Capensis.fr
Support professionnel

Vagrant, Ansible et Docker, un trio efficace


#1

Introduction
Les Technologies
Installation de Vagrant et Ansible
Configuration du Vagrantfile
Configuration du Playbook Ansible
Configuration du fichier Docker-Compose.yml
Conclusion

Introduction

Dans le cadre d’une logique d’intégration continue, nous avons cherché à mettre en place un test automatique dans un environnement jetable de la version dockerisée de notre solution Canopsis.
L’objectif ? Pouvoir la tester sûrement et rapidement.

Les technologies

Pour cela, nous nous sommes appuyés sur 4 technologies :

  • Vagrant : site officiel de Vagrant
    Vagrant est un outil permettant la création et la gestion automatisée de machines virtuelles. Ces VMs s’appellent communément des boxes.
    Vagrant ne crée pas ces VMs seul. Il a recours à des providers, comme Virtual Box, LXC ou Docker.
  • Ansible : site officiel de Ansible
    Comme indiqué dans notre article Zoom sur Ansible, pourquoi utiliser cette technologie de gestion de configuration ? , Ansible fait aujourd’hui partie de notre quotidien. C’est une technologie d’industrialisation simple et efficace.
  • Docker : site officiel de Docker
    Docker est l’outil de conteneurisation n°1 actuellement.
    Optimisé avec son outil Docker-Compose, il permet de déployer et configurer de manière automatisée un ou plusieurs conteneurs.
    Nous y avons notamment recours pour la création d’une version dockerisée de Canopsis.
  • Inspec : site officiel de Inspec
    L’outil Inspec vous a déjà été préalablement présenté, avec un exemple pratique de mise en place sur notre outil Canopsis dockerisé, dans l’article A la découverte de Inspec.
    Pour le citer, “Inspec est un framework qui a pour mission de tester votre infra selon vos règles d’intégration, de conformité, de sécurité et autres pré-requis qui vous sont propres afin de débusquer des régressions ou anomalies dans vos déploiements.

Le but est de mettre en place le scénario suivant :

  • la création d’une Vagrant Box
  • Le déclenchement d’un rôle Ansible qui va :
    • installer Docker et Docker-Compose au sein de la Vagrant Box
    • Faire un GIT clone d’un dépôt où se trouve le fichier Docker-Compose de notre démo Canopsis
    • Lancer les conteneurs Docker au sein de la Vagrant Box
    • Installer Inspec au sein de la VagrantBox
    • Faire un GIT clone du rôle Ansible pour le test Inspec sur Canopsis
    • Lancer le rôle Ansible pour le test Inspec sur Canopsis
    • Laisser ce rôle faire un GIT clone du profil Inspec pour le test sur Canopsis
    • Laisser ce rôle exécuter le test Inspec au sein de la Vagrant Box

Installation de Vagrant et Ansible
Seuls Vagrant et Ansible (ainsi qu’un provider pour Vagrant, dans notre cas nous avons choisi Virtual Box) doivent être installés sur la machine hôte.
Vagrant
Les derniers paquets d’installation de Vagrant sont disponibles sur cette page : http://www.vagrantup.com/downloads.html.

Ansible
Les dernières instructions d’installation de Ansible sont disponibles sur cette page: http://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-the-control-machine.

On peut également l’installer via pip avec la commande

$ sudo pip install ansible

Configuration du Vagrantfile
Création et configuration d’un Vagrantfile qui lance du Ansible
On configure la création et l’exécution de la Vagrant Box via un fichier nommé Vagrantfile.

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/bionic64"
  config.vm.define "Vagrant-Ansible-Docker"
  config.ssh.forward_agent = true
  config.vm.provider "virtualbox" do |v|
    end

    config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.extra_vars = {
    DOCKER_COMPOSE_REPO: "gitlab_repo_for_docker_compose.git",
    INSPEC_ANSIBLE_REPO: "gitlab_repo_for_ansible_inspec_role.git"
    }
  end

end

Quelques explications sur ce fichier :

config.vm.box = "ubuntu/bionic64"
config.vm.define Vagrant-Ansible-Docker
config.ssh.forward_agent = true

Signifie que l’on va utiliser la Vagrant Box ubuntu/bionic64 et que la VM s’appellera Vagrant-Ansible-Docker.
On active également le SSH agent forwarding pour que la machine puisse cloner les dépôts GITLAB.

config.vm.provider "virtualbox" do |v|
end

S’assure que Vagrant va utiliser Virtual Box comme provider

config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"

Lance Ansible avec le fichier playbook.yml.
Si on ne stipule pas de fichier d’inventaire, Vagrant en génèrera et utilisera automatiquement un. Sauf cas particuliers (besoin de stipuler une adresse IP particulière à la VM ainsi qu’un port SSH spécial), il est préférable de laisser Vagrant générer le fichier d’inventaire.

    ansible.extra_vars = {
    DOCKER_COMPOSE_REPO: "gitlab_repo_for_docker_compose.git",
    INSPEC_ANSIBLE_REPO: "gitlab_repo_for_ansible_inspec_role.git"
    }

On définit deux variables : DOCKER_COMPOSE_REPO et INSPEC_ANSIBLE_REPO.
On peut utiliser ansible.extra_vars pour définir toutes les variables que l’on désire que Ansible prenne en compte. Si nous n’en stipulons aucune, aucune variable ne sera définie. En effet, Vagrant ne va pas chercher et attribuer de lui-même à Ansible des variables définies dans un fichier externe.

Configuration du Playbook Ansible
Pour exécuter Ansible, nous utilisons un fichier playbook.yml
Exemple de fichier playbook pour Ansible :

- name: Install Canopsis
   gather_facts: no
   hosts: Vagrant-Ansible-Docker
   become: true
   tasks:
  - name: Install Ansible, Docker, Docker-Compose
     apt:
       name: "{{item}}"
       state: latest
       update_cache: yes
     with_items:
       - git
       - ansible
       - docker
       - docker-compose
  - name: Clone repository with docker-compose files
     git:
       repo: "{{DOCKER_COMPOSE_REPO}}"
       accept_hostkey: yes
       clone: yes
       update: yes
       force: yes
       ssh_opts: -o ForwardAgent=yes 
       dest: "/vagrant"
     become_user: vagrant
  - docker_service:
       project_src: /vagrant/
       files: docker-compose.yml
       state: present
  - name: Install Inspec
     apt:
       deb: https://packages.chef.io/files/stable/inspec/2.2.16/ubuntu/18.04/inspec_2.2.16-1_amd64.deb
  - name: Clone Inspec Ansible role for Canopsis
     git:
       repo: "{{INSPEC_ANSIBLE_REPO}}"
       accept_hostkey: yes
       clone: yes
       update: yes
       force: yes
       ssh_opts: -o ForwardAgent=yes 
       dest: /vagrant/roles/inspec_ansible_role"
     become_user: vagrant
  - name: Download Docker.py
     get_url:
       url: https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/docker.py
       dest: /tmp/docker.py
       mode: "a+x"
  - name: Run Inspec role
     shell: ansible-playbook -i /tmp/docker.py -i inventory_local.yml playbook_local.yml
     become_user: vagrant
     args:
       chdir: /vagrant

Quelques explications sur ce fichier :

- name: Install Canopsis
   gather_facts: no
   hosts: Vagrant-Ansible-Docker
   become: true

Cela indique que le playbook va s’exécuter sur la machine dont le nom est Vagrant-Ansible-Docker (le nom que l’on a donné à la machine dans le Vagrantfile) et avec les droits SUDO.

  - name: Install Ansible, Docker, Docker-Compose
     apt:
       name: "{{item}}"
       state: latest
       update_cache: yes
     with_items:
       - git
       - ansible
       - docker
       - docker-compose

Cette commande APT installe les paquets GIT, Ansible, Docker et Docker-Compose depuis les dépôts.

  - name: Clone repository with docker-compose files
     git:
       repo: "{{DOCKER_COMPOSE_REPO}}"
       accept_hostkey: yes
       clone: yes
       update: yes
       force: yes
       ssh_opts: -o ForwardAgent=yes 
       dest: "/vagrant"
     become_user: vagrant

Cette commande GIT clone le dépôt où se trouve le fichier docker-compose.yml (dépôt défini dans le fichier Vagrantfile) dans le répertoire /vagrant.

  - docker_service:
       project_src: /vagrant/
       files: docker-compose.yml
       state: present

Cette commande DOCKER-SERVICE exécute un docker-compose up sur le fichier /vagrant/docker-compose.yml.

NOTE : À la place de la la commande docker_service, on peut utiliser une commande shell pour lancer le docker-compose :

- name: docker-compose up
   shell: docker-compose up -d
   args:
     chdir: /vagrant

C’est utile lorsque l’on veut avoir recours à des fichiers .env contenant des variables d’environnement. Car, si Ansible sait parfaitement les prendre en compte lorsqu’il est lancé directement, il ne le fait pas lorsqu’il est utilisé via Vagrant.
La ruse dans ce cas est donc pour nous de faire exécuter directement la commande shell.

  - name: Install Inspec
     apt:
       deb: https://packages.chef.io/files/stable/inspec/2.2.16/ubuntu/18.04/inspec_2.2.16-1_amd64.deb

Cette commande APT installe Inspec avec le fichier .DEB indiqué.

  - name: Clone Inspec Ansible role for Canopsis
     git:
       repo: "{{INSPEC_ANSIBLE_REPO}}"
       accept_hostkey: yes
       clone: yes
       update: yes
       force: yes
       ssh_opts: -o ForwardAgent=yes 
       dest: /vagrant/roles/inspec_ansible_role"
     become_user: vagrant

Cette commande GIT clone le dépôt où se trouve le rôle Ansible pour utiliser Inspec sur Canopsis dans le dossier /vagrant/roles/inspec_ansible_repo

  - name: Download Docker.py
     get_url:
       url: https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/docker.py
       dest: /tmp/docker.py
       mode: "a+x"

Cette commande GET-URL télécharge le fichier docker.py dans le dossier /tmp et le rend exécutable. C’est un fichier Python qui permet de générer un inventaire dynamique des conteneurs Docker.
Il est nécessaire à notre rôle Ansible pour Inspec.
Il nous oblige cependant à l’exécuter depuis la machine invité pour qu’il puisse faire l’inventaire des conteneurs en exécution dans la machine invité.
Cela nous force donc à exécuter le rôle Ansible pour Inspec depuis la machine invité.

  - name: Run Inspec role
     shell: ansible-playbook -i /tmp/docker.py -i inventory_local.yml playbook_local.yml
     become_user: vagrant
     args:
       chdir: /vagrant

Cette commande SHELL lance donc le playbook /vagrant/playbook_local.yml avec comme fichiers d’inventaire /tmp/docker.py et inventory_local.yml.
En complément, nous avons donc un fichier playbook_local.yml indiquant l’exécution sur la machine localhost du rôle inspec_ansible_role.

- hosts: all
  gather_facts: no
  roles: 
    - inspec_ansible_role

Et un fichier d’inventaire inventory_local.yml

localhost ansible_connection=local

Configuration du fichier Docker-Compose.yml
C’est un fichier au format YAML (le même que celui du playbook d’Ansible) qui liste les différents containers et leurs configurations respectives.
Extrait d’un fichier docker-compose qui lance le conteneur rabbitmq et expose ses ports 5672 et 15672 ainsi que le conteneur mongo en exposant son port 27017 :

---
version: '2'
services:
  rabbitmq:
    image: rabbitmq
    ports:
      - "5672:5672"
      - "15672:15672"
  mongodb:
    image: mongo
    ports:
      - "27017:27017"

Une fois nos fichiers VAGRANTFILE, PLAYBOOK.YML et DOCKER-COMPOSE.YML configurés, on lance le tout avec la commande

$ vagrant up

Conclusion
Il est possible de faire coopérer Vagrant, Ansible et Docker pour systématiser la mise en place et le test de conteneurs Docker. Si cela demande un peu d’attention et de ruse pour contourner certaines limites, comme pour les variables, on peut toutefois aboutir à un véritable environnement de test et des résultats clairs de manière systématisé.