Ansible + LXD = <3

Petite introduction. Jusqu’ici, mon serveur personnel, une instance EC2 hébergeant ce blog, était à base de :

  • haproxy 
  • letsencrypt
  • docker

Puis chaque composant = un conteneur docker, et l’ajout de configuration haproxy qui va bien en fonction du service hébergé.

Je me connectais donc sur mon serveur avec mes dix petits dix doigts pour aller lancer des conteneurs, mettre à jour le système, renouveler mes certificats LetsEncrypt… Bref. 

J’ai récemment entrepris de le refondre selon une logique toute autre, afin d’exploiter au maximum la puissance d’Ansible et de piloter mon infrastructure avec.

Voici comment j’ai implémenté ce workflow, en deux parties pour pouvoir être exhaustif autant que possible.

LXD

En premier lieu, j’ai abandonné Docker pour LXD, ce dernier m’offrant plus de flexibilité, notamment dans le workflow que j’ai implémenté via Ansible. 

Pour rappel, LXD est un hyperviseur de conteneurs LXC. Ce sont donc des sous-systèmes et non des apps (chroot on steroids, a-t-on l’habitude de dire). 

L’idée est donc d’avoir un conteneur LXD pour chaque service hébergé. Mais comment Ansible va atteindre ces conteneurs ? Quelle logique adopter niveau réseau ? Du NAT sur le porte-conteneur (berk) ? Du loadbalancing TCP avec Haproxy ?

La première question n’est en fait pas là, c’est plutôt :

Comment vais-je me connecter dans mon conteneur directement via Ansible ? 

Je m’explique : pour qu’Ansible joigne le conteneur (selon ma logique, chacun est libre de faire sa tambouille comme il le souhaite), le conteneur doit :

  1. Avoir Python d’installé
  2. Comporter la clef ssh choisie dans le authorized_keys de l’utilisateur choisi

Et LXD doit être exposé sur le net, donc son API doit écouter sur le port 8443, afin que les tasks Ansible liées à LXD fonctionnent. 

Et on serait tenté de se dire:

Ce n’est pas grave, je m’y connecterais juste une fois pour faire tout cela..

Comme ce serait redondant (et ch***t, on ne va pas se mentir). L’idée est de manager l’infrastructure As-A-Code de bout en bout depuis mon mac et non d’aller me connecter au serveur et/ou aux conteneurs qu’il héberge.

Je veux donc pouvoir lancer des conteneurs à la demande et déployer dedans directement via Ansible sans avoir à m’y connecter une seule fois.

La solution qui me semble la plus propre : il faut que mes conteneurs soient lancés depuis une image pré-paramétrée avec l’utilisateur de mon choix ainsi que la clef de mon choix, et que ce conteneur comporte une installation de Python. 

Je créé donc un petit conteneur « lab », j’y installe Python, la clef SSH du projet (généré via ansible-init ;-)) pour l’utilisateur de mon choix. Une fois mon conteneur créé et paramétré, j’en fais une une image avec la commande :


$ lxc publish lab –alias template0

Créé une image locale nommée « template0 » depuis le conteneur nommé « lab »

Une fois que cette image est prête, j’en ai fini avec LXD puisque tout le reste, toutes les autres parties et étapes se feront maintenant directement via Ansible, depuis l’extérieur (oui oui, même la création de conteneurs). 

Et là, on serait tenté de se dire:

Mais euh… OK j’ai une image d’un conteneur Python et ma clef SSH dessus… Je ne peux toujours pas l’atteindre en fait…

Et surprise: il n’y aura pas de NAT ni de loadbalancing haproxy (qui sera lui-même en conteneur d’ailleurs) pour atteindre les conteneurs en SSH dans ce workflow :

Ansible, via une configuration ssh aux p’tits oignons dans le projet, va faire un rebond ssh par le porte-conteneur pour atteindre le LAN des conteneurs.

Workflow que je détaillerais dans un second article 🙂


Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *