一 本地执行

如果希望在控制主机本地运行一个特定的任务,可以使用local_action语句。

假设我们需要配置的远程主机刚刚启动,如果我们直接运行playbook,可能会因为sshd服务尚未开始监听而导致失败,我们可以在控制主机上使用如下示例来等待被控端sshd端口监听:

- name: wait for ssh server to be running
wait_for
port: 22
host: "{{ inventory_hostname }}"
search_regex: OpenSSH
connection: local

二 任务委托

在有些时候,我们希望运行与选定的主机或主机组相关联的task,但是这个task又不需要在选定的主机或主机组上执行,而需要在另一台服务器上执行。

这种特性适用于以下场景:

  • 在告警系统中启用基于主机的告警
  • 向负载均衡器中添加或移除一台主机
  • 在dns上添加或修改针对某个主机的解析
  • 在存储节点上创建一个存储以用于主机挂载
  • 使用一个外部程序来检测主机上的服务是否正常

可以使用delegate_to语句来在另一台主机上运行task:

- name: enable alerts for web servers
hosts: webservers
tasks:
- name: enable alerts
nagios: action=enable_alerts service=web host="{{ inventory_hostname }}"
delegate_to: nagios.example.com

三 任务暂停

有些情况下,一些任务的运行需要等待一些状态的恢复,比如某一台主机或者应用刚刚重启,我们需要需要等待它上面的某个端口开启,此时就需要将正在运行的任务暂停,直到其状态满足要求。

Ansible提供了wait_for模块以实现任务暂停的需求

wait_for模块常用参数:

  • connect_timeout:在下一个任务执行之前等待连接的超时时间
  • delay:等待一个端口或者文件或者连接到指定的状态时,默认超时时间为300秒,在这等待的300s的时间里,wait_for模块会一直轮询指定的对象是否到达指定的状态,delay即为多长时间轮询一次状态。
  • host:wait_for模块等待的主机的地址,默认为127.0.0.1
  • port:wait_for模块待待的主机的端口
  • path:文件路径,只有当这个文件存在时,下一任务才开始执行,即等待该文件创建完成
  • state:等待的状态,即等待的文件或端口或者连接状态达到指定的状态时,下一个任务开始执行。当等的对象为端口时,状态有started,stoped,即端口已经监听或者端口已经关闭;当等待的对象为文件时,状态有present或者started,absent,即文件已创建或者删除;当等待的对象为一个连接时,状态有drained,即连接已建立。默认为started
  • timeout:wait_for的等待的超时时间,默认为300秒

示例:

#等待8080端口已正常监听,才开始下一个任务,直到超时
- wait_for:
port: 8080
state: started #等待8000端口正常监听,每隔10s检查一次,直至等待超时
- wait_for:
port: 8000
delay: 10 #等待8000端口直至有连接建立
- wait_for:
host: 0.0.0.0
port: 8000
delay: 10
state: drained #等待8000端口有连接建立,如果连接来自10.2.1.2或者10.2.1.3,则忽略。
- wait_for:
host: 0.0.0.0
port: 8000
state: drained
exclude_hosts: 10.2.1.2,10.2.1.3 #等待/tmp/foo文件已创建
- wait_for:
path: /tmp/foo #等待/tmp/foo文件已创建,而且该文件中需要包含completed字符串
- wait_for:
path: /tmp/foo
search_regex: completed #等待/var/lock/file.lock被删除
- wait_for:
path: /var/lock/file.lock
state: absent #等待指定的进程被销毁
- wait_for:
path: /proc/3466/status
state: absent #等待openssh启动,10s检查一次
- wait_for:
port: 22
host: "{{ ansible_ssh_host | default(inventory_hostname) }}" search_regex: OpenSSH
delay: 10

四 滚动执行

默认情况下,ansible会并行的在所有选定的主机或主机组上执行每一个task,但有的时候,我们会希望能够逐台运行。最典型的例子就是对负载均衡器后面的应用服务器进行更新时。通常来讲,我们会将应用服务器逐台从负载均衡器上摘除,更新,然后再添加回去。我们可以在play中使用serial语句来告诉ansible限制并行执行play的主机数量。

下面是一个在amazon EC2的负载均衡器中移除主机,更新软件包,再添加回负载均衡的配置示例:

- name: upgrade pkgs on servers behind load balancer
hosts: myhosts
serial: 1
tasks:
- name: get the ec2 instance id and elastic load balancer id
ec2_facts: - name: take the host out of the elastic load balancer id
local_action: ec2_elb
args:
instance_id: "{{ ansible_ec2_instance_id }}"
state: absent - name: upgrade pkgs
apt:
update_cache: yes
upgrade: yes - name: put the host back n the elastic load balancer
local_action: ec2_elb
args:
instance_id: "{{ ansible_ec2_instance_id }}"
state: present
ec2_elbs: "{{ items }}"
with_items: ec2_elbs

在上述示例中,serial的值为1,即表示在某一个时间段内,play只在一台主机上执行。如果为2,则同时有2台主机运行play。

一般来讲,当task失败时,ansible会停止执行失败的那台主机上的任务,但是继续对其他 主机执行。在负载均衡的场景中,我们会更希望ansible在所有主机执行失败之前就让play停止,否则很可能会面临所有主机都从负载均衡器上摘除并且都执行失败导致服务不可用的场景。这个时候,我们可以使用serial语句配合max_fail_percentage语句使用。max_fail_percentage表示当最大失败主机的比例达到多少时,ansible就让整个play失败。示例如下:

- name: upgrade pkgs on fservers behind load balancer
hosts: myhosts
serial: 1
max_fail_percentage: 25
tasks:
......

假如负载均衡后面有4台主机,并且有一台主机执行失败,这时ansible还会继续运行,要让Play停止运行,则必须超过25%,所以如果想一台失败就停止执行,我们可以将max_fail_percentage的值设为24。如果我们希望只要有执行失败,就放弃执行,我们可以将max_fail_percentage的值设为0。

五 只执行一次

某些时候,我们希望某个task只执行一次,即使它被绑定到了多个主机上。例如在一个负载均衡器后面有多台应用服务器,我们希望执行一个数据库迁移,只需要在一个应用服务器上执行操作即可。

可以使用run_once语句来处理:

- name: run the database migrateions
command: /opt/run_migrateions
run_once: true

还可以与local_action配合使用,如下:

- name: run the task locally, only once
command: /opt/my-custom-command
connection: local
run_once: true

还可以与delegate_to配合使用,让这个只执行一次的任务在指定的机器上运行:

- name: run the task locally, only once
command: /opt/my-custom-command
run_once: true
delegate_to: app.a1-61-105.dev.unp

六 设置环境变量

我们在命令行下执行某些命令的时候,这些命令可能会需要依赖环境变量。比如在安装某些包的时候,可能需要通过代理才能完成完装。或者某个脚本可能需要调用某个环境变量才能完成运行。

ansible 支持通过environment关键字来定义一些环境变量。

在如下场景中可能需要用到环境变量:

  • 运行shell的时候,需要设置path变量
  • 需要加载一些库,这些库不在系统的标准库路径当中

下面是一个简单示例:

- name: upload a remote file to aws s3
hosts: test
tasks:
- name: install pip
yum:
name: python-pip
state: installed - name: install the aws tools
pip:
name: awscli
state: present - name upload file to s3
shell: aws s3 put-object --bucket=my-test-bucket --key={{ ansible_hostname }}/fstab --body=/etc/fstab --region=eu-west-1
environment:
AWS_ACCESS_KEY_ID: xxxxxx
AWS_SECRET_ACCESS_KEY: xxxxxx

事实上,environment也可以存储在变量当中:

- hosts: all
remote_user: root
vars:
proxy_env:
http_proxy: http://proxy.example.com:8080
https_proxy: http://proxy.bos.example.com:8080
tasks:
- apt: name=cobbler state=installed
environment: proxy_env

七 交互式提示

在少数情况下,ansible任务运行的过程中需要用户输入一些数据,这些数据要么比较秘密不方便,或者数据是动态的,不同的用户有不同的需求,比如输入用户自己的账户和密码或者输入不同的版本号会触发不同的后续操作等。ansible的vars_prompt关键字就是用来处理上述这种与用户交互的情况的。

- hosts: demo2.example.com
remote_user: root
vars_prompt:
- name: share_user
prompt: "what is your network username?"
private: yes - name: share_pass
prompt: "what is your network password"
private: yes tasks:
- debug:
var: share_user
- debug:
var: share_pass

执行

TASK [debug] **************************************************************************************************************************************
ok: [demo2.example.com] => {
"share_user": "abc"
} TASK [debug] **************************************************************************************************************************************
ok: [demo2.example.com] => {
"share_pass": "def"
}

vars_prompt常用选项说明:

  • private: 默认为yes,表示用户输入的值在命令行不可见
  • default:定义默认值,当用户未输入时则使用默认值
  • confirm:如果设置为yes,则会要求用户输入两次,适合输入密码的情况

八 tags标签

在大型项目当中,通常一个playbook会有非常多的task。而我们每次执行这个playbook时,都会将所有task运行一遍。而事实上,在实际使用过程中,我们可能只是想要执行其中的一部分任务而已,并不想把整个playbook完整跑一遍。这个时候就需要用到tags。

通过tags,我们可以给playbook中的某一些任务打上“标签”,而在执行playbook的时候,我们可以通过选定标签的方式指定只执行哪一些任务或者不执行哪一些任务。

8.1 为task打tag

[root@node1 ansible]# vim tag_ex.yml

- name: configure webservers
hosts: demo2.example.com
gather_facts: no
tasks:
- name: Install httpd
yum:
name: httpd
state: present
tags: install_httpd # - name: Cofiguration httpd
# copy:
# src: /root/httpd.conf
# dest: /etc/httpd/conf/httpd.conf
# tags: conf_httpd
# notify:
# - restart httpd - name: Start httpd
service:
name: httpd
state: started
enabled: no
tags: start_httpd - name: restart httpd
service:
name: httpd
state: restarted
tags: restart_httpd handlers:
- name: restart httpd
service: name=httpd state=restart

[root@node1 ansible]# ansible-playbook tag_ex.yml

TASK [Install httpd] ******************************************************************************************************************************
ok: [demo2.example.com] TASK [Start httpd] ********************************************************************************************************************************
ok: [demo2.example.com] TASK [restart httpd] ******************************************************************************************************************************
changed: [demo2.example.com]

8.2 执行一个设定tag

root@node1 ansible]# ansible-playbook tag_ex.yml   --tags="restart_httpd"

8.3 一次指定多个tag执行

[root@node1 ansible]#  ansible-playbook tag_ex.yml --tags="install_httpd,start_httpd"

PLAY [configure webservers] ***********************************************************************************************************************

TASK [Install httpd] ******************************************************************************************************************************
ok: [demo2.example.com] TASK [Start httpd] ********************************************************************************************************************************
ok: [demo2.example.com]

8.4 排除指定tag的task

通过下面的方式可以排除指定了tag的task,即除了指定tag的task不执行,其他task都执行:

[root@node1 ansible]# ansible-playbook --skip-tags="install_httpd" tag_ex.yml

TASK [Start httpd] ********************************************************************************************************************************
ok: [demo2.example.com] TASK [restart httpd] ******************************************************************************************************************************
changed: [demo2.example.com] PLAY RECAP ****************************************************************************************************************************************
demo2.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

8.5 查看playbook中的所有tag

[root@node1 ansible]# ansible-playbook --list-tags tag_ex.yml

playbook: tag_ex.yml

  play #1 (demo2.example.com): configure webservers    TAGS: []
TASK TAGS: [install_httpd, restart_httpd, start_httpd]

8.6 打tag的几种方式

为一个任务指定一个标签

这种方式就是上面示例中的方法:

tags: conf_httpd

为一个任务指定多个标签

可以通过列表的方式为一个任务指定多个标签:

tags:
- install_httpd
- install_web
tags: ['install_httpd','install_web']
tags: install_httpd,install_web

为一个play指定一组标签

当为一个play指定一组标签后,该play下的所有task都会自动继承该标签,各task也可以自定义自己的标签。

- name: configure webservers
hosts: all
remote_user: ansible
tags:
- httpd
tasks:

8.7 ansible内置tag

除了用户自定义tag,ansible也内置了几个tag,这些tag都包含特殊含义:

  • always:一旦某个task被打上了always的tag,则无论是playbook的完整执行,还是指定tag执行,不管你指定的tag是啥,该任务总是会被执行。除非明确指定"--skip-tags=always"选项,才不会执行该task。

  • never:该标签与always正好相反,总是不会执行,除非明确指定"--tags=never"选项。

tagged:在调用时使用

# 所有打了tag的任务都会被执行,包含never tag的除外,没有标签的不会被执行
ansible-playbook --tags tagged install_web.yaml # 所有打了tag的任务都不会被执行,包括always tag也不会被执行
ansible-playbook --skip-tags tagged install_web.yaml

untagged:在调用时使用

# 所有未打tag的任务都会被执行,打了always tag的也会被执行
ansibl-playbook --tags untagged install_web.yaml # 所有未打tag的任务都不会被执行
ansibl-playbook --skip-tags untagged install_web.yaml

all:表示所有任务都会被执行,在默认情况下,不指定任何标签,则使用的就是该标签


参考:https://www.cnblogs.com/breezey/p/10996658.html

012.Ansible高级特性的更多相关文章

  1. paip。java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型

    paip.java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型 作者Attilax 艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http ...

  2. ActiveMQ中的Destination高级特性(一)

    ---------------------------------------------------------------------------------------- Destination ...

  3. Python3学习(二)-递归函数、高级特性、切片

    ##import sys ##sys.setrecursionlimit(1000) ###关键字参数(**关键字参数名) ###与可变参数不同的是,关键字参数可以在调用函数时,传入带有参数名的参数, ...

  4. 云端卫士实战录 | Java高级特性之多线程

    <实战录>导语 一转眼作为一名Java开发者已经四年多时间了,说长不长说短不短,对于java的感情还是比较深的,主要嘛毕竟它给了我饭吃.哈哈,开个玩笑.今天我想借此机会来和大家聊聊Java ...

  5. javascript高级特性

    01_javascript相关内容02_函数_Arguments对象03_函数_变量的作用域04_函数_特殊函数05_闭包_作用域链&闭包06_闭包_循环中的闭包07_对象_定义普通对象08_ ...

  6. Visual Studio 2015 速递(4)——高级特性之移动开发

    系列文章 Visual Studio 2015速递(1)——C#6.0新特性怎么用 Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力) Visual Studi ...

  7. Android TextView高级特性使用

    TextView一般都是用来显示一段文本,这里说的高级特性主要是一些我们平常不太常用的属性.包括文字阴影.自定义字体.html嵌入多格式.字体加粗.插入图片.这些特性平时开发APP的时候,可能一般使用 ...

  8. Python的高级特性8:你真的了解类,对象,实例,方法吗

    Python的高级特性1-7系列是本人从Python2过渡3时写下的一些个人见解(不敢说一定对),接下来的系列主要会以类级为主. 类,对象,实例,方法是几个面向对象的几个基本概念,其实我觉得很多人并不 ...

  9. Python的高级特性7:闭包和装饰器

    本节跟第三节关系密切,最好放在一起来看:python的高级特性3:神奇的__call__与返回函数 一.闭包:闭包不好解释,只能先看下面这个例子: In [23]: def outer(part1): ...

随机推荐

  1. OOJML系列总结

    目录 0x0 JML理论相关 0.0 概念及作用 0.1 JML语法学习 0x1 使用openJml以及JMLUnitNG 1.0 使用openjml 1.1使用JMLUnitNG 0x2 作业架构设 ...

  2. 如何在CSS中映射的鼠标位置,并实现通过鼠标移动控制页面元素效果

    映射鼠标位置或实现拖拽效果,我们可以在 JavaScript 中做到这一点.但实际上,在CSS中有更加简洁的方法,我们可以在不使用JavaScript 的情况下,仍然可以实现相同的功能! 只使用CSS ...

  3. 2. IntelliJ Idea 常用快捷键列表

    Ctrl+E,最近的文件 Ctrl+Shift+E,最近更改的文件 Shift+Click,可以关闭文件 Ctrl+[ OR ],可以跑到大括号的开头与结尾 Ctrl+F12,可以显示当前文件的结构 ...

  4. 火狐兼容selenium版本解决

    火狐和selenium不是很好兼容,下面提供一些我所知道的可以兼容的版本: 1. 火狐52+selenium 3.3 +geckodriver v0.15.0 2.火狐59+selenium 3.11 ...

  5. 《C标准库》学习笔记整理

    简介 <C标准库>书中对 C 标准库中的 15 个头文件的内容进行了详细的介绍,包括各头文件设计的背景知识.头文件中的内容.头文件中定义的函数和变量的使用.实现.测试等. 我学习此书的目的 ...

  6. VUE+Element 前端应用开发框架功能介绍

    前面介绍了很多ABP系列的文章<ABP框架使用>,一步一步的把我们日常开发中涉及到的Web API服务构建.登录日志和操作审计日志.字典管理模块.省份城市的信息维护.权限管理模块中的组织机 ...

  7. 1053 Path of Equal Weight

    Given a non-empty tree with root R, and with weight W​i​​ assigned to each tree node T​i​​. The weig ...

  8. 1002 A+B for Polynomials (25分)

    This time, you are supposed to find A+B where A and B are two polynomials. Input Specification: Each ...

  9. ASP.NET Core五种Filter

    Authorization Filter Authorization是五种Filter中优先级最高的,通常用于验证Request合不合法,不合法后面就直接跳过. 权限控制器过滤器,可以通过Authon ...

  10. 100多个很有用的JavaScript函数以及基础写法大集合

    100多个很有用的JavaScript函数以及基础写法大集合 1.document.write("");为 输出语句2.JS中的注释为//3.传统的HTML文档顺序是:docume ...