ansible最佳实践之playbook高级循环任务如何操作(代码片段)

山河已无恙 山河已无恙     2022-12-15     299

关键词:

写在前面


  • 今天和小伙伴分享一些ansible剧本中数据迭代的笔记
  • 博文内容比较简单
  • 主要介绍的常见的迭代对比
  • 使用过滤器和查找插件在复杂数据结构上实施迭代循环
  • 食用方式:了解Ansible基础语法
  • 理解不足小伙伴帮忙指正

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。--------王小波


循环和查找插件

Ansible 在 2.5 中引入了loop关键字。以前任务迭代通过使用with_开头并以查找的名称结尾的关键字的方法。与 loop 等效的是 with_list,设计用于在简单的扁平列表中进行迭代,对于简单的列表来讲,loop 是最佳语法。

以下三种语法具有相同的结果,其中第一个使用的loop是首选:

$ cat loop_demo.yaml
---
- name: loop Play
  hosts: servera
  gather_facts: no
  vars:
    - mylist:
        - li
        - rui
        - long
  tasks:
    - name: using loop
      debug: msg= item 
      loop: " mylist "
    - name: using with_list
      debug: msg= item 
      with_list: " mylist "
    - name: using lookup plugin
      debug: msg= item 
      loop: " lookup('list',mylist) "
$

运行剧本是一样的效果,这里第三种方式通过,lookup插件的的方式实现的,lookup 插件是 Jinja2 模板引擎的 Ansible 扩展。通过插件使 Ansible 能够使用外部来源的数据,我们这里使用lookup来将一个数据转化为list

$ ansible-playbook  loop_demo.yaml

PLAY [loop Play] *********************************************************************************************

TASK [using loop] ********************************************************************************************
ok: [servera] => (item=li) => 
    "msg": "li"

ok: [servera] => (item=rui) => 
    "msg": "rui"

ok: [servera] => (item=long) => 
    "msg": "long"


TASK [using with_list] ***************************************************************************************
ok: [servera] => (item=li) => 
    "msg": "li"

ok: [servera] => (item=rui) => 
    "msg": "rui"

ok: [servera] => (item=long) => 
    "msg": "long"


TASK [using lookup plugin] ***********************************************************************************
ok: [servera] => (item=li) => 
    "msg": "li"

ok: [servera] => (item=rui) => 
    "msg": "rui"

ok: [servera] => (item=long) => 
    "msg": "long"


PLAY RECAP ***************************************************************************************************
servera                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

$

使用 loop 关键字替代 with_* 样式的循环具有以下优点:

  • 无需记住或查找 with_* 样式关键字来满足当前迭代场景。
  • 专注于学习 Ansible 中提供的插件和过滤器,适用性比单纯的迭代更广泛。
  • 可以通过ansible-doc -t lookup命令访问查找插件文档,结合插件文档实现复杂遍历

使用loop关键字和dict插件替换"with_dict"关键字

---
- hosts: testB
  remote_user: root
  gather_facts: no
  vars:
    users:
      alice: female
      bob: male
  tasks:
  - debug:
      msg: "item.key is item.value"
    loop: " lookup('dict',users) "

在2.6版本的官网手册中,官方开始推荐使用 loop加filter 的方式来替代"loop加lookup"的方式,

---
- hosts: testB
  remote_user: root
  gather_facts: no
  vars:
    users:
      alice: female
      bob: male
  tasks:
  - debug:
      msg: "item.key is item.value"
    loop: " users | dict2items "

loop 方式还提供了 loop_control属性

可以用于控制循环的行为,添加索引之类,比如,使用loop_control的index_var选项,就能在遍历列表时,将元素对应的索引写入到指定的变量中,除了index_var选项,loop_control还有一些其他的选项可用,此处我们就来总结一下这些选项。

pause选项能够让我们设置每次循环之后的暂停时间,以秒为单位,换句话说就是设置每次循环之间的间隔时间,示例如下

迭代场景示例

在列表的列表上迭代

对于需要多级迭代的嵌套数据,使用传统的循环方式,往往获取不到子数据,即不能实现数据的扁平化处理。

---
- name: loop Play
  hosts: servera
  gather_facts: no
  vars:
    - mylist:
        - ['l','i']
        - rui
        - long
  tasks:
    - name: using loop
      debug: msg= item 
      loop: " mylist "
    - name: using with_list
      debug: msg= item 
      with_list: " mylist "
    - name: using lookup plugin
      debug: msg= item 
      loop: " lookup('list',mylist) "

上面迭代的数据为一个嵌套的list,使用前面所讲的迭代方式不能对嵌套的子数组进行迭代。

三种不同方式的测试,都不能做的扁平化的迭代

$ ansible-playbook  loop_demo.yaml

PLAY [loop Play] *********************************************************************************************

TASK [using loop] ********************************************************************************************
ok: [servera] => (item=['l', 'i']) => 
    "msg": [
        "l",
        "i"
    ]

ok: [servera] => (item=rui) => 
    "msg": "rui"

ok: [servera] => (item=long) => 
    "msg": "long"


TASK [using with_list] ***************************************************************************************
ok: [servera] => (item=['l', 'i']) => 
    "msg": [
        "l",
        "i"
    ]

ok: [servera] => (item=rui) => 
    "msg": "rui"

ok: [servera] => (item=long) => 
    "msg": "long"


TASK [using lookup plugin] ***********************************************************************************
ok: [servera] => (item=['l', 'i']) => 
    "msg": [
        "l",
        "i"
    ]

ok: [servera] => (item=rui) => 
    "msg": "rui"

ok: [servera] => (item=long) => 
    "msg": "long"


PLAY RECAP ***************************************************************************************************
servera                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

这个时候,我们可以使用 with_items 关键字来迭代复杂的列表,实现列表数据的扁平化处理

$ cat loop_demos.yaml
---
- name: loop Play
  hosts: servera
  gather_facts: no
  tasks:
    - name: using with_list
      debug:
        msg: " item "
      with_items:
        - [ 1,2,4 ]
        - [ r,u ]
$ ansible-playbook  loop_demos.yaml

PLAY [loop Play] *********************************************************************************************

TASK [using with_list] ***************************************************************************************
ok: [servera] => (item=1) => 
    "msg": 1

ok: [servera] => (item=2) => 
    "msg": 2

ok: [servera] => (item=4) => 
    "msg": 4

ok: [servera] => (item=r) => 
    "msg": "r"

ok: [servera] => (item=u) => 
    "msg": "u"


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

获取序列

有时候希望在剧本里获取一些序列,可以通过 whit_sequence 关键字实现

$ cat loop_demo_sq.yaml
---
- name: liruilong demo
  hosts: servera
  gather_facts: n
  tasks:
    - name: test whit_sequence
      debug: msg= item 
      with_sequence:
        start=1
        end=5
        stride=1
$ ansible-playbook  loop_demo_sq.yaml

PLAY [liruilong demo] ****************************************************************************************

TASK [test whit_sequence] ************************************************************************************
ok: [servera] => (item=1) => 
    "msg": "1"

ok: [servera] => (item=2) => 
    "msg": "2"

ok: [servera] => (item=3) => 
    "msg": "3"

ok: [servera] => (item=4) => 
    "msg": "4"

ok: [servera] => (item=5) => 
    "msg": "5"


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

flatten 代替 with_items

若希望重构旧的剧本里的 with_items 任务以使用 loop 关键字,可使用 flatten 过滤器。

$ cat loop_demos.yaml
---
- name: loop Play
  hosts: servera
  gather_facts: no
  tasks:
    - name: using with_list
      debug:
        msg: " item "
        #with_items:
      loop:
        - [ 1,2,4,[3,4,5,[6]] ]
        - [ r,u ]
$ ansible-playbook loop_demos.yaml

PLAY [loop Play] *********************************************************************************************
TASK [using with_list] ***************************************************************************************
ok: [servera] => (item=[1, 2, 4, [3, 4, 5, [6]]]) => 
    "msg": [
        1,
        2,
        4,
        [
            3,
            4,
            5,
            [
                6
            ]
        ]
    ]

ok: [servera] => (item=['r', 'u']) => 
    "msg": [
        "r",
        "u"
    ]


PLAY RECAP ***************************************************************************************************
servera                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
$
  • flatten 过滤器将以递归方式搜索嵌入式列表,并从发现的值创建一个列表。

  • flatten 过滤器接受 levels 参数,用于指定搜索嵌入式列表的整数的级别数,levels = 1 与 with_items 隐式进行的相同的一级扁平化。

$ cat loop_demos.yaml
---
- name: loop Play
  hosts: servera
  gather_facts: no
  tasks:
    - name: using with_list
      debug:
        msg: " item "
      loop: " numList | flatten(levels=3) "
      vars:
              numList:
                 - [ 1,2,4,[3,4,5,[6]] ]
                 - [ r,u ]

$

执行测试

$ ansible-playbook loop_demos.yaml

PLAY [loop Play] *********************************************************************************************

TASK [using with_list] ***************************************************************************************
ok: [servera] => (item=1) => 
    "msg": 1

ok: [servera] => (item=2) => 
    "msg": 2

ok: [servera] => (item=4) => 
    "msg": 4

ok: [servera] => (item=3) => 
    "msg": 3

ok: [servera] => (item=4) => 
    "msg": 4

ok: [servera] => (item=5) => 
    "msg": 5

ok: [servera] => (item=6) => 
    "msg": 6

ok: [servera] => (item=r) => 
    "msg": "r"

ok: [servera] => (item=u) => 
    "msg": "u"


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


迭代嵌套列表

subelements 过滤器从 names 变量数据中创建一个新列表。列表中的每一项本身是一个两元素列表。

$ cat  subelements.yaml
---
- name: liruilong demo
  hosts: servera
  vars:
    names:
      - liruilong:
            - key: li
      - liruilong:
            - key: rui
      - liruilong:
            - key: long
  tasks:
    - name: loop demo
      debug: msg= item 
      loop: " names | subelements('liruilong') "

执行测试

$ ansible-playbook subelements.yaml -b

PLAY [liruilong demo] ****************************************************************************************

TASK [Gathering Facts] ***************************************************************************************
ok: [servera]

TASK [loop demo] *********************************************************************************************
ok: [servera] => (item=['liruilong': ['key': 'li'], 'key': 'li']) => 
    "msg": [
        
            "liruilong": [
                
                    "key": "li"
                
            ]
        ,
        
            "key": "li"
        
    ]

ok: [servera] => (item=['liruilong': ['key': 'rui'], 'key': 'rui']) => 
    "msg": [
        
            "liruilong": [
                
                    "key": "rui"
                
            ]
        ,
        
            "key": "rui"
        
    ]

ok: [servera] => (item=['liruilong': ['key': 'long'], 'key': 'long']) => 
    "msg&

ansible最佳实践之playbook执行速度优化(代码片段)

写在前面今天和小伙伴们分享一些Ansible中Playbook执行速度优化的笔记博文通过7种不同的优化方式,合理利用可配置项,从而提高Playbook的执行速度个人感觉如果受控机数量很少,其实没必要速度调优所谓的执行速度调... 查看详情

ansible最佳实践之playbook执行速度优化(代码片段)

写在前面今天和小伙伴们分享一些Ansible中Playbook执行速度优化的笔记博文通过7种不同的优化方式,合理利用可配置项,从而提高Playbook的执行速度个人感觉如果受控机数量很少,其实没必要速度调优所谓的执行速度调... 查看详情

ansible最佳实践之playbook控制任务的执行(代码片段)

写在前面今天和小伙伴们分享一些Ansible中如何控制剧本任务执行的笔记博文内容分为两部分,控制任务执行,和控制主机执行顺序,涉及内容:剧本默认执行顺序分析Demo,先角色后任务import或include导入角色... 查看详情

ansible最佳实践之playbook不同上下文提权demo(代码片段)

写在前面生活加油,今天和小伙伴们分享一些Ansible提权的笔记博文内容涉及如何选择Ansible的提权方式提权策略有哪些提权策略具体的Demo食用方式:需要有Ansible基础,了解Ansible变量的使用理解不足小伙伴帮忙指正近... 查看详情

playbook之ansible

ansibleplaybook最佳实践             http://blog.csdn.net/kellyseeme/article/details/50574340本文出自“运维自动化”博客,请务必保留此出处http://shower.blog.51cto. 查看详情

Ansible 最佳实践不重复常见角色

...述】:在Ansible最佳实践页面上:http://docs.ansible.com/ansible/playbooks_best_practices.html#top-level-playbooks-are-separated-by-role它显示 查看详情

ansible-playbook之loops循环一

...是官方给的参考,参考链接http://docs.ansible.com/ansible/latest/playbooks_loops.html#standard-loops-name:addseveraluser 查看详情

ansible-playbook之循环(loops)

ansible-playbook的循环(Loops)1.标准的Loops:也是最常用的一种循环例:当需要安装10个软件包时,不用写10次任务,只需要写一次然后进行循环即可#注:已经安装的软件系统即不在安装[[email protected] playbook]# cat yum_list.y... 查看详情

ansible最佳实践之awx构建高级作业工作流的创建和调度(代码片段)

...Demo工作流调度和通知的相关介绍食用方式:需要了解Ansible理解不足小伙伴帮忙指正傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我... 查看详情

ansible学习笔记04(最佳实践)(代码片段)

1、使用过滤器处理变量1.1ansiblefilteransible应用变量到playbook并且使用jinja2表达式来使用变量。例如下面的J2表达式中的变量使用两个大括号括起来。J2表达式也支持filter。Filter在playbook或者模板中被用来修改或者处理要替代的变量... 查看详情

自动化运维ansible实践(代码片段)

...装、配置及命令行使用,这篇分享下ansible的高级用法即playbook,在生产环境如果需要完成负责任务,如大批量服务安装配置等,可以采用playbook方式来完成,高效且易于维护。第1章Playbook基本使用使用Playbook的好处特点?易读的编... 查看详情

ansible8:playbook循环

...户并为之赋予权限,操作某个目录下所有文件等等。好在playbook支持循环语句,可以使得某些需求很容易而且很规范的实现。1、with_itemswith_items是playbooks中最基本也是最常用的循环语句:tasks:-name:Secureconfigfile 查看详情

ansible8:playbook循环

...户并为之赋予权限,操作某个目录下所有文件等等。好在playbook支持循环语句,可以使得某些需求很容易而且很规范的实现。1、with_itemswith_items是playbooks中最基本也是最常用的循环语句:tasks:-name:Secureconfigfiles   查看详情

ansible个人学习通过playbook实践批量免密(代码片段)

方法一:直接使用for循环操作拷贝#指令foriin`seq6163`dossh-copy-id-i/root/.ssh/id_rsa.pubuser_name@192.168.31.$idone方法二:使用ansible-playbook实现1、安装ansible[root@~]#yuminstallepel-release-y[root@~]#yuminstallansible-y2、修改an 查看详情

ansible最佳实践之awx使用ansible与api通信(代码片段)

写在前面分享一些AWX使用Ansible与API通信的笔记博文内容涉及:curl方式调用AWXAPI浏览器接口文档方式调用AWXAPI使用API调用方式启动AWX中作业模板Ansible模块uri的简单介绍Ansible剧本方式调用API启动作业模板理解不足小伙伴帮忙指... 查看详情

ansible之playbook

官方文档https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#playbook-keywordsPlaybook核心组件一个playbook中由多个组件组成,其中所用到的常见组件类型如下:Hosts执行的远程主机列表Tasks任务集,由多个task的元素组成的列表... 查看详情

ansible最佳实践之委派任务和事实(代码片段)

写在前面分享一些Ansible委派任务和事实委派的笔记博文内容涉及:Ploybook任务委派DemoPloybook事实委派Demo理解不足小伙伴帮忙指正傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的... 查看详情

运维自动化之ansible--(playbook模式)

运维自动化之ansible--(playbook模式) 一、Ansible Playbook简介  playbook是ansible用于配置,部署,和管理被控节点的剧本。   通过playbook的详细描述,执行其中的一系列tasks,可以让远端主机达到预期的状态。play... 查看详情