在介绍playbook之前,我们先了解一下YAML语言,因为playbook是用YAML语言编写的
一、YAML
1、YAML是一种可读性高的用来表达资料序列的语言,其语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。所有的yaml文件都以---
开头表示开始一个document,所有的列表元素以"-“开头,键值对用”:",后面的空格是必须的。下面是一个示例:
--- #打头符可省略
- name: John Smith
age: 41
gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- name: Jenny Smith
age 13
gender: Female
YAML文件扩展名通常为.yaml或.yml,如example.yaml
2、list
列表的所有元素均使用“-”打头,例如:
# A list of tasty fruits
- Apple
- Orange
- Strawberry
3、dictionary
字典通过key与valuef进行标识,例如:
# An employee record
name: Example Developer
job: Developer
skill: Elite
也可以将key:value放置于{}中进行表示,例如:
# An employee record
{name: Example Developer, job: Developer, skill: Elite}
playbook(剧本)是ansible管理配置、部署应用和编排的文件,可用来描述你想在被控主机上执行的策略或者一组任务等。
一个playbook文件由一个或多个play组成,每个play定义了在一个或多个远程主机上执行的一系列的task,其中每个task一般就是调用一个ansible的模块。
playbook使用YAML语言编写,文件名以.yaml或.yml结尾。此外playbook和模板文件(template)还可使用jinja2语法语法实现高级功能。
targets:指定要执行playbook的远程主机组
variables:定义playbook运行时需要使用的变量
tasks:要执行的任务
handlers:处理器,在某些条件下被触发的操作
一个简单的示例:
vim httpd.yml
- hosts: websrvs
remote_user: root
vars:
remote_conffile_path: /etc/httpd/conf/httpd.conf
tasks:
- name: install httpd
yum: name=httpd state=latest
when: ansible_pkg_mgr == "yum"
- name: configration file
tags: conf
copy: src=/root/httpd.conf dest=` remote_conffile_path `
notify: restart httpd
- name: start httpd
service: name=httpd enabled=yes state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
⑴hosts和users
hosts用于指定要执行指定任务的主机,其可以是一个或多个由逗号分隔主机组;remote_user则用于指定远程主机上的执行任务的用户。如上面示例中的
- hosts: websrvs
remote_user: magedu #在远程主机上以哪个用户身份执行
become: yes #是否允许身份切换
become_method: sudo #切换用户身份的方式,有sudo、su、pbrun等方式,默认为sudo
become_user: root #切换成什么用户身份,默认为root
tasks:
- name: test connection
ping:
以上remote_user、become、become_method、become_use选项不仅可用于全局,也可用于各task中。在absible 2.0以前的版本中,用 sudo 和 sudo_user 两个选项分别表示是否允许sudo和sudo切换到的用户身份
remote_user、become、become_method、become_user分别对应inventory文件中的ansible_user、ansible_become、ansible_become_method、ansible_become_user
如果需要指定切换用户身份时的密码,可在执行ansible-playbook时使用选项 --ask-become-pass指定(旧版ansible使用 --ask-sudo-pass指定sudo切换时的密码)
⑵任务列表和action
play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出。
定义task的可以使用“action: module options”或“module: options”的格式,推荐使用后者以实现向后兼容例如:
tasks:
- name: make sure apache is running
service: name=httpd state=running
在众多模块中,只有command和shell模块仅需要给定一个列表而无需使用“key=value”格式,例如:
tasks:
- name: disable selinux
command: /sbin/setenforce 0
如果命令或脚本的退出码不为零(默认情况下,退出码不为零即表示执行失败,任务会立即中止,后续任务不再执行),可以使用如下方式替代:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true(表示一定会成功)
或者使用ignore_errors来忽略错误信息:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
⑶handlers:用于当关注的资源发生变化时触发一定的操作。
“notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。
- name: template configuration file
template: src=/root/template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
handler是task列表,这些task与前述的task并没有本质上的不同。
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
⑷变量
变量名仅能由字母、数字和下划线组成,且只能以字母开头。
在playbook中定义变量的格式:
- host websrvs
vars:
variable:value
如何调用变量:` variable `
在inventory中定义的变量,可在playbook中直接调用
每个被控节点在接收并运行管理命令之前,会将本主机相关信息(称为facts,这些信息保存于变量中)如操作系统版本,ip地址,cpu数量等报告给ansible主机。这些变量信息通过 ansible -m setup 获取,我们可在playbook中调用这些变量。
当给一个主机应用角色的时候可以传递变量,然后在角色内使用这些变量,示例如下:
- hosts: webservers
roles:
- common
- { role: foo_app_instance, dir: '/web/htdocs/a.com', port: 8080 }
另外,在运行playbook的时候也可以传递一些变量,示例:
ansible-playbook test.yml --extra-vars "hosts=www user=magedu"
如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提,这时就要用到条件测试。
when语句:
在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法。例如:
tasks:
- name: "shutdown Debian flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "Debian"
when语句中还可以使用Jinja2的大多“filter”,例如要忽略此前某语句的错误并基于其结果(failed或者sucess)运行后面指定的语句,可使用类似如下形式:
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|success
- command: /bin/still/something_else
when: result|skipped
此外,when语句中还可以使用facts或playbook中定义的变量。
当有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句来指明迭代的元素列表即可。例如:
- name: add several users
user: name=item state=present groups=wheel
with_items:
- testuser1
- testuser2
上面语句的功能等同于下面的语句:
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
事实上,with_items中可以使用元素还可以是hashes(迭代嵌套),例如:
- name: add several users
user: name=item.name state=present groups=item.groups
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
tags用于让用户选择运行playbook中的某个或某些任务。虽然ansible具有幂等性,会跳过没有变化的部分,但是,有些代码为测试其确实没有发生变化,也会耗费很长时间。我们将playbook中的指定任务打上标签,在运行playbook时指定标签名称,这样就不用运行全部代码了。
playbook中可定义多个标签,且可重名。
示例:
- name: configration file
copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
tags: conf
运行指定标签的任务:ansible-playbook httpd.yml -t conf
ansible-playbook ... [options]
例:ansible-playbook httpd.yml
以下node1为ansible节点,node2和node3为被控节点,已被添加至主机组websrvs。这里假设两个被控节点上已安装好httpd服务程序,且已建立双机互信。
[root@node1 ~]# vim /etc/ansible/hosts
[websrvs]
192.168.30.20
192.168.30.13
[dbsrvs]
192.168.30.14
[root@node1 ~]# ls hb_conf #准备好需要的文件
authkeys ha.cf haresources
[root@node1 ~]# vim heartbeat.yml #创建playbook
- hosts: websrvs
remote_user: root
tasks:
- name: ensure heartbeat latest version
yum: name=heartbeat state=present
- name: authkeys
copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/ mode=600
notify: restart heartbeat
- name: ha.cf
copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/
notify: restart heartbeat
tags: conf #打标签
- name: haresources
copy: src=/root/hb_conf/haresources dest=/etc/ha.d/
notify: restart heartbeat
handlers:
- name: restart heartbeat
service: name=heartbeat state=restarted
[root@node1 ~]# ansible-playbook heartbeat.yml #运行playbook
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [192.168.30.20]
ok: [192.168.30.13]
TASK [ensure heartbeat latest version] *****************************************
changed: [192.168.30.20]
changed: [192.168.30.13]
TASK [authkeys] ****************************************************************
changed: [192.168.30.13]
changed: [192.168.30.20]
TASK [ha.cf] *******************************************************************
changed: [192.168.30.13]
changed: [192.168.30.20]
TASK [haresources] *************************************************************
changed: [192.168.30.20]
changed: [192.168.30.13]
RUNNING HANDLER [restart heartbeat] ********************************************
changed: [192.168.30.13]
changed: [192.168.30.20]
PLAY RECAP *********************************************************************
192.168.30.13 : ok=6 changed=5 unreachable=0 failed=0
192.168.30.20 : ok=6 changed=5 unreachable=0 failed=0
#验证
[root@node2 ~]# ls /etc/ha.d
authkeys ha.cf harc haresources rc.d README.config resource.d shellfuncs
[root@node2 ~]# ll /etc/ha.d/authkeys
-rw------- 1 root root 680 May 3 20:07 /etc/ha.d/authkeys
[root@node2 ~]# service heartbeat status
heartbeat OK [pid 7595 et al] is running on node2 [node2]...
[root@node2 ~]# ip addr show
...
2: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:bd:68:23 brd ff:ff:ff:ff:ff:ff
inet 192.168.30.20/24 brd 192.168.30.255 scope global eth0
inet 192.168.30.100/24 brd 192.168.30.255 scope global secondary eth0
inet6 fe80::20c:29ff:febd:6823/64 scope link
valid_lft forever preferred_lft forever
[root@node2 ~]# service httpd status
httpd (pid 8049) is running...
[root@node1 ~]# vim hb_conf/ha.cf #修改主配置文件
...
mcast eth0 225.1.1.5 694 1 0 #更改心跳信息的组播地址
[root@node1 ~]# ansible-playbook heartbeat.yml -t conf #只执行指定标签的任务
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [192.168.30.13]
ok: [192.168.30.20]
TASK [ha.cf] *******************************************************************
changed: [192.168.30.20]
changed: [192.168.30.13]
RUNNING HANDLER [restart heartbeat] ********************************************
changed: [192.168.30.20]
changed: [192.168.30.13]
PLAY RECAP *********************************************************************
192.168.30.13 : ok=3 changed=2 unreachable=0 failed=0
192.168.30.20 : ok=3 changed=2 unreachable=0 failed=0
[root@node2 ~]# netstat -unl
...
udp 0 0 225.1.1.5:694 0.0.0.0:*
https://blog.51cto.com/9124573/1769887
未完待续。。。。。。。