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来模拟错误,验证回滚,若发生错误,将会回滚到错误发生前,和游戏中的回档类似

ansible的playbook的handler 和 notify ansible playbook详解_缩进


执行到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;
冒号: 以冒号结尾的除外,其他所有冒号后面所有必须有空格;
短横线: 表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表;