Ansible playbook之循环

1.标准Loops

当我们想安装10个软件包的时候,为了避免写10个task来安装,我们可以直接使用标准的loops简单快速实现10个软件包的安装,下面例子是分别打印了one two这两个值:

复制代码
#1.编写loop.yaml
[root@ansible01 ansible]# cat loops.yaml 
---
- hosts: 11.0.1.18
  gather_facts: False
  tasks:
   - name: debug loops
     debug: msg="name --> {{ item }}"
     with_items:
     - one
     - two
#2.运行loop.yaml文件
[root@ansible01 ansible]# ansible-playbook loops.yaml 
PLAY [11.0.1.18] **************************************************************************************************************************************************************************

TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=one) => {
    "msg": "name --> one"
}
ok: [11.0.1.18] => (item=two) => {
    "msg": "name --> two"
}

PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

with_items的值是python list数据结构,可以理解为每个task会循环读取list里面的值,然后key的名称是item,当然list里面也支持python字典,如下:

复制代码
[root@ansible01 ansible]# cat loops2.yaml 
---
- hosts: 11.0.1.18
  gather_facts: False
  tasks:
   - name: debug loops
     debug: msg="name --> {{ item.key }} value -->{{ item.value}}"
     with_items:
     - {key: "one",value: "hello"}
     - {key: "two",value: "wyx"}

[root@ansible01 ansible]# ansible-playbook loops2.yaml 
PLAY [11.0.1.18] **************************************************************************************************************************************************************************

TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item={u'value': u'hello', u'key': u'one'}) => {
    "msg": "name --> one value -->hello"
}
ok: [11.0.1.18] => (item={u'value': u'wyx', u'key': u'two'}) => {
    "msg": "name --> two value -->wyx"
}

PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

2.嵌套Loops

嵌套Loops也是我们编写playbook中比较常见的一种循环,它主要实现一对多或者多对多的合并,如下:

复制代码
[root@ansible01 ansible]# cat loops3.yaml 
---
- hosts: 11.0.1.18
  gather_facts: False
  tasks:
   - name: debug loops
     debug: msg="name --> {{ item[0] }} value --> {{ item[1] }}"
     with_nested:
     - ['A']
     - ['a','b','c']
[root@ansible01 ansible]# ansible-playbook loops3.yaml 
PLAY [11.0.1.18] **************************************************************************************************************************************************************************

TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=[u'A', u'a']) => {
    "msg": "name --> A value --> a"
}
ok: [11.0.1.18] => (item=[u'A', u'b']) => {
    "msg": "name --> A value --> b"
}
ok: [11.0.1.18] => (item=[u'A', u'c']) => {
    "msg": "name --> A value --> c"
}

PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

3. 散列loops

散列loops相比标准的loops就是变量支持更丰富的数据结构,比如标准loops的最外层数据必须是Python的list数据类型,而散列loops直接支持YAML格式的数据变量。如下:

复制代码
[root@ansible01 ansible]# cat loops4.yaml 
---
- hosts: 11.0.1.18
  gather_facts: False
  vars:
    user:
      shencan:
        name: shencan
        shell: bash
      ruifengyun:
        name: ruifengyun
        shell: zsh
  tasks:
   - name: debug loops
     debug: msg="name --> {{ item.key }} value --> {{ item.value.name }} shell --> {{ item.value.shell }}"
     with_dict: "{{ user }}"

[root@ansible01 ansible]# ansible-playbook loops4.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************

TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item={u'key': u'ruifengyun', u'value': {u'shell': u'zsh', u'name': u'ruifengyun'}}) => {
    "msg": "name --> ruifengyun value --> ruifengyun shell --> zsh"
}
ok: [11.0.1.18] => (item={u'key': u'shencan', u'value': {u'shell': u'bash', u'name': u'shencan'}}) => {
    "msg": "name --> shencan value --> shencan shell --> bash"
}

PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

4. 文件匹配loops

我们针对一个目录下指定格式的文件进行处理时,可以直接引用with_fileglob循环去匹配我们需要处理的文件即可,如下:

复制代码
[root@ansible01 ansible]# cat /etc/ansible/loops5.yaml 
---
- hosts: 11.0.1.18
  gather_facts: False
  tasks:
   - name: debug loops
     debug: msg="files --> {{ item }}"
     with_fileglob:
      - /etc/ansible/*.yaml 
[root@ansible01 ansible]# ansible-playbook loops5.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************

TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=/etc/ansible/loops2.yaml) => {
    "msg": "files --> /etc/ansible/loops2.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/loops3.yaml) => {
    "msg": "files --> /etc/ansible/loops3.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/loops5.yaml) => {
    "msg": "files --> /etc/ansible/loops5.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/loops4.yaml) => {
    "msg": "files --> /etc/ansible/loops4.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/variable.yaml) => {
    "msg": "files --> /etc/ansible/variable.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/variable2.yaml) => {
    "msg": "files --> /etc/ansible/variable2.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/loops.yaml) => {
    "msg": "files --> /etc/ansible/loops.yaml"
}

PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

with_fileglob 这个时候会匹配/etc/ansible下所有的yaml结尾的文件,当作{{ item }}变量来引用。

原理是使用了python glob模块去做的文件模糊匹配。

5. 随机选择loops

with_random_choice会从传入的list里面随机选择一个,作为item引用的参数

复制代码
[root@ansible01 ansible]# cat loops6.yaml 
---
- hosts: 11.0.1.18
  gather_facts: False
  tasks:
   - name: debug loops
     debug: msg="names --> {{ item }}"
     with_random_choice:
      - "ansible1"
      - "ansible2"
      - "ansible3"
[root@ansible01 ansible]# ansible-playbook loops6.yaml 
PLAY [11.0.1.18] **************************************************************************************************************************************************************************

TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=ansible3) => {
    "msg": "names --> ansible3"
}

PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

6. 条件判断loops

有时候执行一个task后,我们需要检测这个task的结果是否达到了预想状态,如果没有达到我们预想的状态时,就需要退出整个playbook执行,这个时候我们需要对某个task结果一直进行循环检测,如下:

复制代码
[root@ansible01 ansible]# cat loops7.yaml 
---
- hosts: 11.0.1.18
  gather_facts: False
  tasks:
   - name: debug loops
     shell: cat /etc/ansible/hosts
     register: host
     until: host.stdout.startswith("Master")
     retries: 5
     delay: 5
[root@ansible01 ansible]# ansible-playbook loops7.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************

TASK [debug loops] ************************************************************************************************************************************************************************
FAILED - RETRYING: debug loops (5 retries left).
FAILED - RETRYING: debug loops (4 retries left).
FAILED - RETRYING: debug loops (3 retries left).
FAILED - RETRYING: debug loops (2 retries left).
FAILED - RETRYING: debug loops (1 retries left).
fatal: [11.0.1.18]: FAILED! => {"attempts": 5, "changed": true, "cmd": "cat /etc/ansible/hosts", "delta": "0:00:00.005700", "end": "2024-04-30 09:49:27.614588", "rc": 0, "start": "2024-04-30 09:49:27.608888", "stderr": "", "stderr_lines": [], "stdout": "# This is the default ansible 'hosts' file.\n#\n# It should live in /etc/ansible/hosts\n#\n#   - Comments begin with the '#' character\n#   - Blank lines are ignored\n#   - Groups of hosts are delimited by [header] elements\n#   - You can enter hostnames or ip addresses\n#   - A hostname/ip can be a member of multiple groups\n\n# Ex 1: Ungrouped hosts, specify before any group headers.\n\n## green.example.com\n## blue.example.com\n## 192.168.100.1\n## 192.168.100.10\n\n# Ex 2: A collection of hosts belonging to the 'webservers' group\n\n## [webservers]\n## alpha.example.org\n## beta.example.org\n## 192.168.1.100\n## 192.168.1.110\n\n# If you have multiple hosts following a pattern you can specify\n# them like this:\n\n## www[001:006].example.com\n\n# Ex 3: A collection of database servers in the 'dbservers' group\n\n## [dbservers]\n## \n## db01.intranet.mydomain.net\n## db02.intranet.mydomain.net\n## 10.25.1.56\n## 10.25.1.57\n\n# Here's another example of host ranges, this time there are no\n# leading 0s:\n#11.0.1.18\tkey=118\n#11.0.1.19\tkey=119\n[nginx]\n11.0.1.1[8:9]\n[nginx:vars]\nansible_python_interpreter=/usr/bin/python2.7", "stdout_lines": ["# This is the default ansible 'hosts' file.", "#", "# It should live in /etc/ansible/hosts", "#", "#   - Comments begin with the '#' character", "#   - Blank lines are ignored", "#   - Groups of hosts are delimited by [header] elements", "#   - You can enter hostnames or ip addresses", "#   - A hostname/ip can be a member of multiple groups", "", "# Ex 1: Ungrouped hosts, specify before any group headers.", "", "## green.example.com", "## blue.example.com", "## 192.168.100.1", "## 192.168.100.10", "", "# Ex 2: A collection of hosts belonging to the 'webservers' group", "", "## [webservers]", "## alpha.example.org", "## beta.example.org", "## 192.168.1.100", "## 192.168.1.110", "", "# If you have multiple hosts following a pattern you can specify", "# them like this:", "", "## www[001:006].example.com", "", "# Ex 3: A collection of database servers in the 'dbservers' group", "", "## [dbservers]", "## ", "## db01.intranet.mydomain.net", "## db02.intranet.mydomain.net", "## 10.25.1.56", "## 10.25.1.57", "", "# Here's another example of host ranges, this time there are no", "# leading 0s:", "#11.0.1.18\tkey=118", "#11.0.1.19\tkey=119", "[nginx]", "11.0.1.1[8:9]", "[nginx:vars]", "ansible_python_interpreter=/usr/bin/python2.7"]}

PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

5s执行一次cat /etc/ansible/hosts,将结果register给host然后判断host.stdout.startswith的内容是否Master字符串开头,如果条件成立,此task运行完成,如果条件不成立5s后再重试,5次后还不成立,此task运行失败。

7. 文件优先匹配loops

这个与第4个文件匹配类似,就新增了一个优选项,如下:

复制代码
[root@ansible01 ansible]# cat loops8.yaml 
---
- hosts: 11.0.1.18
  gather_facts: False
  tasks:
   - name: debug loops
     debug: msg="files --> {{ item }}"
     with_first_found:
      - "wyx.yaml"
[root@ansible01 ansible]# ansible-playbook loops8.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************

TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=/etc/ansible/wyx.yaml) => {
    "msg": "files --> /etc/ansible/wyx.yaml"
}

PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
相关推荐
孙克旭_3 天前
day051-ansible循环、判断与jinja2模板
linux·运维·服务器·网络·ansible
leo__5205 天前
自动化运维:使用Ansible简化日常任务
运维·自动化·ansible
风清再凯10 天前
自动化工具ansible,以及playbook剧本
运维·自动化·ansible
IT乌鸦坐飞机10 天前
ansible部署数据库服务随机启动并创建用户和设置用户有完全权限
数据库·ansible·centos7
遇见火星24 天前
如何使用Ansible一键部署MinIO集群?
ansible
粥周粥24 天前
ANSIBLE
ansible
码农101号24 天前
Linux中ansible模块补充和playbook讲解
linux·运维·ansible
码农101号24 天前
Linux的Ansible软件基础使用讲解和ssh远程连接
ansible
烟雨书信25 天前
ANSIBLE运维自动化管理端部署
运维·自动化·ansible
碎碎-li25 天前
ANSIBLE(运维自动化)
运维·自动化·ansible