Ansible:获取组的所有IP地址

For*_*vin 40 jinja2 ansible ansible-playbook

让我们假设一个像这样的库存文件:

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]
Run Code Online (Sandbox Code Playgroud)

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

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"
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止所得到的:

vars:
  main_nodes_ips: "{{groups['mainnodes']|join(',')}}"
  main_nodes_ips_with_port: "{{groups['mainnodes']|join(':3000,')}}"
Run Code Online (Sandbox Code Playgroud)

但那会使用主机名而不是IP地址.

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

更新:

看了一段时间的文档,我认为这将允许我遍历所有的IP地址:

{% for host in groups['mainnodes'] %}
    {{hostvars[host]['ansible_ssh_host']}}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚如何创建一个包含所有这些IP的数组.这样我就可以|join()对它们使用命令了.

Update2:
我只是觉得我已经弄明白了......但事实证明你不能在剧本中使用{%%}语法......或者我可以吗?在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,')}}"
Run Code Online (Sandbox Code Playgroud)

McK*_*vin 59

我在map extract 这里找到了魔力.

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"
Run Code Online (Sandbox Code Playgroud)

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

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

(假设界面是eth0)

  • RedHat的大中指破坏了Ansible支持门户网站.第二个环节已经死了. (8认同)
  • 并注意,ansible_ssh_host`自ansible 2.0起已重命名为`ansible_host`。 (2认同)
  • 如果您需要为结果列表中的每个项目添加一些后缀(例如端口号),您可以使用: `"{{ groups['backend_servers'] | map('extract', hostvars, ['ansible_host'] ) | 地图('regex_replace', '^(.*)', '\\1:80') | 列表 }}"` (2认同)
  • 对于第二部分,`ansible_default_ipv4`可能更可靠,因为接口名称变得不可预测。 (2认同)

use*_*522 9

我曾经遇到过这个问题,这就是我提出的问题(不是最优的,但它有效)

---
# 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
Run Code Online (Sandbox Code Playgroud)

和模板文件是

ip:
{% for h in groups['webservers'] %}
 - {{ hostvars[h].ansible_ssh_host }}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

  • 为此创建一个任务似乎有点矫枉过正。 (2认同)

Sca*_*ave 9

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

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


For*_*vin 2

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

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,')}
Run Code Online (Sandbox Code Playgroud)

  • @McKelvin 的答案应该是公认的解决方案,因为它远远优于这个解决方案以及 Ansible 官方文档推荐的方法。 (8认同)