playbook适合复杂的环境部署。其实用的语法是yaml。
playbook由一个或多个plays组成,它的内容是以plays为元素的列表。在play中,主机被定义为角色,play的内容被称为task,一个task是对ansible模块的一次调用。
举栗子:
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
这是一个playbook,只包含一个play。
每个play都可以指定主机,执行者身份,和操作内容。
---
- hosts: webservers
remote_user: root
---
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: yourname
---
- hosts: webservers
remote_user: yourname
become:yes
become_method: su
---
- hosts: webservers
remote_user: yourname
tasks:
- service: name=nginx state=started
become: yes
become_method: sudo
---
- hosts: webservers
remote_user: yourname
become: yes
become_user: username
如果需要指定sudo的密码,请使用–ask-become-pass运行ansible-playbook,或者使用旧的sudo语法–ask-sudo-pass(-K)。如果程序卡死,可能是在权限切换部分卡住,执行Ctrl+C打断,检查身份认证的语法再执行。
每个play包含一个task的列表,task按照与主机匹配的模式顺序执行,然后进行下一个task。重要的是要明白,在一个play中,所有的主机都获得了相同的,play的目的是把主机映射到task上。
如果要声明一个 task,以前有一种格式: “action: module options” (可能在一些老的 playbooks 中还能见到).现在推荐使用更常见的格式:”module: options”
tasks:
- name: make sure apache is running
service: name=httpd state=running
tasks:
- name: disable selinux
command: /sbin/setenforce 0
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
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
tasks:
- name: create a virtual host file for {{ vhost }}
template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}
这些变量在 tempates 中也是可用的,稍后会讲到.
在一个基础的 playbook 中,所有的 task 都是在一个 play 中列出,稍后将介绍一种更合理的安排 task 的方式:使用 ‘include:’ 指令.
playbook从上到下执行,如果某个host执行task失败,则会把其从playbook的rotation中去除;如果发生执行失败的情况,则修改playbooks,重新执行。
每个 task 的目标在于执行一个 moudle, 通常是带有特定的参数来执行.在参数中可以使用变量(variables)。
modules 具有”幂等”性,意思是如果你再一次地执行 moudle,moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全。
对于 command module 和 shell module,重复执行 playbook,实际上是重复运行同样的命令.如果执行的命令类似于 ‘chmod’ 或者 ‘setsebool’ 这种命令,这没有任何问题.也可以使用一个叫做 ‘creates’ 的 flag 使得这两个 module 变得具有”幂等”特性 (不是必要的)。
每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的. 如果没有定义 name,‘action’ 的值将会用作输出信息中标记特定的 task.
模块具有幂等性,当远端发生改变时,重复执行playbook可以恢复改动,因为playbook本身识别这种改动,并且有一个系统来响应这种改动。
notify这个动作在每个task末尾被触发,而且就算被多个task触发,也只生效一次。比如说,多个resources表示配置文件改动而需要重启Apache,但是最终Apache只会重启一次。
下面是重启两个服务的例子,但是只有文件更改了才会生效:
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
noitfy下面的列出来的即是handlers
handlers是由全局唯一名称引用的task列表,与常规task完全没有任何区别,并由notifier进行notify,如果没有被notify,handlers将不会执行。在所有task运行完一遍之后,不管有多少个notify,handles只会运行一次。
handlers示例:
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
从ansible2.2开始,处理程序也可以“listen”通用topic,task可以notify该topic:
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"
这将很容易调用多个handlers,也使其名称和handlers分离,从而容易在playbook和roles之间共享handlers。
在介绍role之前,要注意几点:
- 在pre_tasks, tasks, post_tasks 中调用handlers之后,在notify之后就自动刷新handlers。
- 在roles中notify handlers,则在这个task末尾,下一个task之前刷新handlers。
还可以手动刷新handles:
tasks:
- shell: some tasks go here
- meta: flush_handlers
- shell: some other tasks
在上述例子中,任何在等待的handlers将会在meta时提早执行。