Ansible 剧本playbook

概念

Playbooks are automation blueprints, in YAML format, that Ansible uses to deploy and configure nodes in an inventory.

playbook 是自动化的蓝图,使用YAML 格式,用来配置和部署清单中的节点。

  • Executing tasks with elevated privileges or as a different user.
  • Using loops to repeat tasks for items in a list.
  • Delegating playbooks to execute tasks on different machines.
  • Running conditional tasks and evaluating conditions with playbook tests.
  • Using blocks to group sets of tasks.

playbook 、play、task 的关系

简单总结一下playbook、play和task的关系:
1.playbook中可以定义一个或多个play
2.每个play中可以定义一个或多个task

- 其中还可以定义两类特殊的task:pre_tasks和post_tasks  
- pre_tasks表示执行执行普通任务之前执行的任务列表  
- post_tasks表示普通任务执行完之后执行的任务列表  

3.每个play都需要通过hosts指令指定要执行该play的目标主机
4.每个play都可以设置一些该play的环境控制行为,比如定义play级别的变量

Yaml 语法

YAML的基本语法规则如下:
(1).使用缩进表示层级关系
(2).缩进时不允许使用Tab键,只允许使用空格
(3).缩进的空格数目不重要,只要相同层级的元素左对齐即可
(4).yaml文件以”—“作为文档的开始,以表明这是一个yaml文件

- 即使没有使用`---`开头,也不会有什么影响  

(5).# 表示注释,从这个字符一直到行尾,都会被解析器忽略
(6).字符串不用加引号,但在可能产生歧义时,需加引号(单双引号皆可),比如引用变量时
(7).布尔值非常灵活,不分区大小写的true/false、yes/no、on/off、y/n、0和1都允许

YAML支持三种数据结构:
(1).对象:key/value格式,也称为哈希结构、字典结构或关联数组
(2).数组:也称为列表
(3).标量(scalars):单个值

可以去找一些在线YAML转换JSON网站,比如 http://yaml-online-parser.appspot.com 通过在线转换可以验证或查看自己所写的YAML是否出错以及哪里出错。

对象

一组键值对,使用冒号隔开key和value。注意,冒号后必须至少一个空格

name: task1
等价于json:{
  "name": "task1"
}


数组

---
- Shell
- Perl
- Python
等价于json:

["Shell","Perl","Python"]

对象与数组结合

---
languages:
  - Shell
  - Perl
  - Python

字典
---
person1:
  name: task1
  age: 18
  gender: male

person2:
  name: task2
  age: 19
  gender: female

复合结构

---
- person1:
  name: task1
  age: 18
  langs:
    - Perl
    - Ruby
    - Shell

- person2:
  name: task2
  age: 19
  langs:
    - Python
    - Javascript

字符串续行

字符串可以写成多行,从第二行开始,必须至少有一个单空格缩进。换行符会被转为空格。

str: hello
  world
  hello world

等价于json:

{
  "str": "hello world hello world"
}

也可以使用 > 换行,它类似于上面的多层缩进写法。此外,还可以使用|在换行时保留换行符。

this: |
  Foo
  Bar
that: >
  Foo
  Bar

等价于json:

{‘that’: ‘Foo Bar’, ‘this’: ‘Foo\nBar\n’}



playbook 的组成

再来解释一下这个playbook文件的含义。

playbook中,每个play都需要放在数组中,所以在playbook的顶层使用列表的方式- xxx:来表示这是一个play(此处是- hosts:)。

每个play都必须包含hoststasks指令。

hosts指令用来指定要执行该play的目标主机,可以是主机名,也可以是主机组,还支持其它方式来更灵活的指定目标主机。具体的规则后文再做介绍。

tasks指令用来指定这个play中包含的任务,可以是一个或多个任务,任务也需要放在play的数组中,所以tasks指令内使用- xxx:的方式来表示每一个任务(此处是- copy:)。

gather_facts是一个play级别的指令设置,它是一个负责收集目标主机信息的任务,由setup模块提供。默认情况下,每个play都会先执行这个特殊的任务,收集完信息之后才开始执行其它任务。但是,收集目标主机信息的效率很低,如果能够确保playbook中不会使用到所收集的信息,可以显式指定gather_facts: no来禁止这个默认执行的收集任务,这对效率的提升是非常可观的。

此外每个play和每个task都可以使用name指令来命名,也建议尽量为每个play和每个task都命名,且名称具有唯一性。

playbook 模块参数传递方式

在刚才的示例中,copy模块的参数传递方式如下:

  tasks: 
    - name: copy /etc/passwd to /tmp
      copy: src=/etc/passwd dest=/tmp

这是标准的yaml语法,参数部分src=/etc/passwd dest=/tmp是一个字符串,当作copy对应的值。

根据前面介绍的yaml语法,还可以换行书写。有以下几种方式:

---
- name: first play
  hosts: nginx
  gather_facts: false
  tasks: 
    - copy: 
        src=/etc/passwd dest=/tmp

    - copy: 
        src=/etc/passwd
        dest=/tmp

    - copy: >
        src=/etc/passwd
        dest=/tmp

    - copy: |
        src=/etc/passwd
        dest=/tmp

除此之外,Ansible还提供了另外两种传递参数的方式:
(1).将参数和参数值写成key: value的方式
(2).使用args参数声明接下来的是参数

---
- name: first play
  hosts: nginx
  gather_facts: false
  tasks: 
    - name: copy1
      copy: 
        src: /etc/passwd
        dest: /tmp

    - name: copy2
      copy: 
      args:
        src: /etc/passwd
        dest: /tmp

指定执行的主机

每一个play都包含hosts指令,它用来指示在解析inventory之后选择哪些主机执行该play中的tasks。

hosts指令通过pattern的方式来筛选节点,pattern的指定方式有以下几种规则:
1.直接指定inventory中定义的主机名

- hosts: localhost  

2.直接指定inventory中的主机组名

- hosts: nginx、hosts: all  

3.使用组名时,可以使用数值索引的方式表示组中的第几个主机

- hosts: nginx[1]:mysql[0]  

4.可使用冒号隔开多个pattern

- hosts: nginx:localhost  

5.可以使用范围表示法

- hosts: 192.168.200.3[0:3]  
- hosts: web[A:D]  

6.可以使用通配符*

- hosts: *.example.com  
- hosts: *  

7.可以使用正则表达式,需使用~开头

- hosts: ~(web|db)\.example\.com  

此外:
1.所有pattern选中的主机都是包含性的,第一个pattern选中的主机会添加到下一个pattern的范围内,直到最后一个pattern筛选完,于是取得了所有pattern匹配的主机
2.pattern前面加一个&符号表示取交集

- pattern1:&pattern2 要求同时存在于pattern1和pattern2中的主机  

3.pattern前面加一个!符号表示排除

- pattern1:!pattern2 要求出现在pattern1中但未出现在pattern2中  
Index