Yugang Zhou
Yugang Zhou

Reputation: 7283

How can I configure /etc/hosts with ansible orchestration

The application needs the following hosts:

[foo-servers]
foo-server ansible_ssh_host=192.168.50.2 

[bar-servers]
bar-server ansible_ssh_host=192.168.50.3 

[mysql-servers]
mysql-server ansible_ssh_host=192.168.50.4 

[mongodb-servers]
mongodb-server ansible_ssh_host=192.168.50.5 

I need to configure hosts on foo server and bar server as they need to access mysql and mongodb. To achieve this, I introduce a role named hosts:

# roles/hosts/tasks/main.yml
---
- name: change hosts
template: src=hosts.j2 dest=/etc/hosts

# roles/hosts/templates/hosts.j2
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

{% for item in hostvars %}
{{ hostvars[item]['ansible_ssh_host'] }} {{ item }}
{% endfor %}

The problem is when I run

ansible-playbook foo.yml 

The /etc/hosts on the target only contains the ip and hostname of the current host, foo-server in this case.

My question is:

How can I get all hosts in the inventory when I run playbook against only one of them?

Or could you suggest some alternatives as I get the wrong idea at the first place.

The alternatives come to my mind are:

Make hosts configuration an individual playbook against all hosts like

---
- name: Configuring hosts
  hosts: all
  user: root

  roles:
    - hosts

The drawback is I need to run this playbook before others and this seems not a right way to use roles.

Upvotes: 8

Views: 34677

Answers (4)

Danny
Danny

Reputation: 1

i am using vagrant to provision MV, but i was not working the hostmanager plugin, so in ansible helped this solution.

        - name: hosts to all hosts
  blockinfile:
    dest: /etc/hosts
    block: |
      {% for host in groups['all'] %}
      {{ hostvars[host]['ansible_facts']['hostname'] }} {{ hostvars[host]['ansible_facts']['enp0s8']['ipv4']['address'] }}
      {% endfor %}
    state: present

cat /etc/hosts " -# BEGIN ANSIBLE MANAGED BLOCK K8SETCD11 192.168.56.11 K8SETCD12 192.168.56.12 -# END ANSIBLE MANAGED BLOCK "

Upvotes: 0

leucos
leucos

Reputation: 18269

Indeed this is weird, since even the docs say :

If, at this point, you haven’t talked to that host yet in any play in the playbook or set of playbooks, you can get at the variables, but you will not be able to see the facts.

I understand from this that you might not get gathered facts if host hasn't been "queried" yet, but you still should see variables defined in inventory (and group/host vars). May be you should push that to the mailing list.

In the mean time, you can solve your problem using groups['all'] to loop over your hosts instead :

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

{% for item in groups['all'] %}
{{ hostvars[item]['ansible_ssh_host'] }} {{ item }}
{% endfor %}

Upvotes: 8

Vipul HK
Vipul HK

Reputation: 71

I had the same issue and here is my solution for anyone who is interested.

hosts/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

tasks/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 %}

Notes:

  • python 3.7.5 ansible 2.9.0
  • I decided to go with blockinfile instead of using templates because hostvars context was not getting updated inside the template. Plus I was in a hurry :-).

Upvotes: 0

Abdennour TOUMI
Abdennour TOUMI

Reputation: 93333

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

{% for host in groups['all'] %}

{{ hostvars[host].ansible_default_ipv4.address }} {{ host  }}   {{ hostvars[host].ansible_fqdn }}

{% endfor  %}

Upvotes: 1

Related Questions