文章目录
  1. 1. Ansible playbook 简介
  2. 2. Ansible playbook使用场景
  3. 3. Ansible playbook格式
    1. 3.1. 1)格式简介
    2. 3.2. 2)核心元素
    3. 3.3. 3)基本组件
    4. 3.4. 4)playbook的运行指令
    5. 3.5. 5)variables 部分
    6. 3.6. 6)模板 templates
    7. 3.7. 7)条件测试
    8. 3.8. 8)字典
    9. 3.9. 9)角色订制:roles

Ansible playbook 简介

playbook 是 ansible 用于配置,部署,和管理被控节点的剧本。
通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期的状态。playbook 就像 Ansible 控制器给被控节点列出的的一系列 to-do-list ,而被控节点必须要完成。
也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。

Ansible playbook使用场景

执行一些简单的任务,使用ad-hoc命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行的ad-hoc命令是不适合的,这时最好使用playbook。
就像执行shell命令与写shell脚本一样,也可以理解为批处理任务,不过playbook有自己的语法格式。使用playbook你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用Ansible的过程中,你也会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写成playbook,之后管理服务器会变得十分简单。

Ansible playbook格式

1)格式简介

playbook由YMAL语言编写。YAML( /ˈjæməl/ )参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822,Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与OrenBen-Kiki也是这语言的共同设计者。
  YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。首先学习了解一下YMAL的格式,对我们后面书写playbook很有帮助。以下为playbook常用到的YMAL格式:

1
2
3
4
5
  1、文件的第一行应该以 "---" (三个连字符)开始,表明YMAL文件的开始。
  2、在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
  3、YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
  4、同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
  5、play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以":"分隔表示,":"后面还要增加一个空格。

我们的文件名称应该以.yml结尾,像我们上面的例子就是mysql.yml。其中,有三个部分组成:

1
2
3
host部分:使用 hosts 指示使用哪个主机或主机组来运行下面的 tasks ,每个 playbook 都必须指定 hosts ,hosts也可以使用通配符格式。主机或主机组在 inventory 清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i选项,指定清单的位置即可。在运行清单文件的时候,–list-hosts选项会显示那些主机将会参与执行 task 的过程中。
remote_user:指定远端主机中的哪个用户来登录远端系统,在远端系统执行 task 的用户,可以任意指定,也可以使用 sudo,但是用户必须要有执行相应 task 的权限。
tasks:指定远端主机将要执行的一系列动作。tasks 的核心为 ansible 的模块,前面已经提到模块的用法。tasks 包含 name 和要执行的模块,name 是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。

执行有三个步骤:1、收集facts 2、执行tasks 3、报告结果

2)核心元素

Playbook的核心元素:

1
2
3
4
5
6
Hosts:主机组;
Tasks:任务列表;
Variables:变量,设置方式有四种;
Templates:包含了模板语法的文本文件;
Handlers:由特定条件触发的任务;
tags: 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

3)基本组件

Playbooks配置文件的基础组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Hosts:运行指定任务的目标主机
remoute_user:在远程主机上执行任务的用户;
tasks:任务列表
格式:
    tasks:
      – name: TASK_NAME
       module: arguments
       notify: HANDLER_NAME
       handlers:
      – name: HANDLER_NAME
       module: arguments
module:模块,模块参数
格式:
    (1) action: module arguments
    (2) module: arguments
    注意:shell和command模块后面直接跟命令,而非key=value类的参数列表;
handlers:任务,在特定条件下触发;接收到其它任务的通知时被触发;
(1) 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
(2) 任务可以通过“tags“打标签,而后可在ansible-playbook命令上使用-t指定进行调用;

4)playbook的运行指令

ansible-playbook <filename.yml> ...[options]

1
2
3
4
5
6
7
8
9
10
//常见选项
--check //只检测可能发生的改变,但不真正执行操作
--list-hosts //列出运行任务的主机
--limit //主机列表,只针对主机列表中的主机执行
-v //显示过程 -vv -vvv

//示例:
ansible-playbook file.yml --check //只检测,不执行
ansible-playbook file.yml
ansible-playbook file.yml --limit webServer

5)variables 部分

上文中,我们说到了variables是变量,有四种定义方法,现在我们就来说说这四种定义方法:
① facts :可直接调用
上一篇中,我们有说到setup这个模块,这个模块就是通过调用facts组件来实现的。我们这里的variables也可以直接调用facts组件。具体的facters我们可以使用setup模块来获取,然后直接放入我们的剧本中调用即可。
② 用户自定义变量
我们也可以直接使用用户自定义变量,想要自定义变量有以下两种方式:

  1. 通过命令行传入:ansible-playbook命令的命令行中的-e VARS, –extra-vars=VARS,这样就可以直接把自定义的变量传入。
  2. 在playbook中定义变量:
    1
    2
    3
    vars:
      - var1: value1
      - - var2: value2

③ 通过roles传递变量
④ Host Inventory
我们也可以直接在主机清单中定义。定义的方法如下:
向不同的主机传递不同的变量:IP/HOSTNAME varaiable=value var2=value2
向组中的主机传递相同的变量:

1
2
[groupname:vars]
  variable=value

6)模板 templates

模板是一个文本文件,嵌套有脚本(使用模板编程语言编写)。
Jinja2:Jinja2是python的一种模板语言,以Django的模板语言为原本。
模板支持:

1
2
3
4
5
6
7
8
9
10
11
12
字符串:使用单引号或双引号;
  数字:整数,浮点数;
  列表:[item1, item2, ...]
  元组:(item1, item2, ...)
  字典:{key1:value1, key2:value2, ...}
  布尔型:true/false
  算术运算:
    +, -, *, /, //, %, **
  比较操作:
    ==, !=, >, >=, <, <=
  逻辑运算:
    and, or, not

通常来说,模板都是通过引用变量来运用的。

7)条件测试

when语句:在task中使用,jinja2的语法格式。
举例如下:

1
2
3
4
5
6
7
tasks:
- name: install conf file to centos7
template: src=files/nginx.conf.c7.j2
when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
template: src=files/nginx.conf.c6.j2
when: ansible_distribution_major_version == "6"

循环:迭代,需要重复执行的任务;
  对迭代项的引用,固定变量名为”item”,而后,要在task中使用with_items给定要迭代的元素列表;
举例如下:

1
2
3
4
5
6
7
tasks:
- name: unstall web packages
yum: name={{ item }} state=absent
with_items:
- httpd
- php
- php-mysql

8)字典

ansible playbook 还支持字典功能。举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- name: install some packages
yum: name={{ item }} state=present
with_items:
- nginx
- memcached
- php-fpm
- name: add some groups
group: name={{ item }} state=present
with_items:
- group11
- group12
- group13
- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user11', group: 'group11' }
- { name: 'user12', group: 'group12' }
- { name: 'user13', group: 'group13' }

9)角色订制:roles

① 简介
  对于以上所有的方式有个弊端就是无法实现复用假设在同时部署Web、db、ha 时或不同服务器组合不同的应用就需要写多个yml文件。很难实现灵活的调用。
  roles 用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量(vars)、文件(file)、任务(tasks)、模块(modules)及处理器(handlers)放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
  
② 角色集合
角色集合:
files/:存储由copy或script等模块调用的文件;
tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用;
handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用;
vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用;
templates/:存储由template模块调用的模板文本;
meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用;
default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;

③ 角色定制实例

  1. 在roles目录下生成对应的目录结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    [root@server ansible]# cd roles/
    [root@server roles]# ls
    [root@server roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
    [root@server roles]# tree
    .
    ├── httpd
    │ ├── default
    │ ├── files
    │ ├── handlers
    │ ├── meta
    │ ├── tasks
    │ ├── templates
    │ └── vars
    ├── mysql
    │ ├── default
    │ ├── files
    │ ├── handlers
    │ ├── meta
    │ ├── tasks
    │ ├── templates
    │ └── vars
    └── nginx
    ├── default
    ├── files
    ├── handlers
    ├── meta
    ├── tasks
    ├── templates
    └── vars
  2. 定义配置文件
    我们需要修改的配置文件为/tasks/main.yml,下面,我们就来修改一下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [root@server roles]# vim nginx/tasks/main.yml
    - name: cp
    copy: src=nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm
    - name: install
    yum: name=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=latest
    - name: conf
    template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    tags: nginxconf
    notify: new conf to reload
    - name: start service
    service: name=nginx state=started enabled=true
  3. 放置我们所需要的文件到指定目录
    因为我们定义的角色已经有了新的组成方式,所以我们需要把文件都放到指定的位置,这样,才能让配置文件找到这些并进行加载。rpm包放在files目录下,模板放在templates目录下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [root@server nginx]# cp /tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm ./files/
    [root@server nginx]# cp /tmp/nginx.conf.j2 ./templates/
    [root@server nginx]# tree
    .
    ├── default
    ├── files
    │ └── nginx-1.10.2-1.el7.ngx.x86_64.rpm
    ├── handlers
    ├── meta
    ├── tasks
    │ └── main.yml
    ├── templates
    │ └── nginx.conf.j2
    └── vars
  4. 修改变量文件
    我们在模板中定义的变量,也要去配置文件中加上:

    1
    2
    [root@server nginx]# vim vars/main.yml
    nginxprot: 9999
  5. 定义handlers文件
    我们在配置文件中定义了notify,所以我么也需要定义handlers,我们来修改配置文件:

    1
    2
    3
    [root@server nginx]# vim handlers/main.yml
    - name: new conf to reload
    service: name=nginx state=restarted
  6. 定义剧本文件
    接下来,我们就来定义剧本文件,由于大部分设置我们都单独配置在了roles里面,所以,接下来剧本就只需要写一点点内容即可:

    1
    2
    3
    4
    5
    [root@server ansible]# vim roles.yml 
    - hosts: web
    remote_user: root
    roles:
    - nginx
  7. 启动服务
    剧本定义完成以后,我们就可以来启动服务了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    [root@server ansible]# ansible-playbook roles.yml

    PLAY [web] *********************************************************************

    TASK [setup] *******************************************************************
    ok: [192.168.37.122]
    ok: [192.168.37.133]

    TASK [nginx : cp] **************************************************************
    ok: [192.168.37.122]
    ok: [192.168.37.133]

    TASK [nginx : install] *********************************************************
    changed: [192.168.37.122]
    changed: [192.168.37.133]

    TASK [nginx : conf] ************************************************************
    changed: [192.168.37.122]
    changed: [192.168.37.133]

    TASK [nginx : start service] ***************************************************
    changed: [192.168.37.122]
    changed: [192.168.37.133]

    RUNNING HANDLER [nginx : new conf to reload] ***********************************
    changed: [192.168.37.122]
    changed: [192.168.37.133]

    PLAY RECAP *********************************************************************
    192.168.37.122 : ok=6 changed=4 unreachable=0 failed=0
    192.168.37.133 : ok=6 changed=4 unreachable=0 failed=0

启动过后照例查看端口号:

1
2
3
4
5
6
[root@server ansible]# ansible web -m shell -a "ss -ntulp |grep 9999"
192.168.37.122 | SUCCESS | rc=0 >>
tcp LISTEN 0 128 *:9999 *:* users:(("nginx",pid=7831,fd=6),("nginx",pid=7830,fd=6),("nginx",pid=7829,fd=6))

192.168.37.133 | SUCCESS | rc=0 >>
tcp LISTEN 0 128 *:9999 *:* users:(("nginx",pid=9654,fd=6),("nginx",pid=9653,fd=6),("nginx",pid=9652,fd=6))

可以看出我们的剧本已经执行成功。

本文章转载自:自动化运维工具——ansible详解(二)

文章目录
  1. 1. Ansible playbook 简介
  2. 2. Ansible playbook使用场景
  3. 3. Ansible playbook格式
    1. 3.1. 1)格式简介
    2. 3.2. 2)核心元素
    3. 3.3. 3)基本组件
    4. 3.4. 4)playbook的运行指令
    5. 3.5. 5)variables 部分
    6. 3.6. 6)模板 templates
    7. 3.7. 7)条件测试
    8. 3.8. 8)字典
    9. 3.9. 9)角色订制:roles