Ansible-playbook中的流控制

在ansible中的有各种流控制的机制,本节主要讲ansible流控制中的when和with_item

流控制when

在使用ansible做自动化运维的时候,大多数情况下都执行某些任务的时候都需要依赖某个变量的值或者是上一个任务的执行结果。如,根据facts信息中的系统版本相关的信息来确定使用哪种包管理器安装软件。Ansible提供when语句,可以控制任务的执行流程。

playbook中when的使用

when测试条件:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提条件时,需要用到条件测试,通过when语句实现,在task中使用,jinja2语法。

when使用实战

当系统不同时,httpd的配置文件也不同,根据系统的版本来判断使用哪个httpd的配置文件

1.使用setup模块找远程系统中版本变量

1
2
3
4
[root@ansible yaml]# ansible webserver -m setup | grep distribution_major_version
"ansible_distribution_major_version": "6",
"ansible_distribution_major_version": "7",
"ansible_distribution_major_version": "7",

2.根据变量值编写yaml文件,使用when来判断变量的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@ansible yaml]# vim httpd.yaml
---
#install httpd
- hosts: webserver
remote_user: root

tasks:
- name: install
yum: name=httpd
- name: config
template: src=httpd6.conf.j2 dest=/etc/httpd/conf/httpd.conf
when: ansible_distribution_major_version == "6" #判断系统版本的值当系统版本为6时使用http6.conf.j2的模板
notify: restart service
- name: config
template: src=httpd7.conf.j2 dest=/etc/httpd/conf/httpd.conf
when: ansible_distribution_major_version == "7" #判断系统版本的值当系统版本为7时使用http7.conf.j2的模板
notify: restart service
- name: service
service: name=httpd state=started

handlers:
- name: restart service
service: name=httpd state=restarted

3.修改模板文件,将监听的端口改为变量的形式

1
2
3
4
5
6
7
8
[root@ansible templates]# vi httpd6.conf.j2
#Listen 12.34.56.78:80
Listen {{port}}

[root@ansible templates]# vi httpd7.conf.j2
#Listen 12.34.56.78:80
Listen {{port}}

4.执行脚本

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
32
33
34
35
36
37
[root@ansible yaml]# ansible-playbook  httpd.yaml

PLAY [webserver] ************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************
ok: [192.168.73.135]
ok: [192.168.73.132]
ok: [192.168.73.134]

TASK [install] **************************************************************************************************
changed: [192.168.73.135]
changed: [192.168.73.134]
changed: [192.168.73.132]

TASK [config] ***************************************************************************************************
skipping: [192.168.73.134]
skipping: [192.168.73.135]
changed: [192.168.73.132]

TASK [config] ***************************************************************************************************
skipping: [192.168.73.132]
ok: [192.168.73.134]
changed: [192.168.73.135]

TASK [service] **************************************************************************************************
changed: [192.168.73.132]
changed: [192.168.73.135]
changed: [192.168.73.134]

RUNNING HANDLER [restart service] *******************************************************************************
changed: [192.168.73.132]
changed: [192.168.73.135]

PLAY RECAP ******************************************************************************************************
192.168.73.132 : ok=5 changed=4 unreachable=0 failed=0
192.168.73.134 : ok=4 changed=2 unreachable=0 failed=0
192.168.73.135 : ok=5 changed=4 unreachable=0 failed=0

这样在部署httpd服务时候就会更具系统的版本号使用不同的配置文件。

with_items

迭代:当有需要重复行执行的任务时,可以使用迭代机制

对迭代项的引用,固定变量名为”item”

要在task中使用with_items给定要迭代的元素列表

列表格式:字符串、字典

with_items使用示例

使用with_items创建文件

在远程主机上创建以下多个文件,可以看出这些文件都有一个特征都是以”.log”结尾,如此只需要将之前的文件使用变量代替,然后使用with_items给定元素列表就能创建出相应的文件了

1
2
3
aaa.log  
bbb.log
ccc.log

1.创建剧本

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@ansible yaml]# vim file.yaml
---
#touch file
- hosts: webserver
remote_user: root

tasks:
- name: touch file
file: name=/data/{{item}}.log state=touch #将需要重复创建的*.log文件的文件名使用item这个变量代替
with_items: #hwith_item列表中写入所有需要创建出的文件名。
- aaa
- bbb
- ccc

2.执行剧本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@ansible yaml]# ansible-playbook  file.yaml

PLAY [webserver] ************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************
ok: [192.168.73.132]
ok: [192.168.73.134]
ok: [192.168.73.135]

TASK [touch file] ***********************************************************************************************
changed: [192.168.73.132] => (item=aaa)
changed: [192.168.73.134] => (item=aaa)
changed: [192.168.73.135] => (item=aaa)
changed: [192.168.73.132] => (item=bbb)
changed: [192.168.73.134] => (item=bbb)
changed: [192.168.73.135] => (item=bbb)
changed: [192.168.73.132] => (item=ccc)
changed: [192.168.73.135] => (item=ccc)
changed: [192.168.73.134] => (item=ccc)

PLAY RECAP ******************************************************************************************************
192.168.73.132 : ok=2 changed=1 unreachable=0 failed=0
192.168.73.134 : ok=2 changed=1 unreachable=0 failed=0
192.168.73.135 : ok=2 changed=1 unreachable=0 failed=0

校验查看远程主机上的文件是否被创建

1
2
3
4
5
6
[root@ansible yaml]# ansible webserver -a 'ls /data'
192.168.73.132 | CHANGED | rc=0 >>
aaa.log #三个文件已经被创建出来
bbb.log
ccc.log
lost+found
使用with_items创建用户

在批量创建用户将账户时也可以使用with_items来创建用户,具体使用方法如下

1.创建yaml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14

[root@ansible yaml]# vim createuser.yml
---
#createuser
- hosts: webserver
remote_user: root

tasks:
- name: create user
user: name={{item}} #将用户名使用item变量来代替
with_items: #使用with_items来列出所有需要创建的用户
- alice
- bob
- clack

2.执行playbook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@ansible yaml]# ansible-playbook createuser.yml

PLAY [webserver] ************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************
ok: [192.168.73.135]
ok: [192.168.73.132]
ok: [192.168.73.134]

TASK [create user] **********************************************************************************************
changed: [192.168.73.135] => (item=alice)
changed: [192.168.73.134] => (item=alice)
changed: [192.168.73.132] => (item=alice)
changed: [192.168.73.132] => (item=bob)
changed: [192.168.73.135] => (item=bob)
changed: [192.168.73.134] => (item=bob)
changed: [192.168.73.132] => (item=clack)
changed: [192.168.73.134] => (item=clack)
changed: [192.168.73.135] => (item=clack)

PLAY RECAP ******************************************************************************************************
192.168.73.132 : ok=2 changed=1 unreachable=0 failed=0
192.168.73.134 : ok=2 changed=1 unreachable=0 failed=0
192.168.73.135 : ok=2 changed=1 unreachable=0 failed=0

3.验证远程主机上的用户已经被创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@ansible yaml]# ansible webserver -a 'getent passwd | tail -3'
192.168.73.132 | CHANGED | rc=0 >>
alice:x:500:500::/home/alice:/bin/bash
bob:x:501:501::/home/bob:/bin/bash
clack:x:502:502::/home/clack:/bin/bash

192.168.73.135 | CHANGED | rc=0 >>
alice:x:3307:3307::/home/alice:/bin/bash
bob:x:3308:3308::/home/bob:/bin/bash
clack:x:3309:3309::/home/clack:/bin/bash

192.168.73.134 | CHANGED | rc=0 >>
alice:x:3307:3307::/home/alice:/bin/bash
bob:x:3308:3308::/home/bob:/bin/bash
clack:x:3309:3309::/home/clack:/bin/bash

with_items的高级用法

当多个类型的item之间有对应的关系时,可以使用字典的形式将多个item项进行关联起来

with_items的字典用法

创建组和用户的对应关系,将用户关联到对应的用户组下

1
2
3
4
USER        GROUP
aaa agroup
bbb bgroup
ccc cgroup

1.编辑yaml文件,将用户名和组名做字典对应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@ansible yaml]# vim usergroup.yaml
---
- hosts: webserver
remote_user: root

tasks:
- name: create group
group: name={{item}} #将组名定义为变量
with_items: #将需要创建的组写在with_items下
- agroup
- bgroup
- cgroup
- name: create user
user: name={{item.name}} group={{item.group}} #创建用户并和组进行关联,使用以“item.*"形式的变量将用户和组进行关联起来
with_item: #在with_items写入name和group的字典关系
- { name: "aaa",group: "agroup"}
- { name: "bbb",group: "bgroup"}
- { name: "ccc",group: "cgroup"}

2.执行剧本

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
32
33
34
35
[root@ansible yaml]# ansible-playbook usergroup.yaml

PLAY [webserver] ************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************
ok: [192.168.73.135]
ok: [192.168.73.132]
ok: [192.168.73.134]

TASK [create group] *********************************************************************************************
changed: [192.168.73.132] => (item=agroup)
changed: [192.168.73.134] => (item=agroup)
changed: [192.168.73.135] => (item=agroup)
changed: [192.168.73.132] => (item=bgroup)
changed: [192.168.73.135] => (item=bgroup)
changed: [192.168.73.134] => (item=bgroup)
changed: [192.168.73.132] => (item=cgroup)
changed: [192.168.73.135] => (item=cgroup)
changed: [192.168.73.134] => (item=cgroup)

TASK [create user] **********************************************************************************************
changed: [192.168.73.134] => (item={u'group': u'agroup', u'name': u'aaa'})
changed: [192.168.73.132] => (item={u'group': u'agroup', u'name': u'aaa'})
changed: [192.168.73.135] => (item={u'group': u'agroup', u'name': u'aaa'})
changed: [192.168.73.132] => (item={u'group': u'bgroup', u'name': u'bbb'})
changed: [192.168.73.135] => (item={u'group': u'bgroup', u'name': u'bbb'})
changed: [192.168.73.134] => (item={u'group': u'bgroup', u'name': u'bbb'})
changed: [192.168.73.132] => (item={u'group': u'cgroup', u'name': u'ccc'})
changed: [192.168.73.134] => (item={u'group': u'cgroup', u'name': u'ccc'})
changed: [192.168.73.135] => (item={u'group': u'cgroup', u'name': u'ccc'})

PLAY RECAP ******************************************************************************************************
192.168.73.132 : ok=3 changed=2 unreachable=0 failed=0
192.168.73.134 : ok=3 changed=2 unreachable=0 failed=0
192.168.73.135 : ok=3 changed=2 unreachable=0 failed=0

校验查看远程主机上的用户是否和组进行了关联

1
2
3
4
5
6
7
8
9
10
[root@ansible yaml]# ansible webserver -a 'id aaa'
192.168.73.132 | CHANGED | rc=0 >>
uid=503(aaa) gid=503(agroup) groups=503(agroup)

192.168.73.134 | CHANGED | rc=0 >>
uid=3310(aaa) gid=3310(agroup) groups=3310(agroup)

192.168.73.135 | CHANGED | rc=0 >>
uid=3310(aaa) gid=3310(agroup) groups=3310(agroup)