Ansible test lab in Docker

We gaan een Ansible test lab inrichten. Deze bestaat dan uit:
– Ansible Manager server
– Target1 machine
– Target2 machine

Al deze servers worden voorzien van CentOS 7 en de inventory file van Ansible zal ervoor zorgen dat we met de Ansible ping module de beide targets kunnen benaderen middels ssh.

Op de targets wordt hiervoor een gebruiker ‘ansible’ aangemaakt die op de target-servers gebruikt wordt als account voor de ansible-playbooks.

Images aanmaken

Ervan uitgaande dat Docker is geïnstalleerd, gaan we eerst CentOS7 image downloaden, vervolgens maken we een nieuwe image aan waarin we met behulp van het yum-commando de ssh daemon en ansible installeren. Dit kan allemaal gedaan worden met een Dockerfile. De inhoud wordt alsvolgt:

FROM centos:centos7
MAINTAINER The CentOS Project cloud-ops@centos.org

RUN yum -y update; yum clean all
RUN yum -y install openssh-server ansible net-tools passwd; yum clean all

ADD ./inventory /inventory

RUN /usr/bin/ssh-keygen -A
ENTRYPOINT ["/usr/sbin/sshd", "-D"

Het bestand inventory is voor Ansible en ziet er alsvolgt uit:

[all]
target1 ansible_host=172.11.0.3 ansible_user=ansible ansible_password=ansible
target2 ansible_host=172.11.0.4 ansible_user=ansible ansible_password=ansible

We moeten er dus voor zorgen dat de machines het juiste IP adres krijgen. Dat gaan we doen door straks de IP adressen mee te geven in de docker-compose.yml file. Maar eerst gaan we een image maken met bovenstaande twee bestanden en geven hier een tag aan genaamd centos7ansible:

$ docker build -t centos7ansible .

Denk om de laatste . (punt) De output van het build-commando laat de stappen zien en met ‘docker images‘ kunnen we de nieuwe image zien.

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos7ansible latest ffcba64c8c61 6 hours ago 380MB

Nu kun je een nieuwe Dockerfile maken voor de beide target-servers. Het enige verschil is dat op de target-servers de ansible service niet nodig is. Wel hebben we op de nodes ook een ssh daemon nodig zodat Ansible de servers kan benaderen via ssh. Hier maken we de ansible gebruiker aan via het bash-script start.sh. De inhoud van start.sh ziet er zo uit

#!/bin/bash

__create_user() {
# Create the ansible user for SSH
useradd ansible
SSH_USERPASS=ansible
echo -e "$SSH_USERPASS\n$SSH_USERPASS" | (passwd --stdin ansible)
echo ssh ansible password: $SSH_USERPASS
}

# Call all functions
__create_user

Het bestand Dockerfile gaat er alsvolgt uit zien:

FROM centos:centos7
MAINTAINER The CentOS Project cloud-ops@centos.org

RUN yum -y update; yum clean all
RUN yum -y install openssh-server net-tools passwd; yum clean all

ADD ./start.sh /start.sh

RUN /usr/bin/ssh-keygen -A
RUN chmod 755 /start.sh
RUN ./start.sh
ENTRYPOINT ["/usr/sbin/sshd", "-D"]

Net zoals de image van centos7ansible maken we nu een image maar dan met de tag centos7target:

docker build -t centos7target .

Denk om de laatste . (punt) De output van het build-commando laat de stappen zien en met ‘docker images‘ kunnen we de beide images zien:

$ docker image
REPOSITORY TAG IMAGE ID CREATED SIZE
centos7ansible latest 1d8a1c4f0e43 8 minutes ago 380MB
centos7target latest d847c0fcd4da 14 minutes ago 320MB

Containers maken

Met het bestand docker-compose.yml maken we de containers. Dit bestand ziet er alsvolgt uit:

version: '2.1'
services:
target1:
image: centos7target
container_name: target1
ports:
- "22"
networks:
ansible_network:
ipv4_address: 172.11.0.3
target2:
image: centos7target
container_name: target2
ports:
- "22"
networks:
ansible_network:
ipv4_address: 172.11.0.4
ansible:
image: centos7ansible
container_name: ansible
ports:
- "22"
networks:
ansible_network:
ipv4_address: 172.11.0.2
networks:
ansible_network:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.11.0.0/16
gateway: 172.11.0.1

Uitleg:

De version aan het begin van dit bestand geeft aan welke commando’s geldig zijn. Er worden met enige regelmaat nieuwe versies uitgebracht en daarmee kunnen commando’s vervangen zijn door andere commando’s, of parameters op een andere manier gedefinieerd zijn. Raadplaag de docker website voor updates.

services geeft aan welke containers we gaan gebruiken, in dit geval de 3 eerdere genoemde servers. De target-servers gebruiken de aangemaakte image centos7target en de Ansible server gebruikt centos7ansible. De container_names spreken voor zich en elk gebruikt poort 22 (ssh) om een verbinding te kunnen maken via het IPv4 adres dat opgegeven is. Hiervoor wordt een nieuw network gemaakt genaamd ansible_network met de config-parameters zoals aangegeven.

Het commando om de containers te starten is:

$ docker-compose up -d

Waarbij de -d parameter gebruikt wordt om de containers op de achtergrond te draaien (detached). Het commando ‘docker ps’ laat zien wat er draait.

$ docker-compose up -d
Creating network "ansible_ansible_network" with driver "bridge"
Creating target2 … done
Creating ansible … done
Creating target1 … done

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a2a0c48d42f9 centos7target "/usr/sbin/sshd -D" 7 seconds ago Up 5 seconds 0.0.0.0:32784->22/tcp target1
2c9491bc736e centos7target "/usr/sbin/sshd -D" 7 seconds ago Up 5 seconds 0.0.0.0:32782->22/tcp target2
ea010959d326 centos7ansible "/usr/sbin/sshd -D" 7 seconds ago Up 5 seconds 0.0.0.0:32783->22/tcp ansible

We hadden nu een gebruiker aan kunnen maken op de Ansible server waarmee we kunnen inloggen via ssh maar we kunnen ook het docker exec; commando gebruiken om een bash shell op te starten in de Ansible container:

$ docker exec -it ansible bash

Nu kunnen we het volgende ansible-commando gebruiken om de twee target-servers te controleren:

# ansible -m ping all -i inventory

Het resultaat zou zoiets moeten zijn:

target1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
target2 | SUCCESS => {
"changed": false,
"ping": "pong"
}