Et oui ! c'est la saison des chaussettes, histoire de ne 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 dernière version, il est désormais possible de brancher l'application PHP au serveur de base de données via un fichier 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 vous laisse chercher un 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 garder 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, je joins la version initiale de mes unités systemd :

Les contextes SELinux de certains volumes ne sont pas en MLS (option :Z) lorsque le volume est partagé entre deux containers (par exemple /run/mariadb). Sinon cela entraine des conflits de label SELinux, et indubitablement des AVC denied. Il sont donc volontairement abaissés en Targeted (option :z) ce qui assure la compatibilité avec le système hôte.

É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.

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/

Étape 2

Modification du fichier inc/config.php. C'est dans cette étape que l'on va reconfigurer l'accès à la base de données en utilisant le 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 vigilant par rapport au nom d'utilisateur MariaDB, l'accès par le fichier verrou est encore différent des hôtes '@192.168.X.X', '@localhost' et '@%' (socket TCP). Il est évident qu'un léger paramétrage de l'utilisateur MariaDB est requis pour ne pas se retrouver bloqué.

Étape 3

Couper les services systemd. Pas tous les services, seulement ceux qui accèdent à la base de données, pour ensuite 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... Personnellement mon backup est plutôt simpliste, une tâche Cron.daily qui contient ce qui suit est largement suffisant :

# setup mdp user mysql
MYSQL_USER_PASSWORD=mot_de_passe

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, si jamais on doit rollback.

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.

Étape 6

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

Capture d'écran

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

Maintenant que le plus gros du travail est achevé, on va fignoler la mise à jour des unités systemd. Il y a en effet un certain nombre de modifications à effectuer avant que tout soit parfait.

É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 pour 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 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.

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.

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

Étape 8

Recharger systemd.

En une commande c'est réglé, sans avoir 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.