目录
一、循环
二、条件
三、handlers
四、失败的处理
一、循环
使用 loop 关键字对一组项目迭代任务,循环变量 item 保存每个迭代过程中使用的值。
[student@workstation ansible]$ vim loop.yml ---
- name: Test loophosts: devgather_facts: novars:num:- one- two- three- four- fivetasks:- name: Echo someshell: "echo This is {{ item }}"loop: "{{ num }}"register: echo_results- name: Loop register vardebug:msg: "{{ item.stdout }}"loop: "{{ echo_results.results }}"
二、条件
when 语句用于有条件地运行任务。它取要测试的条件作为值。如果条件满足, 则运行任务。如果条件不满足,则跳过任务。举例,我们在 webservers 组添加了自定义事实,如果定义了那么安装一下自定义的包,否则跳过。
[student@workstation ansible]$ vim when.yml ---
- name: Install hosts: alltasks:- name: Install db_pkg if db_pkg is definedyum:name: "{{ ansible_facts.ansible_local.myfact.packages.db_pkg }}"state: presentwhen: ansible_facts.ansible_local.myfact is defined[student@workstation ansible]$ ansible-playbook when.yml
......
TASK [Install db_pkg if db_pkg is defined] *************************************************
skipping: [servera.lab.example.com]
skipping: [serverb.lab.example.com]
changed: [serverc.lab.example.com]
changed: [serverd.lab.example.com]
......
三、handlers
Ansible 模块设计为具有幂等性,playbook 及其任务可以运行多次而不会改变受管主机。
handlers 是由其他任务触发的通知的任务。仅当任务在受管主机上被更改,任务才通知handlers。
每个处理程序具有全局唯一的名称,在 playbook 中任务块的末尾触发。
处理程序可视为非活动任务,只有在使用 notify 语句调用时才会被触发。
handlers 在一个 playbook 里面和 tasks 是对齐的。
处理handlers的规范:
- 处理程序始终按照 play 的 handlers 部分指定的顺序运行。它们不按在任务中由 notify 语句列出的顺序运行,或按任务通知它们的顺序运行。
- 处理程序通常在相关 play 中的所有其他任务完成后运行。
- 如果两个处理程序被错误地给予相同的名称,则仅会运行一个。
- 即使有多个任务通知处理程序,该处理程序依然仅运行一次。如果没有任务通知处理程序,它就不会运行。
比如,覆盖 /etc/httpd/conf/httpd.conf 配置文件,使 httpd 监听端口改为 8421。这就需要修改 selinux 端口上下文、重启 httpd 服务、配置防火墙入栈规则。顺序一定是先修改 selinux 端口上下文,再重启 httpd 服务,否则因为 selinux 重启 httpd 会失败。
[student@workstation ansible]$ vim handlers.yml ---
- name: Test handlershosts: webserverstasks:- name: Httpd listen 8421copy:src: httpd.conf.newdest: /etc/httpd/conf/httpd.confnotify: - Allow Apache to listen on tcp port 8421- Restart httpd- Firewall permit 8421/tcphandlers:- name: Allow Apache to listen on tcp port 8421seport:ports: 8421proto: tcpsetype: http_port_tstate: present- name: Restart httpdservice:name: httpdstate: restarted- name: Firewall permit 8421/tcpfirewalld:port: 8421/tcpstate: enabledpermanent: yesimmediate: yes
[student@workstation ansible]$ ansible-playbook handlers.yml......
PLAY [Test handlers] ******************************************TASK [Gathering Facts] ****************************************
ok: [serverc.lab.example.com]
ok: [serverd.lab.example.com]TASK [Httpd listen 8421] **************************************
changed: [serverc.lab.example.com]
changed: [serverd.lab.example.com]RUNNING HANDLER [Allow Apache to listen on tcp port 8421] *****
changed: [serverc.lab.example.com]
changed: [serverd.lab.example.com]RUNNING HANDLER [Restart httpd] *******************************
changed: [serverd.lab.example.com]
changed: [serverc.lab.example.com]RUNNING HANDLER [Firewall permit 8421/tcp] ********************
changed: [serverd.lab.example.com]
changed: [serverc.lab.example.com]
......[student@workstation ansible]$ curl http://serverc.lab.example.com:8421
Added by ansible.
[student@workstation ansible]$ curl http://serverd.lab.example.com:8421
Added by ansible.
四、失败的处理
block-rescue-always 就类似 java 里面的 try-catch-finally 处理方式,block 升级一下,如果失败那么 rescue 一下,无论如何都有收尾工作放在 always里面。比如,webservers 组的两个服务器有 300 ~ 1000MiB 不同大小的卷组 vg_data,我们创建大小为 800MiB 的逻辑卷 lv_web,如果空间不够就创建大小 200MiB 的逻辑卷 lv_web,最后用 xfs 格式创建文件系统。
[student@workstation ansible]$ vim control.yml ---
- name: BlockRescueAlwayshosts: webserversvars:tasks:- name: Create lvmblock:- name: Check 0.8gdebug:msg: "vg_data is less than 0.8g, not enough space"when: ansible_facts.lvm.vgs.vg_data is defined and ansible_facts.lvm.vgs.vg_data.free_g | float < 0.8failed_when: ansible_facts.lvm.vgs.vg_data is defined and ansible_facts.lvm.vgs.vg_data.free_g | float < 0.8- name: Create a logical volume of 0.8glvol:vg: vg_datalv: lv_websize: 800mrescue:- name: Create a logical volume of 0.2glvol:vg: vg_datalv: lv_websize: 0.2galways:- name: Create a xfs filesystemfilesystem:fstype: xfsdev: /dev/vg_data/lv_web
执行过程
[student@workstation ansible]$ ansible-playbook control.yml PLAY [BlockRescueAlways] **********************************************************************TASK [Gathering Facts] ************************************************************************
ok: [serverd.lab.example.com]
ok: [serverc.lab.example.com]TASK [Check 0.8g] *****************************************************************************
fatal: [serverc.lab.example.com]: FAILED! => {"msg": "vg_data is less than 0.8g, not enough space"
}
skipping: [serverd.lab.example.com]TASK [Create a logical volume of 0.8g] ********************************************************
changed: [serverd.lab.example.com]TASK [Create a logical volume of 0.2g] ********************************************************
changed: [serverc.lab.example.com]TASK [Create a xfs filesystem] ****************************************************************
changed: [serverd.lab.example.com]
changed: [serverc.lab.example.com]
.......
检查结果,看到创建 lv_web 的大小是不同的。
[student@workstation ansible]$ ansible webservers -a "lvs"
serverd.lab.example.com | CHANGED | rc=0 >>LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convertroot cl -wi-ao---- <17.00g swap cl -wi-ao---- 2.00g lv_web vg_data -wi-a----- 800.00m
serverc.lab.example.com | CHANGED | rc=0 >>LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convertroot cl -wi-ao---- <17.00g swap cl -wi-ao---- 2.00g lv_web vg_data -wi-a----- 208.00m