mkerins
mkerins

Reputation: 23

Ansible docker connection with identical container names on more than one host

I'm trying to run an ansible playbook against multiple hosts that are running containers using the same name. There are 3 hosts each running a container called "web". I'm trying to use the docker connection.

I'm using the typical pattern of a hosts file which works fine for running ansible modules on the host.

- name: Ping
  ping:

- name: Add web container to inventory
  add_host:
    name: web
    ansible_connection: docker
    ansible_docker_extra_args: "-H=tcp://{{ ansible_host }}:2375"
    ansible_user: root
  changed_when: false

- name: Remove old logging directory
  delegate_to: web
  file:
    state: absent
    path: /var/log/old_logs

It only works against the first host in the hosts file

PLAY [all]

TASK [Gathering Facts]
ok: [web1]
ok: [web2]
ok: [web3]


TASK [web-playbook : Ping]
ok: [web1]
ok: [web2]
ok: [web3]

TASK [web-playbook : Add sensor container to inventory] 
ok: [web1]

PLAY RECAP 
web1  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web2  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web3  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

I've tried setting name to web_{{ ansible_host }} to make it unique between hosts but it then tries to connect to web_web1. I've been running the commands using sudo docker exec web rm -rf /var/log/old_logs which of course works, but I'd like to be able to use the ansible modules directly in the docker containers.

Upvotes: 2

Views: 1398

Answers (1)

Zeitounator
Zeitounator

Reputation: 44799

The result you get is absolutely expected. Quoting the add_host documentation

This module bypasses the play host loop and only runs once for all the hosts in the play, if you need it to iterate use a with-loop construct.

i.e. you cannot rely on the hosts loop for the add_host and need to make a loop yourself.

Moreover, you definitely need to have different names (i.e. inventory_hostname) for your dynamically created hosts but since all your docker containers have the same name, their ansible_host should be the same.

Assuming all your docker host machines are in the group dockerhosts, the following playbook should do the job. I'm currently not in a situation where I can test this myself so you may have to adjust a bit. Let me know if it helped you and if I have to edit my answer.

Note that even though the add_host task will not naturally loop, I kept the hosts on your original group in the first play so that facts are gathered correctly and correctly populated in the hostvars magic variable

---
- name: Create dynamic inventory for docker containers
  hosts: dockerhosts

  tasks:
    - name: Add web container to inventory
      add_host:
        name: "web_{{ item }}"
        groups:
          - dockercontainers
        ansible_connection: docker
        ansible_host: web
        ansible_docker_extra_args: "-H=tcp://{{ hostvars[item].ansible_host }}:2375"
        ansible_user: root
      loop: "{{ groups['dockerhosts'] }}"

- name: Play needed commands on containers
  hosts: dockercontainers

  tasks:
    - name: Remove old logging directory
      file:
        state: absent
        path: /var/log/old_logs

Upvotes: 0

Related Questions