【问题标题】:Ansible: Get all the IP addresses of a groupAnsible:获取一个组的所有 IP 地址
【发布时间】:2016-03-31 09:07:43
【问题描述】:

让我们想象一个这样的库存文件:

node-01 ansible_ssh_host=192.168.100.101
node-02 ansible_ssh_host=192.168.100.102
node-03 ansible_ssh_host=192.168.100.103
node-04 ansible_ssh_host=192.168.100.104
node-05 ansible_ssh_host=192.168.100.105

[mainnodes]
node-[01:04]

在我的剧本中,我现在想创建一些变量,其中包含mainnodes 组的 IP 地址:

vars:
  main_nodes_ips: "192.168.100.101,192.168.100.102,192.168.100.103,192.168.100.104"
  main_nodes_ips_with_port: "192.168.100.101:3000,192.168.100.102:3000,192.168.100.103:3000,192.168.100.104:3000"

这是我目前得到的:

vars:
  main_nodes_ips: "{{groups['mainnodes']|join(',')}}"
  main_nodes_ips_with_port: "{{groups['mainnodes']|join(':3000,')}}"

但这将使用主机名而不是 IP 地址。

有什么想法可以做到这一点吗?

更新

看了一会儿文档,我想这可以让我遍历所有的 ip 地址:

{% for host in groups['mainnodes'] %}
    {{hostvars[host]['ansible_ssh_host']}}
{% endfor %}

但我只是不知道如何创建一个包含所有这些 IP 的数组。这样我就可以对它们使用|join() 命令。

更新 2:
我只是以为我已经弄明白了......但事实证明你不能在剧本中使用 {% %} 语法......或者我可以吗? 那么在 vars 部分它没有。 :/

vars:
  {% set main_nodes_ip_arr=[] %}
  {% for host in groups['mesos-slave'] %}
     {% if main_nodes_ip_arr.insert(loop.index,hostvars[host]['ansible_ssh_host']) %} {% endif %}
  {% endfor %}
  main_nodes_ips: "{{main_nodes_ip_arr|join(',')}}"
  main_nodes_ips_with_port: "{{main_nodes_ip_arr|join(':3000,')}}"

【问题讨论】:

  • 对于使用 2.0+ 版本的任何人,ansible_ssh_host 已被弃用。此解决方案仍然有效,但您需要将其替换为 ansible_host
  • 您写道,您对自己的分析器不太满意。你已经非常接近最佳实践了。请现在将 McKelvins 设置为接受的。 stackoverflow.com/a/39932728/2898712 谢谢。

标签: ansible jinja2 ansible-playbook


【解决方案1】:

我发现了魔法map extracthere

main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_host']) | join(',') }}"
main_nodes_ips_with_port: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_host']) | join(':3000,') }}:3000"

另一种选择(想法来自here):

main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_eth0', 'ipv4', 'address']) | join(',') }}"

(假设接口是eth0

【讨论】:

  • 对 RedHat 的大中指表示感谢,因为它破坏了 Ansible 支持门户。第二个链接失效了。
  • 请注意,仅当所有服务器的所有主接口都设置为 eth0 时,替代方案才有效
  • 还要注意 ansible_ssh_host 自 ansible 2.0 起已重命名为 ansible_host
  • 谢谢@wedi。已更新。
  • 对于第二部分ansible_default_ipv4 可能更可靠,因为接口名称已经变得不可预测......
【解决方案2】:

我不久前遇到了这个问题,这就是我想出的(不是最佳的,但它有效)

---
# playbook.yml
  - hosts: localhost
    connection: local

    tasks:
      - name: create deploy template
        template:
          src: iplist.txt
          dest: /tmp/iplist.txt
      - include_vars: /tmp/iplist.txt

      - debug: var=ip

模板文件是

ip:
{% for h in groups['webservers'] %}
 - {{ hostvars[h].ansible_ssh_host }}
{% endfor %}

【讨论】:

  • 为此创建一个任务似乎有点矫枉过正。
【解决方案3】:

这对我有用。不依赖接口名

- main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_default_ipv4', 'address']) | join(',') }}"

【讨论】:

  • 也适合我。非常感谢
【解决方案4】:
- name: Create List of nodes to be added into Cluster
  set_fact: nodelist={%for host in groups['mygroup']%}"{{hostvars[host].ansible_eth0.ipv4.address}}"{% if not loop.last %},{% endif %}{% endfor %}

 - debug: msg=[{{nodelist}}]

 - name: Set Cluster node list in config file
   lineinfile:
         path: "/etc/myfonfig.cfg"
         line: "hosts: [{{ nodelist }}]"

作为结果,您将在配置文件中包含以下行:

hosts: ["192.168.126.38","192.168.126.39","192.168.126.40"]

【讨论】:

    【解决方案5】:

    我现在可以自己工作了。我对这个解决方案不太满意,但它会做的:

    main_nodes_ips: "{% set IP_ARR=[] %}{% for host in groups['mainnodes'] %}{% if IP_ARR.insert(loop.index,hostvars[host]['ansible_ssh_host']) %}{% endif %}{% endfor %}{{IP_ARR|join(',')}}"
    main_nodes_ips_with_port: "{% set IP_ARR=[] %}{% for host in groups['mainnodes'] %}{% if IP_ARR.insert(loop.index,hostvars[host]['ansible_ssh_host']) %}{% endif %}{% endfor %}{{IP_ARR|join(':3000,')}
    

    【讨论】:

    • @McKelvin 的回答应该是公认的解决方案,因为它远远优于这个解决方案以及 Ansible 官方文档推荐的解决方案。
    【解决方案6】:

    我通过在剧本中使用 ansible 事实来做到这一点。 该剧本采用 ansible_all_ipv4_addresses 列表和 ansible_nodename(实际上是完全限定的域名),遍历所有主机并将数据保存在本地主机上的 localpath_to_save_ips 文件中。您可以将 localpath_to_save_ips 更改为本地主机上的绝对路径。

    ---
    - hosts: all
      become: yes
      gather_facts: yes
    
      tasks:
      - name: get ip
        local_action: shell echo {{ ansible_all_ipv4_addresses }} {{ ansible_nodename }} >> localpath_to_save_ips

    【讨论】:

    • 虽然此代码 sn-p 可以解决问题,但 including an explanation 有助于提高您的回复质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
    【解决方案7】:

    当以下任何一项为真时,我找到了访问其他组 ip 的“唯一方法”:

    • 一些成员还没有被 ansible 引导
    • 使用串行
    • 组不是剧本的一部分

    如下:

    {% set ips=[] %}{% for host in groups['othergroup'] %}{% if ips.append(lookup('dig', host)) %}{% endif %}{% endfor %}{{ ips }}
    

    在运行ansible的机器上需要dnspython,安装通过

    sudo apt-get install python-dnspython
    

    如果有人在条件下知道更好的方法,我很想摆脱这种可憎的东西。

    【讨论】:

      【解决方案8】:

      这是我为了不被依赖 eth0 所做的(感谢 ADV-IT 的回答):

      - name: gathering facts
        hosts: mainnodes
        gather_facts: true
      
      - hosts: mainnodes
        tasks:
          - name: Create List of nodes
            set_fact: nodelist={%for host in groups['mainnodes']%}"{{hostvars[host]['ansible_env'].SSH_CONNECTION.split(' ')[2]}}"{% if not loop.last %},{% endif %}{% endfor %}
      
      

      【讨论】:

        【解决方案9】:

        我在获取另一个组中节点的 IP 地址时遇到了类似的问题。 使用如下构造: the_ip: "{{ hostvars[groups['master'][0]]['ansible_default_ipv4'].address }}" 仅在运行组 master 时才有效,这不是我的剧本的一部分(我在 localhost 上运行)。 我通过在剧本中添加额外的剧本来克服这个问题,例如:

        - hosts: master
          gather_facts: yes
          become: no
          vars: 
            - the_master_ip: "{{ hostvars[groups['master'][0]]['ansible_default_ipv4'].address }}"
          tasks:
          - debug: var=the_master_ip
          - set_fact: the_ip={{ the_master_ip }}
        

        之后我可以在剧本的下一个剧本中使用the_ip

        这也可以解决@Petroldrake 提到的可憎?

        【讨论】:

        【解决方案10】:

        ##只需使用 -ansible_default_ipv4.address- 获取 Ip 并重定向到本地文件然后使用它

        • 名称:gathering_facts 主机:主机 收集事实:真 任务:

          • 名称:重定向到文件 外壳:回声“{{ansible_default_ipv4.address}}”>>ipss.txt delegate_to: 本地主机

        【讨论】:

        • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-09-04
        • 2017-11-10
        • 1970-01-01
        • 1970-01-01
        • 2011-07-13
        • 1970-01-01
        • 2014-12-31
        相关资源
        最近更新 更多