Un script bash et docker pour vous aider à développer des rôles ansible

Print Friendly, PDF & Email

Ce script n’a presque pas pris une ride depuis ces premiers pas sur le chaine youtube. Eh oui c’était la première vidéo de la chaine xavki. Je l’ai légèrement toiletté et j’ai bien sûr mis à jour l’image docker avec une version plus récente de Debian (10).

Il m’est très utilise pour mes formations ansible.

Lorsque j’ai créé ce script, j’avais besoin de tester régulièrement les rôles que je développais. J’utilisais déjà un peu vagrant et je trouvais que lancer une machine virtuelle demandais du temps. Et comme pour bien développer du ansible, il me semble très important de tout casser pour tout refaire, je me suis réorienté vers des conteneurs docker. Après coup, LXD/LXC serait encore plus optimal, ces conteneurs étant des conteneurs systèmes.

Bref, à l’époque j’ai creusé et cherchais comment avoir des conteneurs avec SSH et systemD. Finalement cela n’est pas très compliqué après avoir installé systemd, il suffit de supprimer quelques répertoires et de monter ceux de la machine en dessous.

Cependant attention, cela signifie aussi de lancer ces conteneurs en privileged. Donc tout cela cumulé, rend ce concept très défaillant d’un point de vue sécurité et non sécurisable. Il faut donc l’utiliser et supprimer les conteneurs après utilisation. En tout cas c’est ce que je recommande fortement.

Le Dockerfile d’une Debian avec SSH et SystemD

Je vous propose donc le Dockerfile suivant :

FROM debian:10

ENV container docker
ENV LC_ALL C
ENV DEBIAN_FRONTEND noninteractive

RUN echo 'deb http://deb.debian.org/debian stretch-backports main' >> /etc/apt/sources.list

RUN apt-get update \
    && apt-get install -y --no-install-recommends systemd python3 sudo bash net-tools openssh-server openssh-client vim git\
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's/#PermitRootLogin/PermitRootLogin/' /etc/ssh/sshd_config
RUN rm -f /lib/systemd/system/multi-user.target.wants/* \
    /etc/systemd/system/*.wants/* \
    /lib/systemd/system/local-fs.target.wants/* \
    /lib/systemd/system/sockets.target.wants/*udev* \
    /lib/systemd/system/sockets.target.wants/*initctl* \
    /lib/systemd/system/sysinit.target.wants/systemd-tmpfiles-setup* \
    /lib/systemd/system/systemd-update-utmp*

RUN ln -s /lib/systemd/system /sbin/init
RUN systemctl set-default multi-user.target
RUN sed -i 's#root:\*#root:sa3tHJ3/KuYvI#' /etc/shadow
ENV init /lib/systemd/systemd
VOLUME [ "/sys/fs/cgroup" ]

ENTRYPOINT ["/lib/systemd/systemd"]

Plusieurs remarques donc :

  • on installe ssh et systemd
  • on permet le root login avec ssh
  • on supprime de nombreux liens systemd car notre conteneur ne dispose pas de son propre matériel
  • on définit un passsowr pour root (“password” par défaut)
  • on prévoit de monter /sysS
  • on lance en entrypoint : systemd (donc ssh n’est pas lancé en l’état)
Découvrez  [Docker] : Comment prendre en compte un proxy pour puller/pusher et comment le passer dans un conteneur ?

Lancer un conteneur avec SSH/SystemD

Voici comment lancer avec un simple docker run un conteneur avec cette image

Là encore rien de très compliqué :

docker run -d --cap-add NET_ADMIN --cap-add SYS_ADMIN --publish-all=true -v /srv/data:/srv/html -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name <nom_contneeur> -h <nom_conteneur> priximmo/debian_systemd:v1.0

On permet une élévation de privilège de notre conteneur sur notre hosts sur les capabilities NET_ADMIN et SYS_ADMIN.

On publie tous les ports pour pouvoir utiliser les applicatifs sur l’ip du conteneur sans se poser de question.

On monte un répertoire d’échange entre le host et le conteneur pour /srv/data.

On monte en lecture seul /sys/fs/cgroup.

Maintenant on automatise le lancement des conteneurs avec un script bash

L’enjeu est tout de même de pouvoir créer à la volée des conteneurs. Et d’essayer de gagner du temps dans le développement ansible. Au passage, bien sûr, ce script est utilisable dans d’autres cas d’utilisation (testing, dev…).

Voici le script que je vous propose et que vous pourrez personnaliser et compléter à votre goût.

#!/bin/bash

############################################################
#
#  Description : déploiement à la volée de conteneur docker
#
#  Auteur : Xavier
#
#  Date : 28/12/2018 - V2.0
#
###########################################################


# Functions #########################################################

help(){
echo "

Options :
		- --create : lancer des conteneurs

		- --drop : supprimer les conteneurs créer par le deploy.sh
	
		- --infos : caractéristiques des conteneurs (ip, nom, user...)

		- --start : redémarrage des conteneurs

		- --ansible : déploiement arborescence ansible

"

}

createNodes() {
	# définition du nombre de conteneur
	nb_machine=1
	[ "$1" != "" ] && nb_machine=$1
	# setting min/max
	min=1
	max=0

	# récupération de idmax
	idmax=`docker ps -a --format '{{ .Names}}' | awk -F "-" -v user="$USER" '$0 ~ user"-debian" {print $3}' | sort -r |head -1`
	# redéfinition de min et max
	min=$(($idmax + 1))
	max=$(($idmax + $nb_machine))

	# lancement des conteneurs
	for i in $(seq $min $max);do
		docker run -tid --privileged --publish-all=true -v /srv/data:/srv/html -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name $USER-debian-$i -h $USER-debian-$i priximmo/buster-systemd-ssh
		docker exec -ti $USER-debian-$i /bin/sh -c "useradd -m -p sa3tHJ3/KuYvI $USER"
		docker exec -ti $USER-debian-$i /bin/sh -c "mkdir  ${HOME}/.ssh && chmod 700 ${HOME}/.ssh && chown $USER:$USER $HOME/.ssh"
	docker cp $HOME/.ssh/id_rsa.pub $USER-debian-$i:$HOME/.ssh/authorized_keys
	docker exec -ti $USER-debian-$i /bin/sh -c "chmod 600 ${HOME}/.ssh/authorized_keys && chown $USER:$USER $HOME/.ssh/authorized_keys"
		docker exec -ti $USER-debian-$i /bin/sh -c "echo '$USER   ALL=(ALL) NOPASSWD: ALL'>>/etc/sudoers"
		docker exec -ti $USER-debian-$i /bin/sh -c "service ssh start"
		echo "Conteneur $USER-debian-$i créé"
	done
	infosNodes	

}

dropNodes(){
	echo "Suppression des conteneurs..."
	docker rm -f $(docker ps -a | grep $USER-debian | awk '{print $1}')
	echo "Fin de la suppression"
}

startNodes(){
	echo ""
	docker start $(docker ps -a | grep $USER-debian | awk '{print $1}')
  for conteneur in $(docker ps -a | grep $USER-debian | awk '{print $1}');do
		docker exec -ti $conteneur /bin/sh -c "service ssh start"
  done
	echo ""
}


createAnsible(){
	echo ""
  	ANSIBLE_DIR="ansible_dir"
  	mkdir -p $ANSIBLE_DIR
  	echo "all:" > $ANSIBLE_DIR/00_inventory.yml
	echo "  vars:" >> $ANSIBLE_DIR/00_inventory.yml
    echo "    ansible_python_interpreter: /usr/bin/python3" >> $ANSIBLE_DIR/00_inventory.yml
  echo "  hosts:" >> $ANSIBLE_DIR/00_inventory.yml
  for conteneur in $(docker ps -a | grep $USER-debian | awk '{print $1}');do      
    docker inspect -f '    {{.NetworkSettings.IPAddress }}:' $conteneur >> $ANSIBLE_DIR/00_inventory.yml
  done
  mkdir -p $ANSIBLE_DIR/host_vars
  mkdir -p $ANSIBLE_DIR/group_vars
	echo ""
}

infosNodes(){
	echo ""
	echo "Informations des conteneurs : "
	echo ""
	for conteneur in $(docker ps -a | grep $USER-debian | awk '{print $1}');do      
		docker inspect -f '   => {{.Name}} - {{.NetworkSettings.IPAddress }}' $conteneur
	done
	echo ""
}



# Let's Go !!! ###################################################################""

#si option --create
if [ "$1" == "--create" ];then
	createNodes $2

# si option --drop
elif [ "$1" == "--drop" ];then
	dropNodes

# si option --start
elif [ "$1" == "--start" ];then
	startNodes

# si option --ansible
elif [ "$1" == "--ansible" ];then
	createAnsible

# si option --infos
elif [ "$1" == "--infos" ];then
	infosNodes

# si aucune option affichage de l'aide
else
	help

fi

Plusieurs options sont prévues :

  • –create : la création de conteneurs en ajoutant à cette option un nombre pour indiquer le nombre de docker souhaités
  • –drop : pour supprimer les conteneurs lancés avec ce script
  • –start : en cas d’arrêt et de relance de votre machine, les conteneurs seront stoppés, cette options permet de les relancer à la volée
  • –ansilbe : créé un répertoire dédié aux développements ansible avec notamment un inventory déjà rempli et complété par les ip de chacun des conteneurs
  • –infos : pour lister les ip des conteneurs créés
Découvrez  [Docker][Ansible] : comment se créer un mini datacenter de test sans VM ? (parc de conteneurs)

Bien sûr on organise tout cela avec des fonctions bash. La plus fournie étant la fonction de création qui notamment :

  • créé un user du même nom du user qui lance le script
  • lui définit un password par défaut à “password”
  • lui copie votre clef publique dans le authorized_keys
  • lance ssh (cf dans notre dockerfile on ne lançait que systemd et pas sshd)

Voilà, j’ai déjà eu pas mal de retour positifs ou de gens qui ont customisé ce script. Certains ont ajouté d’autres OS également. A vous de voir et de vous faire plaisir en personnalisant tout cela et en l’adaptant au mieux à votre cas d’utilisation.

Tout le code source est ici.