Итак, я развертываю небольшой кластер из 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]: НЕ ПРОШЛО! => {"failed": true, "msg": "поле 'args' имеет недопустимое значение, которое, по-видимому, включает неопределенную переменную. Ошибка была: 'ansible.vars.hostvars.HostVars object' не имеет атрибут u \ "groups ['all'] \" \ n \ nОшибка, похоже, была в '/Users/k/Projects/Ansible/roles/common/tasks/main.yml': строка 29, столбец 3, но может \ n находиться где-нибудь в файле в зависимости от точной синтаксической проблемы. \ n \ nСтрока, вызывающая нарушение, выглядит так: \ n \ n \ n- name: Добавить IP-адреса всех хостов ко всем хостам \ n ^ здесь \ n "}
Я не уверен, что происходит. Я все еще новичок в Ansible и до сих пор был доволен своим прогрессом. Любые идеи о том, что мне не хватает?
Предыдущий ответ просто не работает, потому что он добавляет новую строку для того же хоста вместо изменения существующей строки при изменении 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 }}"
Похоже, у вас есть ошибки в синтаксисе. И какую версию 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 }}"
ОБНОВИТЬ
Василий задумывался о ситуациях, когда 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 }}"
У меня была такая же проблема, и вот мое решение для всех, кому это интересно.
[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
---
- 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 %}
Ноты:
В 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']}}"
Я объединил гболо решение и этот решение с добавлением локального имени хоста в / etc / hosts, а также убедитесь, что не ошиблись с именами хостов, такими как s1
и ss1
друг с другом
- name: add hostname to /etc/hosts
vars:
comment: '# added by ansible'
lineinfile:
dest: /etc/hosts
regexp: "127[.]0[.]0[.]1.*"
line: "127.0.0.1 localhost.localdomain localhost {{ ansible_hostname }} {{ comment }}"
state: present
backup: yes
- name: add IP address of all hosts to /etc/hosts
vars:
comment: '# added by ansible'
lineinfile:
dest: /etc/hosts
regexp: ".* {{ item }} {{ comment }}"
line: "{{ hostvars[item]['ansible_env'].SSH_CONNECTION.split(' ')[2] }} {{ item }} {{ comment }}"
state: present
backup: yes
when: ansible_hostname != item
loop: "{{ query('inventory_hostnames', 'all') }}"
В раствор от Василия А довольно гибкий, но он может оставлять избыточные записи, если вы измените имя хоста или удалите хосты из инвентаря. По этой причине я создал немного доработанную версию решение от Vipul HK, с помощью blockinfile
вместо того lineinfile
:
- name: Add Ansible inventory mappings to /etc/hosts
become: true
blockinfile:
path: /etc/hosts
block: |
{% for host in groups['all'] %}
{{ hostvars[host].ansible_host }} {{ host }}
{% endfor %}
Это решение гарантирует, что сопоставления хостов в /etc/hosts
всегда совпадает с теми, что указаны в файле инвентаря.