Ansible 任务控制基本介绍
任务控制类似于编程语言中的 if … 、for … 等逻辑控制语句。
·
Ansible 判断控制
在 Playbook 中,使用 when 进行条件判断控制。
when 支持的运算符如下:
- ==
- !=
- >、 >=
- < 、<=
- is defined
- is not defined
- true
- false
- 支持逻辑运算符: and or
·
示例一:Nginx 启动逻辑欠缺考虑
若 Nginx 的配置文件语法错误则会导致启动 Nginx 失败,以至于 Playbook 执行失败。
---
- name: A simple paly example
hosts: wpf002
tasks:
- name: yum install nginx
yum: name=nginx state=installed
- name: update nginx config
copy: src=nginx.conf dest=/etc/nginx/ backup=yes
- name: add nginx virtualhost config
copy: src=wpf.com.conf dest=/etc/nginx/conf.d/
- name: start nginx
systemd: name=nginx state=started
如果我们能够在启动之前去对 Nginx 的配置文件语法做正确性的校验,只有当校验通过的时候我们才去启动或者重启 Nginx;否则则跳过启动 Nginx 的过程。这样就会避免 Nginx 配置文件语法问题而导致的无法启动 Nginx 的风险。
·
使用注册变量和 debug 模块检测 Nginx 语法
1 获取 Nginx 语法检测结果
---
- name: task control playbook example
hosts: wpf002
tasks:
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
2 通过 debug 模块,打印出结果
---
- name: task control playbook example
hosts: wpf002
tasks:
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
- name: print nginxsyntax
debug: var=nginxsyntax
[root@wpf ~]# ansible-playbook playbook.yml
...
TASK [print nginxsyntax] *************************************************************************************************************
ok: [wpf002] => {
"nginxsyntax": {
"changed": true,
"cmd": "/usr/sbin/nginx -t",
"delta": "0:00:00.015091",
"end": "2021-02-21 21:05:56.557691",
"failed": false,
"rc": 0,
"start": "2021-02-21 21:05:56.542600",
"stderr": "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok\nnginx: configuration file /etc/nginx/nginx.conf test is successful",
"stderr_lines": [
"nginx: the configuration file /etc/nginx/nginx.conf syntax is ok",
"nginx: configuration file /etc/nginx/nginx.conf test is successful"
],
"stdout": "",
"stdout_lines": []
}
}
...
从上面输出内容可以看出,当 nginxsyntax.rc 为 0 时语法校验正确。
3 通过条件判断(when)指令校验 Nginx 的语法
---
- name: task control playbook example
hosts: wpf002
tasks:
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
- name: print nginxsyntax
debug: var=nginxsyntax
- name: start nginx
systemd: name=nginx state=started
when: nginxsyntax.rc == 0
·
示例一最终 Playbook
---
- name: A simple paly example
hosts: wpf002
tasks:
- name: yum install nginx
yum: name=nginx state=installed
- name: update nginx config
copy: src=nginx.conf dest=/etc/nginx/ backup=yes
- name: add nginx virtualhost config
copy: src=wpf.com.conf dest=/etc/nginx/conf.d/
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
- name: start nginx
systemd: name=nginx state=started
when: nginxsyntax.rc == 0
·
Ansible 循环控制
在 Playbook 中使用 with_items 去实现循环控制,且循环时的中间变量(比如:for i in中的 $i 变量)只能是关键字 item ,不能随意自定义。
·
示例二:批量创建用户
通过一个个指令的罗列过于死板。如果再创建若干个用户,将难以收场。
---
- name: A simple paly example
hosts: wpf002
tasks:
- name: create tomcat user
user: name=tomcat state=present
- name: create www user
user: name=www state=present
- name: create mysql user
user: name=mysql state=present
·
示例二最终 Playbook
---
- name: A simple paly example
hosts: wpf002
vars:
createuser:
- tomcat
- www
- mysql
tasks:
- name: create user
user: name="{{ item }}" state=present
with_items: "{{ createuser }}"
·
新版本(loop)循环控制
loop 循环控制 + when 条件判断控制
---
- name: A simple paly example
hosts: wpf002
gather_facts: no
vars:
some_list:
- "a"
- "b"
- "c"
num_list:
- 1
- 2
- 3
- 5
tasks:
- name: show item
debug:
var: "{{ item }}"
loop: "{{ some_list }}"
- name: show item when item > 3
debug:
var: "{{ item }}"
loop: "{{ num_list }}"
when: item > 3
·
Tags 属性
tags 属性可以帮助我们去解决目前 Playbook 变更而导致的扩大变更范围和变更风险的问题。
在我们重复使用一个 Playbook 中的某一个或多个 task 任务的时候,就需要 tags 属性。
示例三:新增属性 tags
使用示例一的例子,比如我们需要对 Nginx 的配置文件进行多次修改。
为"update nginx main config" 和 "add virtualhost config"新增属性 tags,属性值为 updateconfig。
另外我们新增 “reload nginx server” task 任务。当配置文件更新后,去 reload Nginx 服务。
reload Nginx 服务,需要依赖于 Nginx 服务是已经启动状态。所以,还需要进一步通过判断 Nngix 的 pid 文件是否存在。判断一个文件出否存在,可以使用 stat 模块。
·
·
使用 stat 模块判断 nginx.pid 是否存在
---
- name: task control playbook example
hosts: wpf002
tasks:
- name: check nginx running
stat: path=/var/run/nginx.pid
register: nginxrunning
- name: print nginx syntax
debug: var=nginxrunning
[root@wpf ~]# ansible-playbook playbook.yml
...
ok: [wpf002] => {
"nginxrunning": {
"changed": false,
"failed": false,
"stat": {
...
"executable": false,
"exists": true,
"gid": 0,
"gr_name": "root",
...
}
}
}
...
从上面输出内容可以看出,当 nginxrunning.stat.exists 的值是 true 就表示 /var/run/nginx.pid 存在且为文件,就代表 Nginx 正常运行,反之 false 是未运行。
·
示例三最终 Playbook
---
- name: task control playbook example
hosts: wpf002
tasks:
- name: yum install nginx
yum: name=nginx state=installed
- name: update nginx config
copy: src=nginx.conf dest=/etc/nginx/ backup=yes
tags: updateconfig
- name: add nginx virtualhost config
copy: src=wpf.com.conf dest=/etc/nginx/conf.d/
tags: updateconfig
- name: check nginx running
stat: path=/var/run/nginx.pid
register: nginxrunning
tags: updateconfig
- name: print nginxrunning
debug: var=nginxrunning.stat.exists
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
tags: updateconfig
- name: print nginxsyntax
debug: var=nginxsyntax.rc
- name: reload nginx server
systemd: name=nginx state=reloaded
when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == true
tags: updateconfig
- name: start nginx
systemd: name=nginx state=started
when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == false
tags: updateconfig
注意: 使用 stat 模块判断 nginx.pid 是否存在,本身没有问题。但是在这之前,使用了 “/usr/sbin/nginx -t” 来检测 nginx 语法的正确性。当 nginx.pid 不存在时,执行这个命令会生成一个空的 nginx.pid 文件。所以,在后面的 nginxrunning.stat.exists 会一直为 true。所以在判断 nginx.pid 是否存在,应该放在 nginx 语法检测之前。
·
指定 tags 去执行 Playbook
执行时一定要指定 tags,这样再执行的过程中只会执行 task 任务上打上 tags 标记为 updateconfig 的任务
ansible-playbook playbook.yml -t updateconfig
·
Handlers 属性
观察前面的 Playbook,可以发现,当我的配置文件没有发生变化时,每次依然都会去触发 “reload nginx server” 这个任务。如果要实现,只有配置文件发生变化的时候才去触发"reload nginx server" 这个任务,就需要使用 handlers 属性。
在 Playbook 中,使用 notify 调用 Handlers。Handlers 与 task 同级。
·
示例四:Handlers 属性
---
- name: task control playbook example
hosts: wpf002
tasks:
- name: yum install nginx
yum: name=nginx state=installed
- name: update nginx config
copy: src=nginx.conf dest=/etc/nginx/ backup=yes
tags: updateconfig
notify: reload nginx server
- name: add nginx virtualhost config
copy: src=wpf.com.conf dest=/etc/nginx/conf.d/
tags: updateconfig
notify: reload nginx server
- name: check nginx running
stat: path=/var/run/nginx.pid
register: nginxrunning
tags: updateconfig
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
tags: updateconfig
- name: start nginx
systemd: name=nginx state=started
when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == false
tags: updateconfig
handlers:
- name: reload nginx server
systemd: name=nginx state=reloaded
when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == true
tags: updateconfig
我们针对"update nginx main config" 和 “add virtualhost config” 任务增加了新属性 notify, 值为 “reload nginx server”。
它的意思是说,针对这两个任务,设置一个通知机制,当 Ansible 认为文件的内容发生了变化时(文件MD5发生变化了),它就会发送一个通知信号,通知 handlers ,它会根据发送的通知,在 handlers 中相关的任务中寻找名称为"reload nginx server" 的任务。
注意: notify 属性设置的值,一定要确保能和 handlers 中的 task name 对应上。