Et oui! c'est la saison des chaussettes, histoire de pas attraper froid. On peut même enfiler plusieurs paires, pour avoir encore plus chaud! Dans mon précédent article, je vous parlais de Dotclear, et d'une feature très attendue, à propos de socket. Depuis la sortie de la toute dernière version, il est désormais possible de brancher l'application PHP au serveur de base de données via socket Unix (aussi appelé UDS: Unix Domain Socket).

Avant, on avait pas le choix, on était obligé de passer par le socket TCP. La plupart d'entre nous, pour ne pas dire "tout le monde", passe par les sockets TCP. Lorsque qu'une application quelconque se connecte au serveur de base de données par son port d'écoute, on passe par le socket TCP sans même s'en rendre compte. Et pourquoi on fait tous cela ? Parce que c'est facile, il faut l'admettre. Pourtant, des fichiers verrou (socket Unix), il y en a beaucoup dans les systèmes GNU/Linux et pour cause, ils sont plus performants et plus rapides que les sockets TCP. Je laisse le soin au lecteur de chercher des comparatifs de test de performances, c'est pas ce qui manque sur le web. Et donc des fichiers verrou il y en a partout, il y en a même un fourni par le serveur de base de données MariaDB.

Dans l'optique de faire gagner quelques millisecondes à Dotclear, d'augmenter la réactivité du site, et d'alléger la charge sur la machine, le choix d'UDS s'impose de par ses perfs au banc d'essai. Pour rajouter un peu de challenge (sinon où est le fun ?), la migration aura lieu dans un environnement entièrement full stack Docker, avec SELinux activé.

Présentation du système

L'infrastructure se découpe en trois containers docker, le premier est pour Apache, il communique déjà avec PHP-FPM par UDS. Le second est pour PHP-FPM, il communique initialement avec MariaDB par socket TCP. Enfin la 3ème brique est pour MariaDB, qui doit maintenir un nom de container constant pour permettre le linkage entre containers avec PHP-FPM (à cause du socket TCP).

Avant toute opération de mise à jour des unités systemd, un travail préparatoire avait déjà été réalisé sur les containers Docker de PHP-FPM et Mariadb quelques mois auparavant. Les unités systemd de MariaDB et PHP-FPM s'étaient vu assigner un volume supplémentaire pour la socket Unix de MariaDB: /run/mariadb/. Comme vous le constaterez dans les unités systemd, les images Docker utilisées sont des images custom, les sources sont disponibles dans mes dépôts Git.

À titre de comparatif uniquement, je joins la version initiale de mes unités systemd:

Les contextes SELinux de certains volumes ne sont pas en MLS (option :Z) dès que le volume est partagé entre deux containers (par exemple /run/mariadb), sinon cela entraine des conflits, et indubitablement des AVC denied. Il sont donc volontairement abaissés en Targeted (option :z) ce qui reste toutefois raisonnable.

Étape 1

Mise à jour manuelle du code de Dotclear. Ce mode de mise à jour est très bien documenté, aussi je ne ne m'attarderais pas trop sur cette étape, à un détail près: Je travaille dans un nouveau répertoire! Si le répertoire racine se nomme /var/www/html, alors je fais tout dans /var/www/html.new et je vous invite à en faire autant! Allez-y, décompressez...

Pour ceux qui ont une politique de permissions en écriture très restrictive, n'oubliez pas de donner les droits en écriture des répertoires suivant au serveur web:

  • themes/
  • plugins/

Sinon ça marche moins bien.

Étape 2

Modification du fichier inc/config.php. C'est à cette étape que l'on va reconfigurer l'accès à la base de données en utilisant la socket Unix. Dans le nouveau fichier (/var/www/html.new/inc/config.php), remplacer:

define('DC_DBHOST','nom_d_hote_du_serveur');

par:

define('DC_DBHOST','localhost:/run/mariadb/mariadb.socket');

La clé ici c'est "localhost:". Après vous pouvez renseigner n'importe quel chemin vers le fichier verrou. Toutes les autres options de configuration restent inchangées.

Restez vigilent par rapport au nom d'utilisateur mariadb, l'accès par le fichier verrou est encore différent des hôtes '@192.168.0.X', '@localhost' et '@%' (et oui, socket TCP oblige...). Il est évident qu'un léger paramétrage de l'utilisateur mariadb est requis.

Étape 3

Couper les services systemd. Pas tous les services, seulement ceux qui accèdent à la base de données, pour pouvoir faire un dernier dump de backup. On coupe:

  1. apache-casper-site.service
  2. php-fpm-casper-site.service

Étape 4

Lancer le backup de la base de données... Comment ça vous n'avez pas de script de backup automatique ?!? Non je rigole, évidemment que vous en avez un. Même quelque chose de simple, une tâche Cron.daily qui contient ce qui suit est largement suffisant:

# setup mdp user mysql
MYSQL_USER_PASSWORD=truc

# utliser mysqldump à la place
mysqldump --opt -S /contener/mariadb-casper-site/run/mariadb/mariadb.socket \
          -u casperlefantom \
          -p$MYSQL_USER_PASSWORD \
          casperlefantom > db-casperlefantom-$(date +%Y%m%d).dump

# compresser les fichiers de dump
pxz db-*-$(date +%Y%m%d).dump

# garder ici les 30 derniers jours
find . -name "db-*.dump.xz" -atime +30 -delete

Il va falloir que je remplace un jour mes tâches Cron par des timers systemd, mais on verra ça une autre fois...

Étape 5

On remplace /var/www/html par /var/www/html.new. Les services sont coupés, on peut y aller sereinement. Par mesure de précaution, on garde l'ancien répertoire sous le nom /var/www/html.old, on est jamais trop prudent.

Puis on peut relancer les services systemd précédemment coupés:

  1. php-fpm-casper-site.service
  2. apache-casper-site.service

Et le tour est joué. Grâce à ce mode opératoire, le site est resté down moins d'une minute, c'est juste parfait. Cerise sur le gâteau, Dotclear passe par la socket Unix pour mettre à jour la base de données à la dernière version installée.

Étape 6

Rendez vous sur la page web /admin/ pour terminer la mise à jour.

Capture d’écran_2018-01-01_09-06-08.png

Pas besoin de commenter, je trouve le message ma foi explicite. On a terminé l'upgrade de Dotclear.

Et maintenant que l'on a eu ce qu'on voulait, on peut fignoler la mise à jour des unités systemd. Il y a en effet un certain nombre de modifications à effectuer avant que tout soit parfait. Comptons-les ensemble :-)

Étape 7

Modification des unités systemd, ou plutôt nettoyage de printemps.

Souvenez-vous, en début d'article j'avais écrit que MariaDB devait avoir un nom de container constant afin que le linkage inter-container fonctionne à tous les coups. Le linkage, c'est pour les ports d'écoute, et donc les sockets TCP. Sauf que nous ne les utilisons plus à présent, ce qui signifie que l'option --name peut être supprimée.

De même, si le container porte à présent un nom aléatoire, la commande ExecStartPre ne sert plus à rien, puisqu'il n'y a plus d'ancien container portant ce nom-là à supprimer.

Et enfin, l'option -p pour exposer le port d'écoute servait à la fois pour le script de dump de backup, mais aussi pour mes opérations de maintenance sur le serveur de base de données (gestion des utilisateurs mariadb, mots de passe, etc...). Je n'en ai plus l'utilité puisque je passe par UDS pour le backup.

Voici la version finale de mariadb-casper-site.service.

Parlons à présent de l'unité de PHP-FPM. On peut supprimer toute dépendance au service MariaDB car il n'y a plus de linkage inter-container nécessaire. Concrètement, les options BindTo et --link passent à la trappe, les services After seront juste épurés.

Et voilà le résultat final de php-fpm-casper-site.service.

Étape 8

Reload systemd. Faudrait pas oublier, quand même.

En une commande c'est réglé, et pas besoin de rebooter:

# systemctl daemon-reload

Étape 9

Modifier le script de dump de backup.

L'infrastructure vient d'être profondément remaniée. Ce remaniement engendre des modifications et des adaptations de tout ce qu'il y a autour, notamment les scripts de backup. N'oubliez pas de contrôler tout ce qui gravite autour des services principaux, c'est malheureusement trop facile de casser un backup automatique avec un petit changement d'architecture de rien du tout.