聊聊Ansible Playbook中的Handler
Ansible是一个系列文章,我会尽量以通俗易懂、诙谐幽默的总结方式给大家呈现这些枯燥的知识点,让学习变的有趣一些。
Ansible系列博文直达链接:Ansible入门系列
前言
在之前的这篇《初窥Ansible playbook》文章中,有说到这个handler
,细心的朋友可能就对这个handler
很好奇,这到底是个什么东西呢?在Ansible中,我们又是如何使用这个handler
呢?在使用的过程中又有哪些事项需要特别注意的呢?这篇文章我就来对这个handler
进行详细的总结,让大家在日后的工作中能够明明白白、放放心心的使用handler
。
什么是handler
通过这么多年的编程经验,我们知道基本上每个主流的编程框架、语言都有Event机制,Ansible作为自动化运维界最亮的仔,它也不例外,这里要说的handler就是Playbook中的Event。将handler概念映射成Event,这样大家应该就能恍然大悟了。但是在Ansible中,它的handler还有一些特别的地方。
在Playbook中Handlers里面的每一个handler都是对模块的一次调用。而handler与任务不同,任务会默认的按照我们定义的顺序执行,handler则不一样,它需要在任务中被明确调用,才有可能被调用。注意这里的有可能,也就是说也有可能你明确调用了,但是handler也不一定能够被触发调用,这又是为什么呢?且听我慢慢说来!
前面有说到过,任务表中的任务都是有状态的,也就是任务执行后的结果:changed
或者ok
。在Ansible中,只有在任务的执行状态为changed
时,才会执行该任务调用的handler。这也是handler与普通的Event机制不同的地方。
handler应用场景
一个东西存在就必定有它存在的场景,那我们在什么情况下使用handler呢?下面我就来说一个特别现实的场景。
在我们的生产环境中是通过Nginx来做负载均衡的,有的时候我们修改了Nginx的配置文件,然后就需要从Ansible管理主机分发到被管理的Nginx主机上,拷贝成功后,要执行nginx -s reload
命令。在这个操作中有一个前提是必须要配置文件拷贝成功后才能执行nginx -s reload
命令。像这样的应用场景,重启Nginx就可以设计成一个handler。
一个handler最多只执行一次,并且在所有的任务都执行完成之后再执行;如果有多个任务调用同一个handler,那么也只执行一次,这个也是同普通的Event机制的一个不同点。下面通过一个简单的例子来进行说明:
---
- hosts: server1
tasks:
- name: CopyFile1
copy:
src: /home/jelly/file1.log
dest: /home/test1/file1.log
notify:
- handler1
- name: CopyFile2
copy:
src: /home/jelly/file2.log
dest: /home/test1/file2.log
notify:
- handler1
handlers:
- name: handler1
debug: msg="Call handler1"
一开始,在被管理主机上是没有文件的,我们执行上面的YAML脚本,会输出以下日志内容:
[jelly@localhost yaml]$ ansible-playbook handlerDemo1.yaml
PLAY [server1] ***************************************
TASK [Gathering Facts] *******************************
ok: [192.168.1.3]
TASK [CopyFile1] *************************************
changed: [192.168.1.3]
TASK [CopyFile2] *************************************
changed: [192.168.1.3]
RUNNING HANDLER [handler1] ***************************
ok: [192.168.1.3] => {
"msg": "Call handler1"
}
PLAY RECAP *******************************************
192.168.1.3 : ok=4 changed=2 unreachable=0 failed=0
可以看到,handler1只被执行了一次。第一次执行后,文件已经被分发过去了,当我们再次执行这个YAML脚本时,changed状态应该为0,此时handler1就不会被执行。输出日志就是这个样子:
[jelly@localhost yaml]$ ansible-playbook handlerDemo1.yaml
PLAY [server1] ***************************************
TASK [Gathering Facts] *******************************
ok: [192.168.1.3]
TASK [CopyFile1] *************************************
ok: [192.168.1.3]
TASK [CopyFile2] *************************************
ok: [192.168.1.3]
PLAY RECAP *******************************************
192.168.1.3 : ok=3 changed=0 unreachable=0 failed=0
handler执行顺序
除了上面说到的触发场景和执行次数需要我们特殊关注外,还有这里要说的执行顺序,handler的执行顺序也是一个“奇葩”点。
handler是按照定义的顺序执行的,而不是按照在任务中的调用顺序执行的。
上面的话有点绕口,下面我通过一个例子来说明。
---
- hosts: server1
tasks:
- name: CopyFile1
copy:
src: /home/jelly/file1.log
dest: /home/test1/file1.log
notify:
- handler3
- name: CopyFile2
copy:
src: /home/jelly/file2.log
dest: /home/test1/file2.log
notify:
- handler2
- name: CopyFile3
copy:
src: /home/jelly/file3.log
dest: /home/test1/file3.log
notify:
- handler1
handlers:
- name: handler1
debug: msg="Call handler1"
- name: handler2
debug: msg="Call handler2"
- name: handler3
debug: msg="Call handler3"
从上面的YAML脚本可以看到,我们调用handler的顺序是3->2->1
,而在handlers中定义的顺序是1->2->3
,最终handler的执行顺序是1->2->3
,同定义顺序保持一致的。执行输出日志如下:
[jelly@localhost yaml]$ ansible-playbook handlerDemo3.yaml
PLAY [server1] ***************************************
TASK [Gathering Facts] *******************************
ok: [192.168.1.3]
TASK [CopyFile1] *************************************
changed: [192.168.1.3]
TASK [CopyFile2] *************************************
changed: [192.168.1.3]
TASK [CopyFile3] *************************************
changed: [192.168.1.3]
RUNNING HANDLER [handler1] ***************************
ok: [192.168.1.3] => {
"msg": "Call handler1"
}
RUNNING HANDLER [handler2] ***************************
ok: [192.168.1.3] => {
"msg": "Call handler2"
}
RUNNING HANDLER [handler3] ***************************
ok: [192.168.1.3] => {
"msg": "Call handler3"
}
PLAY RECAP *******************************************
192.168.1.3 : ok=7 changed=3 unreachable=0 failed=0
触发场景、执行次数和执行顺序这三个“奇葩”点,大家可得牢牢记住喽!!!
总结
断断续续把这个知识点总结完了,关于Ansible handler这个知识点,别看它看起来很简单,就那么点东西,但是在实际的工作中作用却是非常大的,以后大家在读别人的YAML脚本的时候,就能看到更多handler的应用场景了。还是那句话,小工具,大作为!
果冻想,认真玩技术的地方。
2019年10月6日,于内蒙古呼和浩特。