jeudi 16 août 2018

LXD/LXC, Docker et autres joyeusetés (partie 2 sur beaucoup potentiellement…)

Où l'on met beaucoup d'ambiance dans cette boîte jaune…

Docker, c'est bien, mais c'est quand même pas idéal pour tout

En y regardant de plus près, on se rend rapidement compte que Docker a avant tout été imaginé pour faire tourner des applications stateless (sans état), donc des trucs qu'on peut tuer et redémarrer à loisir.

Du coup, pour faire du statefull (base de données, applications persistentes, etc…), c'est déjà nettement plus compliqué (sans être impossible hein, mais disons que ça risque de galérer un peu). L'idée même du conteneur est d'être une structure jetable mais fournie avec les piles (toutes les librairies et une grande partie de la logique de fonctionnement).

Des cas simples…

Il existe donc des cas d'usages finalement relativement simples :

  • l'intégralité de l'application est un seul exécutable (avec un éventuel fichier de conf) :
    • on peut mettre le fichier de conf dans un volume (en lecture seule même éventuellement)
    • on peut faire un dérivé du conteneur « officiel » et y inclure le fichier de conf en question (moins souple, mais l'ensemble est monolithique)
  • l'application peut s'exécuter à 100% dans le conteneur mais requiert un volume pour ces données :
    • on peut très facilement lui coller un volume persistent
    • en cas de mise à jour, le volume persistent ne bougera pas
    • si l'application en question doit toucher à la structure des fichiers lors des mises à jour, ça va être très très compliqué pour revenir en arrière
  • l'application peut s'exécuter à 100% dans le conteneur mais requiert une base de données :
    • on peut héberger la base de données sur l'hôte (ça permet de séparer ce qui est stateless de ce qui est statefull)
    • on peut héberger la base de données dans un autre conteneur à côté et lier simplement les deux conteneurs entre eux (comme ça, la base de données ne peut mécaniquement pas être accessible par autre chose que l'application)
  • l'application consiste en plusieurs exécutables qui travaillent ensemble :
    • on peut tous les inclure dans un conteneur, mais c'est super cracra
    • on peut les séparer dans des conteneurs différents mais tous basés sur la même image, c'est plus propre mais nettement plus compliqué

Il y a probablement d'autres cas, mais ça résume, je trouve, assez bien le type d'applications que j'héberge actuellement.

et des cas plus compliqués…

Le souci avec PHP, c'est qu'en gros, ça fait un peu tout ce qui a été cité avant : généralement, il faut une base de données, des fichiers persistents et des fichiers de configuration (en plus de la configuration « système » elle-même). Et l'exécution PHP requiert que le process naisse, interprète, exécute et meurt. Nous sommes loin de l'application dans un seul exécutable…

Du coup, plusieurs approches sont possibles :

  • tout mettre dans un conteneur Apache + PHP en y incluant toute la conf PHP :
    • les changements de configuration passent obligatoirement par une reconstruction (potentiellement lourde) du conteneur
    • il faut quand même prévoir un ou plusieurs volumes persistents et en fonction des applications, cela peut être très compliqué (beaucoup d'applications PHP écrivent dans plusieurs répertoires)
    • quoiqu'il arrive, il faut prévoir au moins un conteneur MariaDB par application PHP (pas gênant en soi, mais en terme de ressources, c'est un peu bourrin)
    • faut faire du Apache et ça, ça donne vraiment envie de vomir
  • tout mettre dans un conteneur FPM et mettre l'application PHP en elle-même dans un volume à part :
    • il faut alors prévoir un conteneur supplémentaire NginX (par exemple) pour la partie présentation. Il faudra également que ce conteneur ait un accès en lecture seule au volume de données du conteneur FPM (sinon, ça ne marchera pas)
    • il faut inclure les sources PHP du logiciel dans le conteneur : encore une fois, il faut le reconstruire à chaque version et prévoir un mécanisme pour mettre à jour les fichiers du volume persistent, sans écraser les configurations/données

(re)faire de l'Apache est honnêtement au-dessus de mes forces, je me suis donc penché sur les méthodes utilisées par quelques très grosses applications PHP : NextCloud et WordPress.

Les approches sont en générales assez similaires :

  • fournir un conteneur très générique avec de l'Apache + PHP et tout ce qu'il faut dedans
  • fournir un conteneur FPM contenant au moins le programme PHP et un moyen de mettre à jour le volume persistent créé par le conteneur
  • y adjoindre systématiquement un conteneur de base de données

Dans tous les cas, ça marche très bien pour du lab. Le souci, c'est que ça fait des images relativement lourdes et surtout, c'est intéressant si l'on veut distribuer le logiciel en même temps que son environnement. Si on a déjà le logiciel (avec tout ce qu'il faut dedans), je ne vois pas bien l'intérêt.

D'autant plus qu'en cas de mise à jour, il faut de toutes manières aller écraser l'ensemble du contenu du volume persistent : la détection d'une nouvelle version me semble relativement hasardeuse en fonction des cas et surtout on perd la possibilité de faire un rollback en redémarrant simplement la version précédente du conteneur : vous démarrez NextCloud 13.0.2, un truc merde, vous ne pouvez plus revenir en arrière.

On perd du coup une grande partie de l'intérêt des conteneurs. Pareil pour les base de données : si le schéma ou les données sont touchées par la mise à jour, c'est en fini en cas de problème.

C'est un peu ce qui me fait dire que Docker et PHP ne sont peut-être pas vraiment fait pour s'entendre. Ça pourrait être bien pire, mais c'est loin, très loin d'être idéal.

Retour à la case départ

Cela me ramène donc à mon idée d'origine :

  • un dérivé d'un conteur nginx:stable qui embarquerait toute la configuration standard que j'ai l'habitude de mettre partout (ça représente 2 ou 3 fichiers en tout, c'est intéressant de les embarquer directement pour retrouver systématiquement la même structure) ;
  • un dérivé d'un conteneur PHP-FPM contenant toutes les extensions nécessaires au bon fonctionnement de 99% des applis PHP (mysqli, gd, etc…), ainsi que toutes les configurations recommandées pour FPM (opcache, durée de vie, nombre de process, etc…). Des recettes pour faire le plus propre possible (en supprimant les outils de compilation à la fin par exemple) existe. Au pire des cas, NextCloud fournit un template très très complet auquel il ne faut pratiquement rien adjoindre.
  • un conteneur mariadb:latest tout ce qu'il y a de plus standard (parce qu'a priori s'il y a un conteneur MariaDB par application, faire de l'optimisation ne va vraiment pas être nécessaire).

Cette approche permet d'avoir finalement une pile d'exécution PHP assez générique et qui convient à presque tous les usages : les conteneurs permettent d'avoir des environnements d'exécution bien séparés, les base de données sont clairement disjointes, les données persistentes sont bien rangées dans un coin.

Cela pose quand même quelques autres petits inconvénients :

  • il est nécessaire de peupler le volume persistent avec le programme PHP avant de lancer le conteneur quoiqu'il arrive, on ne peut pas simplement se contenter de lancer le conteneur et le laisser se débrouiller ;
  • une seule image PHP-FPM, cela veut dire toutes les librairies embarquées avec potentiellement des librairies complètement inutiles voire dangeureuses dedans.

Mais au moins, de cette manière, pour faire tourner une application, est relativiment simple. Cela nécessite :

  • deux volumes persistents, un pour les données de l'application PHP et un pour les données de la base de données MariaDB
  • présenter le volume de données à un conteneur MariaDB
  • présenter le volume applicatif à un conteneur PHP-FPM en écriture
  • présenter le même volume à un NginX en lecture seule
  • ajouter les configurations nécessaires pour NginX (1 fichier de conf pour l'appli, une clé privée et un certificat public pour la partie HTTPS) en lecture seule
  • et évidemment rajouter toute la communication entre ces différents conteneurs
  • le tout décrit dans un fichier YAML correctement commenté.

Bref, ça fait quand même beaucoup beaucoup de bordel pour pouvoir faire tourner chaque application. Je suis par contre complètement incapable de dire si c'est plus ou moins efficace en terme de maintenabilité :

  • être systématiquement sur les toutes dernières version de NginX, MariaDB et PHP peut présenter des avantages considérables dans certains cas…
  • … mais aussi faire bien chier dans d'autres. S'il faut que je maintienne 3 conteneurs PHP différents, ça va vite devenir très lourd…
  • il faut construire (et donc reconstruire régulièrement) au moins deux conteneurs différents : un pour PHP et un pour NginX. Ce n'est jamais grand-chose, mais j'ignore si l'on peut automatiser ce processus (en mode quand PHP-FPM est mis à jour, va faire un docker build).

Foutaise !

Si tu as bien tout suivi, tu as retenu au moins une chose : tout dockériser, c'est surtout maîtriser l'ensemble de la chaîne de montage de chaque image. Partir du principe que les images toutes faites vont convenir me semble hautement illusoire. Si l'on ne veut pas s'éparpiller, on a grandement intérêt à acquérir les bases logistiques nécessaires pour produire de l'image à tour de bras.

Finalement, peu importe qu'on le déploie avec simplement du Docker, avec du Docker-compose, du Docker Swarm, du Kubernetes, du RancherOS ou n'importe quel autre orchestrateur de conteneurs. Maîtriser le contenu des images est finalement plus important que dans maîtriser le contenant.

Au prochain numéro, on essaiera (tant bien que mal) de voir quelle solution sont adoptables pour faire du reverse-proxy.

lundi 6 août 2018

LXD/LXC, Docker et autres joyeusetés (partie 1 sur beaucoup potentiellement…)

Et là, la marmotte, elle met le chocolat dans le papier d'alu.

Lire la suite

samedi 24 mars 2018

Ma République est morte

Plus la peine de tenter une réanimation, c'est juste fini…

Lire la suite

mercredi 4 janvier 2017

uBlock Origin : ne plus filtrer Piwik

Parce qu'autant je chie allègrement sur Google Analytics, autant Piwik, c'est le bien (y)

Lire la suite

lundi 26 décembre 2016

Z-Push, IMAP, sexe et NextCloud

Peut-être pas de sexe finalement, vous n'avez pas été très sage cette année…

Plus sérieusement, je n'ai vu que très peu de ressources en français sur ce sujet, alors que je pense que c'est plutôt utile et rigolo à faire.

Lire la suite

lundi 15 février 2016

Microsoft, je te chie dans la bouche

Tu es le SIDA de l'Internet et j'ai envie de t'enculer le cerveau…

Lire la suite

lundi 28 septembre 2015

mdadm + LVM + ext4 vers BTRFS sans larme

Mais avec un paquet de lubrifiant quand même…

Lire la suite

lundi 2 février 2015

OpenWRT et dhcp6c : la méthode Barrier Breaker

Parce que les tutos obsolètes, ça commence à bien faire !

Lire la suite

vendredi 22 août 2014

Passerelles VPN redondantes avec OpenBSD et BIRD

vpn_redondant_2_operateurs.png

BIRD, c'est bon, mangez-en !

Lire la suite

vendredi 12 juillet 2013

OpenBSD en lecture seule

Parce que de temps en temps, il faut savoir fermer sa gueule…

Lire la suite

vendredi 15 février 2013

DNSSEC : méthode BIND9.9

Nan, parce que la précédente méthode, c'était vraiment _hardcore_

Lire la suite

vendredi 5 octobre 2012

Fabriquer un lecteur de carte mémoire Nintendo 64 (4)

Pour quelques lignes de C de plus…

Lire la suite

vendredi 21 septembre 2012

Fabriquer un lecteur de carte mémoire Nintendo 64 (3)

J'avais jamais vu autant de bits d'un coup…

Oui, je sais, elle est facile.

Lire la suite

vendredi 14 septembre 2012

nginx : ne pas faire de la merde avec PHP

Du pain, du vin, du PHP

Le gars dans la pub là

Lire la suite

vendredi 31 août 2012

Fabriquer un lecteur de carte mémoire Nintendo 64 (2)

Schéma de branchement de la manette N64

Les spécifs un peu détaillés du bordel

Lire la suite

vendredi 24 août 2012

Fabriquer un lecteur de carte mémoire Nintendo 64 (1)

Diantre, mais pourquoi fabriquer une merde pareille ?

Lire la suite

mercredi 9 mai 2012

Dépucelage DNSSEC (2)

Parce qu'il y a des moments où il faut aller péter des culs !

Lire la suite

vendredi 13 janvier 2012

Mes deux centimes : créer des adresses « génériques » avec Postfix

Parce que les adresses normales, c'est pas assez 2.0

Lire la suite

dimanche 4 décembre 2011

Dépucelage DNSSEC (1)

C'est quand quelqu'un t'oblige à faire confiance à un tiers qu'il faut aller lui chier sur son bureau.

Lire la suite

mardi 27 septembre 2011

Quelques pistes pour une sauvegarde répartie (1)

Ou comment mettre toutes tes saloperies sur les PCs des autres pour être peinard…

Lire la suite

- page 1 de 3