09
sep

GauvainOLN&B

Par Gauvain Pocentek, Consultant Senior et expert OpenStack @Objectif Libre

 

Cet article vise à illustrer l’utilisation de l’inventaire in-memory d’Ansible via un exemple concret d’application pour créer et utiliser des conteneurs LXC.

L’objectif

Le module lxc_container d’Ansible permet la création de conteneurs LXC sur un hôte distant.

Bien pratique, mais une fois le conteneur déployé, il reste à l’utiliser pour y déployer une application. Avec Ansible !

 

Une première approche pourrait être l’utilisation de deux playbooks :

  • Le premier déploie les conteneurs et génère un inventaire statique
  • Le second playbook déploie les applications dans les conteneurs en utilisant l’inventaire généré

Une autre approche est l’utilisation d’un playbook unique contenant plusieurs plays.

  • Dans un premier temps Ansible crée les conteneurs, ou récupère leurs informations s’ils existent déjà
  • L’IP de chaque conteneur est ajoutée à l’inventaire in-memory d’Ansible
  • Une fois l’inventaire complété, il est possible d’exécuter les autres plays du playbook pour déployer l’applicatif dans les conteneurs

Un exemple concret

Notre exemple utilise la configuration suivante :

  • Les hôtes LXC sont listés dans le groupe [lxc_hosts] de l’inventaire
  • Pour chaque hôte une liste de conteneurs à gérer est définie dans la variable containers dans host_vars/{{inventory_hostname}}. Cette variable est définie comme suit :
    containers:
      - name: memcached-1
        service: memcache
      - name: mysql-1
        service: mysql
  • Les conteneurs sont connectés sur un bridge lxcbr0, sur un réseau 10.0.100.0/24
  • Les conteneurs sont déployés grâce à un template ubuntu-ansible, basé sur le template ubuntu de base mais facilitant l’utilisation d’Ansible :
    • Installation de python2.7
    • Configuration sudo sans mot de passe
    • Injection d’une clé publique SSH

Le playbook

La première partie du playbook gère la création des conteneurs (si nécessaire) et récupère les IPs affectées dynamiquement à ces conteneurs.

L’attribut service de chaque conteneur définit dans quel groupe de l’inventaire le conteneur sera ajouté :

- hosts: lxc_hosts
  become: true
  tasks:
  - name: Create the containers
    lxc_container:
      template: ubuntu-ansible
      name: "{{ item.name }}"
      state: started
    with_items: "{{ containers }}"
    register: containers_info

  - name: Wait for the network to be setup in the containers
    when: containers_info|changed
    pause: seconds=10

  - name: Get containers info now that IPs are available
    lxc_container:
      name: "{{ item.name }}"
    with_items: "{{ containers }}"
    register: containers_info

  - name: Register the hosts in the inventory
    add_host:
      name: "{{ item.lxc_container.ips.0 }}"
      group: "{{ item.item.service }}"
    with_items: "{{ containers_info.results }}"

Les sections suivantes du playbook gèrent le déploiement applicatif pour les nouvelles entrées de l’inventaire :

- hosts: memcache
  become: true
  tasks:
  - debug: msg="memcached deployment"

- hosts: mysql
  become: true
  tasks:
  - debug: msg="mysql deployment"

Configuration du client SSH

Dans notre exemple, Ansible n’est pas en mesure d’accéder aux conteneurs car ils sont connectés à un réseau isolé.

SSH permet de gérer ce cas de figure en configurant un relais dans ~/.ssh/config :

Host: lxc1
    Hostname lxc1.domain.com
    User localadmin

Host: 10.0.100.*
    User ubuntu
    ForwardAgent yes
    ProxyCommand ssh -q lxc1 nc %h %p
    StrictHostKeyChecking no
    UserKnownHostsFile=/dev/null

Pour finir

Nous avons choisi dans notre exemple de déployer des conteneurs LXC mais le même procédé peut être utilisé pour déployer d’autres types de VMs ou conteneurs, en utilisant les modules spécifiques d’Ansible : EC2, OpenStack, GCE, Azure, …