Fedora-Fr - Communauté francophone Fedora - Linux

Planet de Fedora-Fr : la communauté francophone autour de la distribution Linux Fedora

A propos

Cette page est actualisée toutes les heures.

Cette page est une sélection de blogs autour de Fedora. Fedora-Fr.org décline toute responsabilité au sujet des propos tenus par les auteurs des blogs de ce planet. Leurs propos sont leur entière responsabilité.

Le contenu de ce planet appartient à leurs auteurs respectifs. Merci de consulter leur blogs pour obtenir les licences respectives.

Mot-clefs : container

En hivers met tes chaussettes

Matthieu Saulnier

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.

En hivers met tes chaussettes

Matthieu Saulnier

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.

Unités systemd avec docker

Matthieu Saulnier

Une fois encore le couple systemd-docker nous montre son efficacité... redoutable. J'ai pû monter un service en quelques minutes sans prise de tête ou complication imprévue; certes la partie zone DNS et reverse proxy était déjà en place, mais quand même. Je résumerais l'histoire en 4 étapes.

Veni

Le premier reflexe à avoir quand on veut monter un nouveau service, est de chercher sur la registry Docker officielle une image potable, et vérifier son Dockerfile pour voir si elle emballe pas quelques abérations. Moi je cherchais une image du service Searx, et je suis tombé sur une perle rare.

Vidi

L'image docker est basée sur Alpine Linux 3.6, elle n'a pas de volumes donc pas de données persistantes, et elle n'expose qu'un seul port, plus simple tu meurs. Petit plus, elle n'embarque pas les dépendances de compilation, elle se contente de compiler le programme sans faire de choses tordues avant ou après. Le script run.sh procède visiblement à quelques ajustements de la config du programme, notament la génération d'une clé d'authentification, qui sera regénérée à chaque lancement. Soit.

Vici \o/

Il ne reste plus qu'à concrétiser tout ça dans son terminal...

# docker pull wonderfall/searx

L'unité systemd aura les fonctionnalités suivantes:

  1. Lancer le processus dans le container et créer le container
  2. Le container utilise le serveur DNS de OpenDNS (fixe un bug avec NetworkManager et dnsmasq)
  3. Le container écoute sur le port 8089 de l'interface localhost (important)
  4. L'url de base est passée en variable d'environnement
  5. Envoi du signal reload au processus cloisonné
  6. Tuer le processus dans son container et laisser le container à l'abandon
  7. un nouveau container avec un nouveau nom sera créé au prochain redémarrage

# cat /etc/systemd/system/searx-casper-site.service
[Unit]
Description=Searx search engine
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker run -i --dns 208.67.222.222 -p 127.0.0.1:8089:8888 \
          -e BASE_URL=https://search.casperlefantom.net \
          wonderfall/searx:latest
ExecReload=/usr/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

J'insiste sur le fait que vos containers doivent écouter seulement sur l'interface localhost pour des raisons de sécurité. Si le container écoute sur l'interface ethernet, alors son port d'écoute sera accessible depuis n'importe où sur Internet. Firewalld ne pourra rien faire pour vous. J'ai 2 reverses proxy devant, je serais bien embêté si on pouvait les bypasser >-)

# systemctl daemon-reload
# systemctl enable searx-casper-site.service
# systemctl start searx-casper-site.service

Les logs du programme sont automatiquement récupérés par Journald. L'étape de suppression des containers sans processus actif est relègué à une opération de nettoyage manuel. Je n'ai malheureusement pas trouvé d'autre solution, des disques trop lent sont assez problématiques et provoquent des erreurs de système de fichier en cours d'utilisation.

Unités systemd avec docker

Matthieu Saulnier

Une fois encore le couple systemd-docker nous montre son efficacité... redoutable. J'ai pû monter un service en quelques minutes sans prise de tête ou complication imprévue; certes la partie zone DNS et reverse proxy était déjà en place, mais quand même. Je résumerais l'histoire en 4 étapes.

Veni

Le premier reflexe à avoir quand on veut monter un nouveau service, est de chercher sur la registry Docker officielle une image potable, et vérifier son Dockerfile pour voir si elle emballe pas quelques abérations. Moi je cherchais une image du service Searx, et je suis tombé sur une perle rare.

Vidi

L'image docker est basée sur Alpine Linux 3.6, elle n'a pas de volumes donc pas de données persistantes, et elle n'expose qu'un seul port, plus simple tu meurs. Petit plus, elle n'embarque pas les dépendances de compilation, elle se contente de compiler le programme sans faire de choses tordues avant ou après. Le script run.sh procède visiblement à quelques ajustements de la config du programme, notament la génération d'une clé d'authentification, qui sera regénérée à chaque lancement. Soit.

Vici \o/

Il ne reste plus qu'à concrétiser tout ça dans son terminal...

# docker pull wonderfall/searx

L'unité systemd aura les fonctionnalités suivantes:

  1. Lancer le processus dans le container et créer le container
  2. Le container utilise le serveur DNS de OpenDNS (fixe un bug avec NetworkManager et dnsmasq)
  3. Le container écoute sur le port 8089 de l'interface localhost (important)
  4. L'url de base est passée en variable d'environnement
  5. Envoi du signal reload au processus cloisonné
  6. Tuer le processus dans son container et laisser le container à l'abandon
  7. un nouveau container avec un nouveau nom sera créé au prochain redémarrage

# cat /etc/systemd/system/searx-casper-site.service
[Unit]
Description=Searx search engine
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker run -i --dns 208.67.222.222 -p 127.0.0.1:8089:8888 \
          -e BASE_URL=https://search.casperlefantom.net \
          wonderfall/searx:latest
ExecReload=/usr/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

J'insiste sur le fait que vos containers doivent écouter seulement sur l'interface localhost pour des raisons de sécurité. Si le container écoute sur l'interface ethernet, alors son port d'écoute sera accessible depuis n'importe où sur Internet. Firewalld ne pourra rien faire pour vous. J'ai 2 reverses proxy devant, je serais bien embêté si on pouvait les bypasser >-)

# systemctl daemon-reload
# systemctl enable searx-casper-site.service
# systemctl start searx-casper-site.service

Les logs du programme sont automatiquement récupérés par Journald. L'étape de suppression des containers sans processus actif est relègué à une opération de nettoyage manuel. Je n'ai malheureusement pas trouvé d'autre solution, des disques trop lent sont assez problématiques et provoquent des erreurs de système de fichier en cours d'utilisation.