Ansible:获取当前目标主机的IP地址

161
如何在角色中获取当前主机的IP地址?
我知道您可以获取主机所属组的列表和主机名,但是我无法找到获取IP地址的解决方案。
您可以使用{{inventory_hostname}}获取主机名,并使用{{group_names}}获取组。
我尝试了一些方法,如{{ hostvars[{{ inventory_hostname }}]['ansible_ssh_host'] }}ip="{{ hostvars.{{ inventory_hostname }}.ansible_ssh_host }}"
12个回答

176

所有地址的列表都存储在事实ansible_all_ipv4_addresses中,其中默认地址是ansible_default_ipv4.address

---
- hosts: localhost
  connection: local
  tasks:
    - debug: var=ansible_all_ipv4_addresses
    - debug: var=ansible_default_ipv4.address

然后每个网络接口都分配了地址... 在这种情况下,您可以显示所有的事实并找到具有您想要使用的值的那一个。


1
你能列出任务内的所有标志吗? - SJC
2
@SJC 标志?您是指事实,对吗?是的,请运行setup:模块,并使用register:allfacts进行显示,然后使用- debug:var = allfacts - techraf
10
为了使其正常工作,gather_facts的值必须为true。默认情况下它是真的,但如果不需要有关主机的信息,则可以将其设置为false。 - shshnk
3
答案不正确。默认 IP 地址不一定是 Ansible 在执行期间使用的地址。 - poige
3
@poige 如果您提出一个新问题,这可能是不正确的。 - techraf
显示剩余4条评论

96

您可以从hostvars、字典ansible_default_ipv4和键address中获取IP地址。

hostvars[inventory_hostname]['ansible_default_ipv4']['address']

分别是 IPv4 和 IPv6 地址。

hostvars[inventory_hostname]['ansible_default_ipv6']['address']

一个示例剧本:

---
- hosts: localhost
  tasks:
    - debug: var=hostvars[inventory_hostname]['ansible_default_ipv4']['address']
    - debug: var=hostvars[inventory_hostname]['ansible_default_ipv6']['address']

2
这可能在某些情况下会失败,请参见:https://medium.com/opsops/ansible-default-ipv4-is-not-what-you-think-edb8ab154b10 - RafalS
这不是 Ansible 连接的地址。它可能匹配,但不一定是。 - LogicDaemon

33

只需使用 ansible_ssh_host 变量即可。

playbook_example.yml

- hosts: host1
  tasks:
  - name: Show host's ip
    debug:
      msg: "{{ ansible_ssh_host }}"

hosts.yml

[hosts]
host1   ansible_host=1.2.3.4

结果

TASK [Show host's ip] *********************************************************************************************************************************************************************************************
ok: [host1] => {
     "msg": "1.2.3.4"
}

7
Ansible 2.0已将“ssh”从ansible_ssh_host中弃用。如果ansible_host包含主机名而不是IP地址,则ansible_ssh_host也可以使用。 - LogicDaemon
1
我目前正在使用 Ansible 的 2.10 版本,这段代码在我的情况下运行得非常好。 - Andrey Bistrinin

29
您可以在模板文件 template.j2 中使用 {{ ansible_eth0.ipv4.address }},就如同使用{{inventory_hostname}}一样。
注:请参考以下博客文章,以获取更多关于如何使用 Ansible 收集远程主机信息的信息:如何使用 Ansible 收集远程主机信息
希望能对有需要的人有所帮助。

17
要特别小心。现在默认的网络接口不总是“eth0”。它有时被称为ens3enp2s0等等。如果您使用ansible_default_ipv4,则有更好的选择,如果它不起作用,则切换回寻找一些合理的默认值。 - Gabor Garami
7
可能过去这个方法是可行的,但在 Ansible 2.7 中,这个变量未定义。 - Dirk
这不是 Ansible 连接的地址。它可能匹配,但并不一定。 - LogicDaemon

13

简单的调试命令:

ansible -i inventory/hosts.yaml -m debug -a "var=hostvars[inventory_hostname]" all

输出:

"hostvars[inventory_hostname]": {
    "ansible_check_mode": false, 
    "ansible_diff_mode": false, 
    "ansible_facts": {}, 
    "ansible_forks": 5, 
    "ansible_host": "192.168.10.125", 
    "ansible_inventory_sources": [
        "/root/workspace/ansible-minicros/inventory/hosts.yaml"
    ], 
    "ansible_playbook_python": "/usr/bin/python2", 
    "ansible_port": 65532, 
    "ansible_verbosity": 0, 
    "ansible_version": {
        "full": "2.8.5", 
        "major": 2, 
        "minor": 8, 
        "revision": 5, 
        "string": "2.8.5"
    }, 

获取主机IP地址:

ansible -i inventory/hosts.yaml -m debug -a "var=hostvars[inventory_hostname].ansible_host" all

zk01 | SUCCESS => {
    "hostvars[inventory_hostname].ansible_host": "192.168.10.125"
}

2
ansible_host 可能包含主机名。 - LogicDaemon
1
就像@LogicDaemon所说,“ansible_host”是您在清单中定义的任何内容,因此这并不总是打印IP地址。 - Arcsector

10

ansible_default_ipv4.address 看似是普通的 IP 地址,但在 某些情况下 可能与您想象的不同,建议使用以下语句进行操作:

ansible_default_ipv4.address|default(ansible_all_ipv4_addresses[0])

1
这应该是被接受的答案,根据文档 - Arcsector

7
另一种查找公共IP的方法是使用uri模块:
    - name: Find my public ip
      uri: 
        url: http://ifconfig.me/ip
        return_content: yes
      register: ip_response

你的IP地址将会在ip_response.content中。


另一个返回相同结果的服务URL是:https://ipecho.net/plain - Paul Parker
@PaulParker https://ipecho.net/plain 似乎不可用或需要API令牌... ifconfig.me是一个更好且稳定的服务,多年来一直如此:+1 - bastien
从未被要求提供API令牌。我无法保证服务的一致性,因为我没有监控它,但它从未让我失望过。 - Paul Parker

6
请查看此链接:http://docs.ansible.com/ansible/latest/plugins/lookup/dig.html 在模板中的使用示例如下:
{{ lookup('dig', ansible_host) }}

注意:

  • 由于清单中不仅可以使用DNS名称,因此最好添加一个检查以确保它不是IP
  • 显然,对于间接主机规范(例如使用跳转主机),此收据将无法按预期工作

但仍然可以满足99%的使用情况(比喻说)。


1
如果环境中不使用DNS,那该怎么办? - techraf
1
如果ansible_host不是所讨论的主机的IP地址,该怎么办? - techraf
这是与“and what”不同的内容,只是“what”,因为你之前提出的问题不算在内,请注意。 - poige
1
我不知道你所谓的“真实IP地址”是什么。你知道一些虚假的吗? - poige
真实IP地址是设置在目标设备上的。与您可能访问服务器的IP地址不同。 - techraf
显示剩余7条评论

5

如果您想获取外部公共IP地址,并且您在AWS或Azure等云环境中,您可以使用ipify_facts模块

# TODO: SECURITY: This requires that we trust ipify to provide the correct public IP. We could run our own ipify server.
- name: Get my public IP from ipify.org
  ipify_facts:

这将把公共IP地址放入变量ipify_public_ip中。

这并不总是有效的。对我来说,ipify_public_ip变量是空的。 - Davide
2
对于AWS,inventory_hostname将是IP地址。 - Berend de Boer
这个插件只能在特定的情况下工作,如果你是从NAT后面访问互联网,它将无法工作。基本上,当服务器可以访问互联网并且可以访问ipify.org网站以解析其外部IP时,它才能正常工作。 - slm
1
@BerenddeBoer 错了。inventory_hostname 是在清单中设置的任何内容。它可以是在.ssh/config中设置的主机名。 - admirabilis
@slm,就像我之前说的,如果你正在寻找外部公共IP地址。如果你在NAT后面,那么你将没有一个外部可访问的公共IP地址,因此你不会使用这种方法。 - Simon Woodside

1
以下代码片段将返回远程机器的公共IP和默认IP(即:局域网)。
这将以引号形式打印IP,以避免在使用配置文件时产生混淆。

>> main.yml

---
- hosts: localhost
  tasks:
    - name: ipify
      ipify_facts:
    - debug: var=hostvars[inventory_hostname]['ipify_public_ip']
    - debug: var=hostvars[inventory_hostname]['ansible_default_ipv4']['address']
    - name: template
      template:
        src: debug.j2
        dest: /tmp/debug.ansible

>> templates/debug.j2

public_ip={{ hostvars[inventory_hostname]['ipify_public_ip'] }}
public_ip_in_quotes="{{ hostvars[inventory_hostname]['ipify_public_ip'] }}"

default_ipv4={{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}
default_ipv4_in_quotes="{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}"


2
你的一些评论会提高这个答案。 - Marged
1
"ipify:" 是一个社区模块。您很快需要使用 community.general.ipify: 来访问它。在 SO 上,仅包含代码的答案是不被鼓励的。请解释这是如何工作的。 - Jeter-work

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接