预计阅读本页时间:-
4.5 playbook介绍
playbook是一个不同于Ansible命令行执行方式的模式,其功能更为强大灵活。简而言之,它是一个非常简单的配置管理和多主机部署系统。playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归为一组的主机装扮成通过Ansible中的task事先定义好的角色。从根本上来讲,所谓的task就是调用Ansible的一个个模块将多个play组织在一个playbook中,这样就可以让它们联通起来按事先编排的机制同唱一台大戏。
playbook的模板是使用Python的jinja2模块来处理的。学习过Saltstack的朋友对此模板应该是比较熟悉的。另外,playbook也是通过YAML格式来进行描述定义的,可以实现多台主机的应用部署,语法也并不复杂,大家可以对应官方案例学习其语法,官方网站提供了大量的案例,其地址为https://github.com/ansible/ansible-examples 。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
下面先来看一下Ansible官方网站的一个案例,以举例说明playbook的用法。
#选择的主机组
- hosts: webserver
#定义的变量
vars:
user: www
group: www
maxclients: 2000
DocumentRoot: /var/www/html
#远端的执行权限
remote_user: root
#task是定义任务列表
tasks:
#利用
yum模块来操作
- name: ensure apache is at the latest version
#建议每个任务事件都要定义一个
name标签,这样做既增强了可读性,又便于观察结果输出。
yum: pkg=httpd state=latest
- name: Apache Config File
template: src=/home/yhc/apache/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
#src为
Ansible主控端模块存放位置,
dest为被控端
httpd配置文件位置
#触发重启服务器
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
#这里的
restart apache 和上面的触发是配对的
,这就是
handlers(处理程序)的作用。
handlers:
- name: restart apache
service: name=httpd state=restarted
模板文件/home/yhc/apache/httpd.conf.j2可参考官方案例,建议以j2结尾,表明这是一个经过jinja2模板渲染的文件,并且存放在名为templates的子目录中。
定义的变量最好跟模板文件/home/yhc/apache/httpd.conf.j2中的变量一一对应,不然后面执行ansible-playbook时会报错,由于模板文件内容太长,这里只摘录跟变量相对应的内容,如下:
User {{ user}}
Group {{ group}}
DocumentRoot "{{DocumentRoot}}"
MaxClients {{maxclients}}
语法简单明了,YAML文件中的变量以“{{变量名}}”表示,该文件若写得过于复杂,就会有语法错误的问题,可以采用如下方式检查语法错误:
ansible-playbook /home/yhc/httpd.yml --list-hosts --list-tasks
playbook: /home/yhc/httpd.yaml
play #1 (webserver): host count=2
192.168.1.205
192.168.1.206
play #1 (webserver): TAGS: []
ensure apache is at the latest version TAGS: []
write the apache config file TAGS: []
ensure apache is running TAGS: []
执行我们预先写好的YAML文件,路径为/home/yhc/httpd.yml,命令如下:
ansible-book /home/yhc/httpd.yml -f 10
显示结果如下所示:
PLAY [webserver] **************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.205]
ok: [192.168.1.206]
TASK: [ensure apache is at the latest version] ********************************
ok: [192.168.1.206]
ok: [192.168.1.205]
TASK: [write the apache config file] ******************************************
changed: [192.168.1.205]
changed: [192.168.1.206]
TASK: [ensure apache is running] **********************************************
ok: [192.168.1.205]
ok: [192.168.1.206]
NOTIFIED: [restart apache] ****************************************************
changed: [192.168.1.205]
changed: [192.168.1.206]
PLAY RECAP ********************************************************************
192.168.1.205 : ok=5 changed=2 unreachable=0 failed=0
192.168.1.206 : ok=5 changed=2 unreachable=0 failed=0
ansible-playbook后面紧跟着的就是我们所写的/home/yhc/httpd.yml文件,它的默认并行进程数为5,可以带上参数-f 10或更大的数值以提高并行进程数。
playbook文件的详细说明
(1)定义主机和用户
每份playbook文件都需要指定针对哪些主机进行运维,而hosts变量则说明了这个问题,users则说明了采用哪个用户执行这条命令。
针对webserver主机组,这里采用root用户执行命令,代码如下:
---
- hosts: webservers
remote_user: root
如果是AWS EC2主机,可以采用sudo模式执行命令,代码如下:
---
- hosts: webservers
remote_user: ec2-user
sudo: yes
(2)任务列表
每一个playbook都会有一份任务列表(tasks list),说明究竟要按照怎样的顺序去执行这些命令(从上至下,依照顺序执行task)。
使用service模块的命令如下:
tasks:
- name: make sure apache is running
service: name=httpd state=running
使用command模块的命令如下:
tasks:
- name: disable selinux
command: /sbin/setenforce 0
使用shell模块的命令如下:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
使用copy模块的命令如下:
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
使用template模块的命令如下:
tasks:
- name: create a virtual host file for {{ vhost }}
template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}
(3)handlers
当被控端主机配置文件发生变化以后,通知处理程序handlers来触发后续的动作,比如重启Apache服务。在没有通知触发时handlers中定义的处理程序是不会执行的,触发是通过handlers定义的name标签来识别的,比如下面的notify中的“restart apache”和handlers中的“name:restart apache”内容请保持一致。
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
下面简单介绍下playbook的条件语句与循环,语法非常简单,直接通过示例即可说明。
条件语句when的示例如下:
tasks:
- name: reboot redhat host
command: /usr/sbin/reboot
when: ansible_os_family == "RedHat"
循环语句的示例如下:
tasks:
- name: install LNMP
yum: name={{ item }} state=present
with_items:
- nginx
- mysql-server
- php-fpm
循环还支持列表,使用的是with_flattened语句。
变量文件的示例如下:
---
packages_LNMP:
- [ 'nginx', 'mysql-server', 'php-fpm' ]引用
- name: Install LNMP
yum: name={{ item }} state=present
with_flattened:
- packages_LNMP
关于playbook文件的更多说明可参考文档http://docs.ansible.com/playbooks_roles.html 。
工作中经常会有这样一个需求:被控机上有3个用户(yhc、admin和readonly),分别对应3套公私钥(分别对应不同的权限),需要用Ansible主控端进行公钥推送。这时,ssh-copy-id.yml文件如下所示:
# Using alternate directory locations:
- hosts: webserver
user: root
tasks:
- name: ensure users is present
user: name={{ item }} state=present
with_items:
- yhc
- admin
- readonly
- name: ssh-copy-id user yhc
authorized_key: user=yhc key='{{ lookup('file', '/home/yhc/ansible/ssh-copy-id/example-master.pub') }}'
- name: ssh-copy-id user admin
authorized_key: user=admin key='{{ lookup('file', '/home/yhc/ansible/ssh-copy-id/example-operation.pub') }}'
- name: ssh-copy-id user readonly
authorized_key: user=readonly key='{{ lookup('file', '/home/yhc/ansible/ssh-copy-id/example-readonly.pub') }}'
authorized_key是Ansible官方新出的一个模块,作用为添加或删除用户SSH公钥(adds or removes an SSH authorized key),这里主要用于添加用户公钥,详细说明请参见:http://docs.ansible.com/ansible/authorized_key_module.html 。
如果Ansible部署在AWS EC2主机上,则默认是不允许root进行SSH的,并且root不提供密码,因此这里需要用一个有sudo权限的用户来执行,默认用户一般是ec2-user。
需要注意的是,这里的公钥文件全部都在Ansible主控机器的/home/yhc/ansible/ssh-copy-id目录下,而且不必担心被控机器端的.ssh目录是否建立、authorized文件权限是否为600等,这些全部由authorized_key模块全自动完成,是不是很人性化呢?
此时的ssh-copy-id文件调整如下:
- hosts: bidder
user: ec2-user
sudo: yes
tasks:
- name: ensure users is present
user: name={{ item }} state=present
with_items:
- bilin
- readonly
sudo:yes
- name:ssh-copy-id user bilin
authorized_key: user=bilin key='{{ lookup('file', '/home/yhc/ansible/ssh-copy-id/example-operation.pub') }}'
- name:ssh-copy-id user readonly
authorized_key: user=readonly key='{{ lookup('file', '/home/yhc/ansible/ssh-copy-id/example-readonly.pub') }}'
可用如下命令执行ssh-copy-id.yml文件,如下所示:
ansible-playbook -i hosts ssh-copy-id.yml
在被控端机器上进行检查,可发现公钥都已经正确分发了,而且权限自动地分配成了600权限,在主控端上切换相应的用户,SSH登录也是正常的,说明整个配置过程是没有问题的。