如何使用Ansible Playbook遍历主机的N级子级? [英] How to iterate through N level children of hosts using Ansible Playbook?

查看:115
本文介绍了如何使用Ansible Playbook遍历主机的N级子级?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道如何使用host_vars来实现这一目标,但是它的问题是主机文件可能会令人费解,因此我倾向于使用ini文件,可以将所有数据放在一个文件中.这篇 SO 帖子帮助我如何将集合放入特定主机的变量中的想法.

I know how to achieve this using host_vars but the problem with it is the host files can get convoluted so I'm leaning towards ini files where I can put all the data in one file. This SO post helped me have an idea how to put a collection in a variable for a particular host.

我有这个样本清单:

;hosts.yml
[web1]
example1.com databases=["example1_com","mysql"]
example2.com databases=["example1_com","mysql"]

[web1:vars]
ansible_host=10.0.16.21

[web2]
example3.com databases=["example3_com"]
example4.com databases=["example4_com","mysql"]

[web2:vars]
ansible_host=10.0.16.22

[web:children]
web1
web2

现在,我想使用web组遍历每个主机,并遍历databases主机变量.

Now I wanted to loop through each hosts using the the web group and iterate through the databases host var.

我做了这样的事情:

---
- debug:
    msg: "{{ item }} - {{ hostvars[item]['databases'] }} "
  with_items:
    - "{{ groups['web'] }}"

,输出为:

ok: [localhost] => (item=example1.com) => {
    "item": "example1.com", 
    "msg": "example1.com - [example1_com,mysql] "
}
ok: [localhost] => (item=example2.com) => {
    "item": "example2.com", 
    "msg": "example2.com - [example1_com,mysql] "
}
ok: [localhost] => (item=example3.com) => {
    "item": "example3.com", 
    "msg": "example3.com - [example3_com] "
}
ok: [localhost] => (item=example4.com) => {
    "item": "example4.com", 
    "msg": "example4.com - [example4_com,mysql] "
}

我尝试使用with_sublements循环实现这一目标,但问题是第二个元素需要动态,而with_subelements则不可能.

I tried achieving this using with_sublements loop but the problem is the 2nd element needs to be dynamic which is not possible with_subelements.

with_subelements:
    - "{{ groups['web'] }}"
    - {{ hostvars[item]['databases'] }} #item is dynamic, this will cause an undefined host error.

推荐答案

对于我来说,目前还不是100%清楚您的原始方法是什么,以及问题中的代码是否代表您的新方法(因为您仍在引用) hostvars).我认为您需要在运行剧本时仅在想要的主机上运行任务时,在剧本(hosts: web)或命令行(-l web)中指定想要影响的组,而不是尝试以便在任务本身内部动态获取组.

It's not 100% clear to me what your original approach was, and if the code in your question was meant to represent your new approach (since you are still referencing hostvars there). I think you need to work more with specifying the groups you want affected within the playbook (hosts: web) or on the command line (-l web) when running the playbook to run the tasks only for those hosts you want, rather than trying to get the group dynamically within the task itself.

关于链接的问题/答案,其中讨论了在变量内定义列表的方法:您需要确保将列表数据用单引号引起来,例如'["example1_com","mysql"]'.

Regarding the linked question/answer, where a way of defining a list within a variable was discussed: you need to make sure to enclose the list data within single quotes, e.g. '["example1_com","mysql"]'.

鉴于此,如果只想从清单文件中定义的主机变量中遍历列表,则可以执行以下操作:

Given that, if you simply want to iterate over a list from a host variable defined in an inventory file, you can do the following:

库存文件"inv"

[web1]
example1.com databases='["example1_com","mysql"]'
example2.com databases='["example1_com","mysql"]'

[web1:vars]
ansible_host=10.0.16.21

[web2]
example3.com databases='["example3_com"]'
example4.com databases='["example4_com","mysql"]'

[web2:vars]
ansible_host=10.0.16.22

[web:children]
web1
web2

Playbook文件"test.yml"

---
- hosts: web
  gather_facts: no
  tasks:
    - debug: msg="Host is {{ inventory_hostname }}. Database is {{ item }}"
      with_items:
        - "{{ databases }}"

然后您可以运行该剧本:

You can then run the playbook:

ansible-playbook test.yml -i inv

生成以下输出:

PLAY ***************************************************************************

TASK [debug] *******************************************************************
ok: [example3.com] => (item=example3_com) => {
    "item": "example3_com", 
    "msg": "Host is example3.com. Database is example3_com"
}
ok: [example1.com] => (item=example1_com) => {
    "item": "example1_com", 
    "msg": "Host is example1.com. Database is example1_com"
}
ok: [example1.com] => (item=mysql) => {
    "item": "mysql", 
    "msg": "Host is example1.com. Database is mysql"
}
ok: [example2.com] => (item=example1_com) => {
    "item": "example1_com", 
    "msg": "Host is example2.com. Database is example1_com"
}
ok: [example2.com] => (item=mysql) => {
    "item": "mysql", 
    "msg": "Host is example2.com. Database is mysql"
}
ok: [example4.com] => (item=example4_com) => {
    "item": "example4_com", 
    "msg": "Host is example4.com. Database is example4_com"
}
ok: [example4.com] => (item=mysql) => {
    "item": "mysql", 
    "msg": "Host is example4.com. Database is mysql"
}

PLAY RECAP *********************************************************************
example1.com               : ok=1    changed=0    unreachable=0    failed=0   
example2.com               : ok=1    changed=0    unreachable=0    failed=0   
example3.com               : ok=1    changed=0    unreachable=0    failed=0   
example4.com               : ok=1    changed=0    unreachable=0    failed=0   

如果您正确构造了剧本,还可以将其设置为针对不同的主机组运行不同的任务集(也许包括来自外部文件的任务,因此您要进行干燥).或者,您可以只在剧本中指定hosts: all,然后使用命令行限制仅针对特定的一组主机运行任务.

If you properly structure your playbook, you can also set it up to run different sets of tasks for different host groups (perhaps including the tasks from an external file so you DRY). Or you could simply specify hosts: all in the playbook, and use command line limiting to only run the tasks against a specific set of hosts.

这篇关于如何使用Ansible Playbook遍历主机的N级子级?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆