Ansible之Playbook详解
- 一、YAML入门
- 1.1 YAML介绍
- 1.2 YAML基本语法
- 1.3 YAML支持的数据类型
- 二、Playbook剧本
- 2.1 Playbook介绍
- 2.2 Playbook核心元素
- 三、 hosts和users介绍
- 四、tasks列表和action
- 五、Handlers介绍
- 六、引用变量
- 6.1 vars: 添加变量
- 6.2 直接引用Ansible变量,ansible自带的固有变量
- 6.3 引用主机变量
- 6.4 条件语句跟变量
- 七、 条件判断
- 7.1 多条件判断
- 7.2 组条件判断
- 7.3 迭代
- 八、总结
一、YAML入门
1.1 YAML介绍
YAML:是一种非标记语言。用来配置文件的语言,非常简洁和强大
YAML语法和其他语言类似,也可以表达散列表、标量等数据结构
结构通过空格来展示;序列里配置项通过-来代表;Map里键值用:来分隔
YAML的扩展名为yaml
1.2 YAML基本语法
1)大小写敏感
2)使用缩进表示层级关系
3)缩进不允许使用tab,只允许空格
4)缩进的空格数不重要,只要相同层级的元素左对齐即可
5)’#’.表示注释
1.3 YAML支持的数据类型
1)对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
2)数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
3)纯量(scalars):单个的、不可再分的值
二、Playbook剧本
2.1 Playbook介绍
通过task调用ansible的模块将多个play组织在一个playbook中运行。playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。
2.2 Playbook核心元素
1)tasks:任务,即调用模块完成的某操作
2)Variables:变量
3)Templates:模板
4)Handlers:处理器,当某条件满足时,触发执行的操作
5)Roles:角色
三、 hosts和users介绍
在playbook中的每一个play都可以选择在哪些服务器和以什么用户完成,hosts一行可以是一个主机组、主机、多个主机,中间以冒号分隔,可使用通配模式。其中remote_user表示执行的用户账号。
[root@ansible ~]# cat demo.yaml
- hosts: apache #指定主机组,可以是一个或多个组。
remote_user: root #指定远程主机执行的用户名
tasks:
- name: test connection
ping:
remote_user: root
[root@ansible ~]# ansible-playbook demo.yaml -k ## 执行playbook-k(–ask-pass) 用来交互输入ssh密码
SSH password:
PLAY [apache] ************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************
ok: [192.168.10.20]
TASK [test connection] ***************************************************************************************
ok: [192.168.10.20]
PLAY RECAP ***************************************************************************************************
192.168.10.20 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
指定远程主机sudo切换
[root@ansible ~]# cat sudo.yaml
- hosts: apache
remote_user: root
become: yes #2.6版本以后的参数,之前是sudo,意思为切换用户运行
become_user: apache #指定sudo用户为apache
ansible-playbook sudo.yaml -k ## 执行playbook -k(–ask-pass) 用来交互输入ssh密码
四、tasks列表和action
1:Play的主体部分是task列表,task列表中的各任务按次序逐个在hosts中指定的主机上执行,即在所有主机上完成第一个任务后再开始第二个任务。
在运行playbook时(从上到下执行),如果一个host执行task失败,整个tasks都会回滚,请修正playbook 中的错误,然后重新执行即可。
Task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量,模块执行时幂等的,这意味着多次执行是安全的,因为其结果一致。
2:每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个task的。如果没有定义name,‘action’的值将会用作输出信息中标记特定的task。
3:定义一个task,常见的格式:”module: options” 例如:yum: name=httpd
4:ansible的自带模块中,command模块和shell模块无需使用key=value格式
[root@ansible ~]# cat apache.yaml ## yum安装apache服务并为其提供一个主页
- hosts: apache
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started
- name: stop firewalld
service: name=firewalld state=stopped
- name: touch index
copy: content="this is my apache" dest=/var/www/html/index.html
[root@ansible ~]# ansible-playbook apache.yaml
PLAY [apache] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.10.20]
TASK [install httpd] ***********************************************************
changed: [192.168.10.20]
TASK [start httpd] *************************************************************
changed: [192.168.10.20]
TASK [stop firewalld] **********************************************************
ok: [192.168.10.20]
TASK [touch index] *************************************************************
ok: [192.168.10.20]
PLAY RECAP *********************************************************************
192.168.10.20 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
回滚举例:
Firewalld写为Firewall来模拟错误,验证回滚,若发生错误,将会回滚到错误发生前,和游戏中的回档类似
执行到stop Firewalld的时候会反馈报错信息,并停止下一步操作,回滚到错误发生之前,访问网页也是没有主页展示的
play中只要执行命令的返回值不为0,就会报错,tasks停止,可以添加下面
ignore_errors: True #忽略错误,强制返回成功
- hosts: apache
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started
- name: stop firewalld
service: name=firewall state=stoppped
ignore_errors: True #忽略错误,强制返回成功
- name: touch index
copy: content="this is my apache" dest=/var/www/html/index.html
[root@ansible ~]# ansible-playbook apache.yaml
PLAY [apache] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.10.20]
TASK [install httpd] ***********************************************************
changed: [192.168.10.20]
TASK [start httpd] *************************************************************
changed: [192.168.10.20]
TASK [stop firewalld] **********************************************************
fatal: [192.168.10.20]: FAILED! => {"changed": false, "msg": "Could not find the requested service firewall: host"}
...ignoring
TASK [touch index] *************************************************************
ok: [192.168.10.20]
PLAY RECAP *********************************************************************
192.168.10.20 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
## 成功了五个,修改了两个,跳过了一个
五、Handlers介绍
- andlers也是一些task的列表,和一般的task并没有什么区别。
- 是由通知者进行的notify,如果没有被notify,则Handlers不会执行,假如被notify了,则Handlers被执行
- 不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次
- hosts: apache
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: install configuration file for httpd
copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: restart httpd
service: name=httpd state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
## 执行到notify的restart httpd时会先执行下面的handlers,handlers执行完了会返回notify继续执行,并且下面的handlers不会再执行了
六、引用变量
6.1 vars: 添加变量
[root@ansible ~]# cat apache.yaml
- hosts: apache
remote_user: root
vars:
- package: httpd ## vars下方可以添加变量
- service: httpd
tasks:
- name: install httpd
yum: name={{package}} ## {{}}引用变量
- name: start httpd
service: name={{service}} enabled=true state=started
6.2 直接引用Ansible变量,ansible自带的固有变量
- ansible_all_ipv4_addresses 获取IP
[root@ansible ~]# cat ipadress.yaml
- hosts: apache
remote_user: root
tasks:
- name: copy file
copy: content="{{ansible_all_ipv4_addresses}}" dest=/opt/ip.txt
6.3 引用主机变量
在组的主机后面添加变量
vi /etc/ansible/hosts
[apache]
192.168.10.20 test="this is a test file"
[mysql]
192.168.10.30
- hosts: apache
remote_user: root
tasks:
- name: copy file
copy: content="{{test}}" dest=/opt/test.txt
[root@ansible ~]# ansible apache -a 'cat /opt/test.txt'
192.168.10.20 | CHANGED | rc=0 >>
this is a test file
6.4 条件语句跟变量
执行playbook的时候可以用-e 来引用变量
- hosts: apache
remote_user: root
tasks:
- name: copy file
copy: content="{{test2}}" dest=/opt/test2.txt
[root@ansible ~]# ansible-playbook ipadress.yaml -e test2="anotherone"
[root@ansible ~]# ansible apache -a 'cat /opt/test2.txt'
192.168.10.20 | CHANGED | rc=0 >>
anotherone
七、 条件判断
when的值是一个条件表达式,如果条件判断成立,这个task就执行,如果判断不成立,则task不执行
如果需要根据变量、facts(setup)或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,在Playbook中条件测试使用when子句。
在task后添加when子句即可使用条件测试:when子句支持jinjia2表达式或语法,例如:
- hosts: apache
remote_user: root
tasks:
- name: shutdown
command: /sbin/shutdown -h now
when: ansible_distribution=="Centos"
## 当系统是Centos系统时就会执行关机指令
7.1 多条件判断
- hosts: apache
remote_user: root
tasks:
- name: shutdown
command: /sbin/shutdown -h now
when:
- ansible_distribution=="Centos"
- ansible_distribution_major_version=="7"
## 当系统是CentOS系统,并且版本号为7才会执行关机语句,两项都满足
7.2 组条件判断
- hosts: apache
remote_user: root
tasks:
- name: shutdown Centos6 Centos7
command: /sbin/shutdown -h now
when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or (ansible_distribution == "CentOS" ansible_distribution_major_version == "7")
7.3 迭代
有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句指明迭代的元素列表即可。
- hosts: apache
remote_user: root
tasks:
- name: install packages
yum: name={{ item }} state=latest
with_items:
- httpd
- php
## 依次安装httpd 和php这两服务
八、总结
playbook是由一个或多个模块组成的,使用多个不同的模块,完成一件事情。需要熟练掌握ansible中各个模块对应的功能以及YAML的语法规则。
缩进: YAML使用一个固定的缩进风格表示层级结构,每个缩进由两个空格组成, 不能使用tabs;
冒号: 以冒号结尾的除外,其他所有冒号后面所有必须有空格;
短横线: 表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表;