1.Playbook Handlers概述
Playbook Handlers(处理程序)是Ansible Playbook中的一种特殊类型的任务。处理程序通常用于在Playbook的最后阶段执行特定操作。
处理程序的定义通常位于Playbook的顶层结构中,使用handlers关键字。处理程序可以与任务关联起来,以便在任务执行后触发执行。当一个或多个任务通知(notify)处理程序时,处理程序将在Playbook的最后执行。
处理程序的主要特点如下:
触发条件:处理程序只有在至少一个任务通知(notify)它时才会执行。任务通知处理程序的方式是通过在任务中使用notify关键字并指定处理程序的名称。
顺序执行:处理程序的执行顺序与它们在Playbook中的定义顺序一致。如果多个任务通知同一个处理程序,处理程序将按照它们在Playbook中定义的顺序执行。
一次执行:处理程序只会执行一次,即使多个任务通知它。这意味着如果多个任务通知同一个处理程序,处理程序只会执行一次。
模块支持:处理程序可以使用Ansible支持的各种模块执行不同的操作,例如服务管理、文件操作、包管理等。
通过使用处理程序,您可以在Playbook中定义一系列的任务,并在需要时执行特定的操作。这使得Playbook更加灵活和可扩展,可以根据需要自动执行额外的操作。处理程序在管理和维护系统时非常有用,可以在任务完成后执行重启服务、重新加载配置文件等操作。
2.Playbook Handlers使用场景
Playbook Handlers(处理程序)在以下场景中非常有用:
服务重启:当某个任务修改了系统配置或文件时,您可以使用处理程序在任务完成后重启相关的服务,以使更改生效。
配置文件重新加载:当某个任务修改了配置文件时,您可以使用处理程序在任务完成后重新加载相关的配置文件,以使更改生效。
通知其他系统:当某个任务完成后,您可以使用处理程序触发通知操作,例如向监控系统发送通知、发送电子邮件等。
状态检查和修复:当某个任务完成后,您可以使用处理程序检查系统状态,并在需要时执行修复操作,例如重新启动服务、修复文件权限等。
部署后操作:在部署过程中,您可以使用处理程序在所有任务完成后执行一些清理操作,例如删除临时文件、重启服务等。
多个任务的聚合操作:如果有多个任务需要执行相同的操作或触发相同的事件,您可以使用处理程序将这些任务关联起来,并在任务完成后执行一次操作,以避免重复代码。
总的来说,处理程序可以在任务完成后执行一些额外的操作,从而增加Playbook的灵活性和可扩展性。您可以根据需要定义多个处理程序,并将它们与任务关联起来,以实现自动化操作的复杂逻辑。处理程序在管理和维护系统时非常有用,可以在任务完成后执行重启服务、重新加载配置文件等操作。
3.handlers注意事项
处理程序的定义:在Playbook中定义处理程序时,确保它们的名称是唯一的,并且与任务的通知名称匹配。处理程序的名称应以handler_开头,以便与其他任务和变量区分开来。
任务通知:确保在需要触发处理程序的任务中使用正确的notify关键字,并指定处理程序的名称。任务通知的名称应与处理程序的名称匹配。
处理程序的顺序:处理程序的执行顺序与它们在Playbook中的定义顺序一致。如果多个任务通知同一个处理程序,处理程序将按照它们在Playbook中定义的顺序执行。因此,确保处理程序的定义顺序符合您的预期。
多个任务通知:如果多个任务通知同一个处理程序,处理程序只会执行一次。这意味着如果您希望处理程序执行多次,确保多个任务都通知了该处理程序。
处理程序的执行时机:处理程序只有在至少一个任务通知时才会执行。因此,确保至少有一个任务通知了处理程序,否则处理程序将不会执行。
处理程序的条件:您可以使用条件语句来控制处理程序的执行。例如,您可以在处理程序中使用when关键字来指定满足特定条件时才执行处理程序。
处理程序的功能:处理程序通常用于在任务完成后执行一些额外的操作,例如重启服务、重新加载配置文件等。确保处理程序的功能与您的需求一致,并在处理程序中使用适当的模块和参数。
错误处理:如果处理程序执行失败,Ansible将继续执行后续的任务和处理程序。如果您希望在处理程序失败时中止Playbook的执行,可以使用failed_when关键字来定义处理程序的失败条件。
4.Playbook Handlers
部署nginx服务
剧本
[root@ansible /server/playbook]$ cat 16Handlers-nginx.yml --- - hosts: web vars: http_port: 8080 tasks: #配置nginx yum源 - name: nginx Repo yum_repository: name: nginx description: nginx repo baseurl: http://nginx.org/packages/centos/$releasever/$basearch/ enabled: yes gpgcheck: yes gpgkey: https://nginx.org/keys/nginx_signing.key #安装nginx - name: install nginx yum: name: nginx state: installed #创建静态页面 - name: file copy: content: "ansible.playbook.com" dest: /usr/share/nginx/html/index.html #推送配置文件 - name: copy nginx template: src: ./www.ansible.com.conf dest: /etc/nginx/conf.d/www.ansible.com.conf backup: yes #监控配置文件,如果发生了变化,重新推送.并且触发 notify: Restart Nginx #安装完成后启动nginx - name: state nginx systemd: name: nginx state: started enabled: yes #配置notify触发后,具体做什么 handlers: - name: Restart Nginx systemd: name: nginx state: reloaded
[root@ansible /server/playbook]$ ansible-playbook 16Handlers-nginx.yml PLAY [web] ******************************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************************** ok: [172.16.1.145] ok: [172.16.1.45] TASK [nginx Repo] ************************************************************************************************************* ok: [172.16.1.145] ok: [172.16.1.45] TASK [install nginx] ********************************************************************************************************** ok: [172.16.1.145] ok: [172.16.1.45] TASK [file] ******************************************************************************************************************* ok: [172.16.1.45] ok: [172.16.1.145] TASK [copy nginx] ************************************************************************************************************* changed: [172.16.1.45] changed: [172.16.1.145] TASK [state nginx] ************************************************************************************************************ changed: [172.16.1.45] changed: [172.16.1.145] RUNNING HANDLER [Restart Nginx] *********************************************************************************************** changed: [172.16.1.145] changed: [172.16.1.45] PLAY RECAP ******************************************************************************************************************** 172.16.1.145 : ok=7 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.45 : ok=7 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
配置文件
[root@ansible /server/playbook]$ cat www.ansible.com.conf server { listen {{ http_port }}; server_name www.ansible.com; location / { root /usr/share/nginx/html/; index index.html index.php; } }
5.Playbook任务标签
在Ansible Playbook中,您可以为任务(tasks)添加标签(tags),以便在执行Playbook时选择性地运行特定的任务。标签可以帮助您在大型Playbook中组织和控制任务的执行。
以下是在Playbook中使用任务标签的一般步骤:
为任务添加标签:在任务定义中,使用tags关键字为任务添加一个或多个标签。标签可以是任何您选择的名称,用空格分隔多个标签。
- name: Install and configure web server yum: name: httpd state: present tags: - install - configure
运行具有特定标签的任务:当运行Playbook时,您可以使用–tags参数指定要运行的任务标签。只有具有指定标签的任务将被执行。
ansible-playbook playbook.yml --tags "install"
上述命令将只运行具有”install”标签的任务。
排除具有特定标签的任务:您还可以使用–skip-tags参数指定要跳过执行的任务标签。具有指定标签的任务将被跳过。
ansible-playbook playbook.yml --skip-tags "configure"
上述命令将跳过具有”configure”标签的任务。
运行具有多个标签的任务:您可以使用逗号分隔多个标签,以运行具有多个标签的任务。
ansible-playbook playbook.yml --tags "install,configure"
上述命令将只运行具有”install”和”configure”标签的任务。
通过使用任务标签,您可以灵活地选择性地运行和跳过特定的任务,以满足您的需求。标签还可以在Playbook中的其他地方使用,例如在角色(roles)中或在包含(include)语句中。这使得您可以在更大规模的自动化环境中更好地组织和控制任务的执行。
使用-t指定tags执行
剧本
[root@ansible /server/playbook]$ cat 17Handlers-nginx-tags.yml --- - hosts: web vars: http_port: 2345 tasks: #配置nginx yum源 - name: nginx Repo yum_repository: name: nginx description: nginx repo baseurl: http://nginx.org/packages/centos/$releasever/$basearch/ enabled: yes gpgcheck: yes gpgkey: https://nginx.org/keys/nginx_signing.key #安装nginx - name: install nginx yum: name: nginx state: installed #创建静态页面 - name: file copy: content: "ansible.playbook.com" dest: /usr/share/nginx/html/index.html #推送配置文件 - name: copy nginx template: src: ./www.ansible.com.conf dest: /etc/nginx/conf.d/www.ansible.com.conf backup: yes tags: - config_file #监控配置文件,如果发生了变化,重新推送.并且触发 notify: Restart Nginx #安装完成后启动nginx - name: state nginx systemd: name: nginx state: started enabled: yes #配置notify触发后,具体做什么 handlers: - name: Restart Nginx systemd: name: nginx state: reloaded
[root@ansible /server/playbook]$ ansible-playbook 17Handlers-nginx-tags.yml -t config_file PLAY [web] ******************************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************************** ok: [172.16.1.45] ok: [172.16.1.145] TASK [copy nginx] ************************************************************************************************************* changed: [172.16.1.145] changed: [172.16.1.45] RUNNING HANDLER [Restart Nginx] *********************************************************************************************** changed: [172.16.1.145] changed: [172.16.1.45] PLAY RECAP ******************************************************************************************************************** 172.16.1.145 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.45 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
使用-t指定tags执行, 多个tags使用逗号隔开即可
[root@ansible /server/playbook]$ ansible-playbook 17Handlers-nginx-tags.yml -t config_file,yuan_nginx PLAY [web] ******************************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************************** ok: [172.16.1.45] ok: [172.16.1.145] TASK [nginx Repo] ************************************************************************************************************* ok: [172.16.1.45] ok: [172.16.1.145] TASK [copy nginx] ************************************************************************************************************* ok: [172.16.1.145] ok: [172.16.1.45] PLAY RECAP ******************************************************************************************************************** 172.16.1.145 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.45 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
使用–skip-tags排除不执行的tags
[root@ansible /server/playbook]$ ansible-playbook 17Handlers-nginx-tags.yml --skip-tags yuan_nginx PLAY [web] ******************************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************************** ok: [172.16.1.145] ok: [172.16.1.45] TASK [install nginx] ********************************************************************************************************** ok: [172.16.1.145] ok: [172.16.1.45] TASK [file] ******************************************************************************************************************* ok: [172.16.1.45] ok: [172.16.1.145] TASK [copy nginx] ************************************************************************************************************* ok: [172.16.1.45] ok: [172.16.1.145] TASK [state nginx] ************************************************************************************************************ ok: [172.16.1.45] ok: [172.16.1.145] PLAY RECAP ******************************************************************************************************************** 172.16.1.145 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.45 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
查看标签
[root@ansible /server/playbook]$ ansible-playbook 17Handlers-nginx-tags.yml --list-tags playbook: 17Handlers-nginx-tags.yml play #1 (web): web TAGS: [] TASK TAGS: [config_file, yuan_nginx]
6.Playbook文件复用
在Ansible中,您可以通过多种方式复用Playbook文件,以便在不同的场景中重复使用相同的任务和配置。
以下是一些常用的方法来实现Playbook文件的复用:
包含(Include)语句:使用include语句可以将一个Playbook文件包含到另一个Playbook文件中。这样可以复用一个或多个任务,而无需重复编写它们。例如,您可以创建一个通用的基础Playbook文件,然后在其他Playbook文件中包含它。
# base.yml - name: Install packages yum: name: "{{ item }}" state: present with_items: - package1 - package2 # playbook.yml - hosts: servers tasks: - include: base.yml
角色(Roles):角色是一种组织和复用任务的机制。您可以将一组相关的任务和配置封装到一个角色中,并在多个Playbook文件中使用该角色。这样可以使Playbook更具模块化和可维护性。
ansible-galaxy init myrole
创建角色后,您可以在Playbook文件中使用roles关键字来引用该角色。
- hosts: servers roles: - myrole
变量文件(Variable Files):您可以将变量定义保存在单独的文件中,并在多个Playbook文件中引用这些变量文件。这样可以避免在每个Playbook文件中重复定义相同的变量。
# vars.yml my_variable: "value" # playbook.yml - hosts: servers vars_files: - vars.yml tasks: - name: Print variable debug: var: my_variable
模板(Template):使用模板可以根据不同的变量值生成不同的配置文件。您可以创建一个通用的模板文件,并在多个Playbook文件中使用不同的变量值来生成不同的配置文件。
# template.j2 server_name: {{ server_name }} # playbook.yml - hosts: servers vars: server_name: example.com tasks: - name: Generate config file template: src: template.j2 dest: /etc/myapp/config.conf
通过使用这些方法,您可以更好地组织和复用Ansible Playbook文件,减少重复工作,并提高自动化的可维护性和灵活性。
include 和 import区别
在Ansible中,include和import是两种不同的语句,用于包含其他Playbook文件或任务。
Include语句 (include) 是一种简单的包含机制,它将指定的Playbook文件内容直接嵌入到当前Playbook文件中。在运行时,Ansible会将被包含的Playbook文件中的任务和配置合并到当前Playbook文件中,就像它们是在同一个文件中定义的一样。使用include语句时,被包含的文件可以使用当前文件中定义的变量和任务。
# playbook.yml - hosts: servers tasks: - include: tasks.yml
Import语句 (import) 是一种更强大和灵活的包含机制。与include不同,import语句不仅仅是简单地将被导入的Playbook文件内容嵌入到当前文件中,而是将其作为一个独立的、可重用的模块进行处理。被导入的Playbook文件可以包含变量、任务和处理逻辑,但它们在导入时不会立即执行。相反,导入的Playbook文件可以在需要时通过import_tasks或include_tasks语句进行调用。
# playbook.yml - hosts: servers tasks: - import_tasks: tasks.yml
import语句还可以使用vars和vars_prompt关键字来定义变量,这些变量将在导入时被传递给导入的Playbook文件。
总结来说,include语句是一种简单的包含机制,将被包含的Playbook文件内容直接嵌入到当前文件中。而import语句是一种更灵活和可重用的包含机制,被导入的Playbook文件可以作为一个独立的模块进行调用。选择使用哪种语句取决于您的需求和使用场景。
include调用任务方式
剧本
[root@ansible /server/playbook]$ cat 18include-tasks.yml --- - hosts: all tasks: - include_tasks: 1801-basic.yml - include_tasks: 1802-install-web.yml [root@ansible /server/playbook]$ cat 1801-basic.yml - name: youhua debug: msg: - "所有的ip地址 {{ ansible_all_ipv4_addresses }}" - "默认的ip地址 {{ ansible_default_ipv4.address }}" - "you interface is {{ ansible_default_ipv4.interface }}" - "time is {{ ansible_date_time.date }}" - "mem total is {{ ansible_memtotal_mb }}" - "you system is {{ ansible_distribution }} version is {{ ansible_distribution_version }}" [root@ansible /server/playbook]$ cat 1802-install-web.yml - name: install web debug: msg: - "installing web servers nginx..............." - "installing web servers php..............." - "installing web servers nfs..............." when: (ansible_hostname is match("web"))
[root@ansible /server/playbook]$ ansible-playbook 18include-tasks.yml PLAY [all] ******************************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************************** ok: [172.16.1.145] ok: [172.16.1.78] ok: [172.16.1.45] ok: [172.16.1.121] fatal: [172.16.1.163]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.16.1.163 port 22: No route to host", "unreachable": true} fatal: [172.16.1.116]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.16.1.116 port 22: No route to host", "unreachable": true} TASK [include_tasks] ********************************************************************************************************** included: /server/playbook/1801-basic.yml for 172.16.1.45, 172.16.1.145, 172.16.1.78, 172.16.1.121 TASK [youhua] ***************************************************************************************************************** ok: [172.16.1.45] => { "msg": [ "所有的ip地址 [u'10.0.0.45', u'172.16.1.45']", "默认的ip地址 10.0.0.45", "you interface is eth0", "time is 2023-08-18", "mem total is 1819", "you system is CentOS version is 7.8" ] } ok: [172.16.1.145] => { "msg": [ "所有的ip地址 [u'172.16.1.145', u'10.0.0.145']", "默认的ip地址 10.0.0.145", "you interface is eth0", "time is 2023-08-18", "mem total is 1819", "you system is CentOS version is 7.8" ] } ok: [172.16.1.78] => { "msg": [ "所有的ip地址 [u'172.16.1.78', u'10.0.0.78']", "默认的ip地址 10.0.0.78", "you interface is eth0", "time is 2023-08-18", "mem total is 1819", "you system is CentOS version is 7.8" ] } ok: [172.16.1.121] => { "msg": [ "所有的ip地址 [u'172.16.1.121', u'10.0.0.121']", "默认的ip地址 10.0.0.121", "you interface is ens33", "time is 2023-08-18", "mem total is 3906", "you system is Ubuntu version is 20.04" ] } TASK [include_tasks] ********************************************************************************************************** included: /server/playbook/1802-install-web.yml for 172.16.1.45, 172.16.1.145, 172.16.1.78, 172.16.1.121 TASK [install web] ************************************************************************************************************ ok: [172.16.1.45] => { "msg": [ "installing web servers nginx...............", "installing web servers php...............", "installing web servers nfs..............." ] } ok: [172.16.1.145] => { "msg": [ "installing web servers nginx...............", "installing web servers php...............", "installing web servers nfs..............." ] } skipping: [172.16.1.78] skipping: [172.16.1.121] PLAY RECAP ******************************************************************************************************************** 172.16.1.116 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.121 : ok=4 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 172.16.1.145 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.163 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.45 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.78 : ok=4 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
7.Playbook忽略错误
在Ansible Playbook中,您可以使用ignore_errors参数来忽略特定任务的错误。当设置为yes时,如果任务失败,Ansible将继续执行后续的任务而不会中止Playbook的执行。
以下是一个示例:
- hosts: servers tasks: - name: Task 1 command: /path/to/command1 ignore_errors: yes - name: Task 2 command: /path/to/command2
在上面的示例中,如果Task 1执行失败,Ansible将忽略错误并继续执行Task 2。如果您不设置ignore_errors参数,当任务失败时,Ansible将中止Playbook的执行。
请注意,ignore_errors只适用于单个任务。如果您希望忽略所有任务的错误,可以在Playbook级别设置ignore_errors为yes。
- hosts: servers ignore_errors: yes tasks: - name: Task 1 command: /path/to/command1 - name: Task 2 command: /path/to/command2
在上面的示例中,无论Task 1或Task 2是否失败,Ansible都将忽略错误并继续执行Playbook中的其他任务。
当有task执行失败则会立即终止后续task运行
剧本
[root@ansible /server/playbook]$ cat 19ignore_errors.yml --- - hosts: al tasks: - name: Ignore False command: /bin/false ignore_errors: yes - name: touch file file: path: /dmxsp/devil state: touch
[root@ansible /server/playbook]$ ansible-playbook 19ignore_errors.yml PLAY [al] ********************************************************************************************************************* TASK [Gathering Facts] ******************************************************************************************************** ok: [172.16.1.78] TASK [Ignore False] *********************************************************************************************************** fatal: [172.16.1.78]: FAILED! => {"changed": true, "cmd": ["/bin/false"], "delta": "0:00:00.002670", "end": "2023-08-18 01:51:44.863125", "msg": "non-zero return code", "rc": 1, "start": "2023-08-18 01:51:44.860455", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []} ...ignoring TASK [touch file] ************************************************************************************************************* changed: [172.16.1.78] PLAY RECAP ******************************************************************************************************************** 172.16.1.78 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
查看
[root@all ~]$ ll /dmxsp/ total 0 -rw-r--r-- 1 root root 0 Aug 18 01:51 devil