03. playbooks
一个 playbooks 可以包含多个 play:
---
- hosts: webservers
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
- hosts: databases
remote_user: root
tasks:
- name: ensure postgresql is at the latest version
yum:
name: postgresql
state: latest
- name: ensure that postgresql is started
service:
name: postgresql
state: started
1. 基础⚓
1.1 Hosts and Users⚓
---
- hosts: webservers
remote_user: root
-
hosts 的语法,以冒号分隔多个主机。
-
remote_user 指定登录到远程主机的账户(同时是默认的执行任务的账户)。
还支持指定其他帐户执行 (Understanding privilege escalation: become)(在 play 或 task 级别):
---
- hosts: webservers
remote_user: yourname
become: yes
become_user: apache
1.1.1 order⚓
在 2.4 及之后,还可以指定主机的执行顺序。
- hosts: all
order: sorted
可选的值有以下几种:
- inventory:默认值,按照 inventory 提供的顺序执行
- reverse_inventory
- sorted:主机按名称的字母顺序排列
- reverse_sorted
- shuffle
1.2 Tasks list⚓
任务是按序执行的。当执行 playbook 的时候,任务失败的主机将从整个 playbook 的轮换中删除。
任务都是通过模块来执行的。并且模块应该是幂等的,即在一个序列中多次运行一个模块应该与仅运行一次具有相同的效果。
大部分模块的参数都是通过 key=value
的方式指定的:
tasks:
- name: make sure apache is running
service:
name: httpd
state: started
command 和 shell 是唯一使用参数列表的模块:
tasks:
- name: enable selinux
command: /sbin/setenforce 1
并且它们关心退出码,若命令成功执行的退出码非零,那么可以这样写:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
2. Handlers⚓
当 task 执行的执行结果是 changed
时, notify
动作会触发其他的 tasks,这些 tasks 就是 handler。
这些 notify
动作是在 play 中每个任务块的结尾处触发的,即使被多个不同的任务通知,也只会触发一次(因为模块的幂等性)。
tasks:
- name: template configuration file
template:
src: template.j2
dest: /etc/foo.conf
notify:
- restart memcached
- restart apache
handlers:
- name: restart memcached
service:
name: memcached
state: restarted
- name: restart apache
service:
name: apache
state: restarted
注意:因为 handler 的 name 是模板化的,不要在 handler 的名字中使用变量!
从 Ansible 2.2 开始, handler 还可以 listen
通用 topic,task 可以像下面这样通知这些 topics:
handlers:
- name: restart memcached
service:
name: memcached
state: restarted
listen: "restart web services"
- name: restart apache
service:
name: apache
state: restarted
listen: "restart web services"
tasks:
- name: restart everything
command: echo "this task will restart the web services"
notify: "restart web services"
仔细看,"restart web services" 并没有指向任何一个 handler ,它只是被 handler 监听,在通知时触发这些 handler。
Note
- handler 的执行顺序是定义时的顺序,而不是被通知的顺序;
- handler 的 name 与 listen topics 的作用域是全局的;
- handler 的 name 是模板化的,listen topics 不是;
- 为每个 handler 定义唯一的 name,否则只会执行最后一个被定义的 handler ;
- 在 Ansible 2.2 以前,不能通知被引入(include)的 handler;从 Ansible 2.2 开始, 可以这样使用,但必须是静态引入。