我正在部署一个小型的 3 节点集群,并且我想将我的清单中定义的公共 IP 地址添加到所有节点的 /etc/hosts 文件中。
我正在尝试使用以下命令,但它给出了一个错误:
- name: Add IP address of all hosts to all hosts
lineinfile:
dest: /etc/hosts
line: '{{ hostvars[item]["ansible_host"] }} {{ hostvars[item]["ansible_hostname"] }} {{ hostvars[item]["ansible_nodename"] }}'
state: present
with_items: groups['all']
错误是:
致命:[app1.domain.com]:失败! => {“失败”:true,“msg”:“字段“args”具有无效值,似乎包含未定义的变量。错误为:“ansible.vars.hostvars.HostVars 对象”没有属性 u“groups['all']”\n\n错误似乎出现在“/Users/k/Projects/Ansible/roles/common/tasks/main.yml”中:第 29 行,第 3 列,但可能\n位于文件的其他位置,具体取决于确切的语法问题。\n\n有问题的行似乎是:\n\n\n- 名称:将所有主机的 IP 地址添加到所有主机\n ^ 此处\n”}
对于我遗漏的内容有什么想法吗?
答案1
上面的答案根本不起作用,因为当主机的 IP 地址发生变化时,它会为同一主机添加新行,而不是修改现有行。
以下解决方案考虑了特定服务器的 IP 地址何时发生变化,并通过仅修改行而不是添加重复条目来很好地处理它。
---
- name: Add IP address of all hosts to all hosts
lineinfile:
dest: /etc/hosts
regexp: '.*{{ item }}$'
line: "{{ hostvars[item].ansible_host }} {{item}}"
state: present
when: hostvars[item].ansible_host is defined
with_items: "{{ groups.all }}"
答案2
看起来你的语法有错误。你使用的 ansible 是哪个版本?变量名可能不同。2.2
这个版本对我来说是有效的:
- name: Add IP address of all hosts to all hosts
lineinfile:
dest: /etc/hosts
line: "{{ hostvars[item].ansible_host }} {{ hostvars[item].inventory_hostname }} {{ hostvars[item].inventory_hostname_short }}"
state: present
with_items: "{{ groups.all }}"
更新
Basil 考虑过 IP 发生变化的情况。在这种情况下,最好使用他建议的解决方案:
- name: Add IP address of all hosts to all hosts
lineinfile:
dest: /etc/hosts
regexp: '.*{{ item }}$'
line: "{{ hostvars[item].ansible_host }} {{item}}"
state: present
when: hostvars[item].ansible_host is defined
with_items: "{{ groups.all }}"
答案3
我遇到了同样的问题,以下是我为任何感兴趣的人提供的解决方案。
主机/dev.ini
[controller]
controller1 ansible_ssh_host=10.11.11.10
controller2 ansible_ssh_host=10.11.11.11
controller3 ansible_ssh_host=10.11.11.12
[compute]
compute1 ansible_ssh_host=10.11.11.13
compute2 ansible_ssh_host=10.11.11.14
compute3 ansible_ssh_host=10.11.11.15
[block]
block1 ansible_ssh_host=10.11.11.16
block2 ansible_ssh_host=10.11.11.17
[haproxy]
haproxy1 ansible_ssh_host=10.11.11.18
[nginx]
nginx1 ansible_ssh_host=10.11.11.19
[deployment]
deployment ansible_ssh_host=10.11.11.20
[all:vars]
ansible_python_interpreter=/usr/bin/python3
任务/main.yml
---
- name: Update /etc/hosts
become: true
blockinfile:
path: /etc/hosts
create: yes
block: |
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
{% for item in ansible_play_batch %}
{{ hostvars[item].ansible_ssh_host }} {{ item }}
{% endfor %}
笔记:
- Python 3.7.5 Ansible 2.9.0
- 我决定使用 blockinfile 而不是使用模板,因为 hostvars 上下文未在模板内更新。而且我很着急 :-)。
答案4
在 Ansible2.5 中,这是一个可行的解决方案,我已经使用ansible_env.SSH_CONNECTION
变量来获取远程服务器 IP,但未ansible_host
在收集的事实中定义。
- name: Update the /etc/hosts file with node name
tags: etchostsupdate
become: yes
become_user: root
lineinfile:
path: "/etc/hosts"
regexp: "{{ hostvars[item]['ansible_env'].SSH_CONNECTION.split(' ')[2] }}\t{{ hostvars[item]['ansible_hostname']}}\t{{ hostvars[item]['ansible_hostname']}}"
line: "{{ hostvars[item]['ansible_env'].SSH_CONNECTION.split(' ')[2] }}\t{{ hostvars[item]['ansible_hostname']}}\t{{ hostvars[item]['ansible_hostname']}}"
state: present
backup: yes
register: etchostsupdate
when: ansible_hostname != "{{ item }}"
with_items: "{{groups['app']}}"