Démarrer un service selon une condition avec systemd

Aujourd’hui présentation de quelques commandes puis mise en place d’un drop-in avec condition.

Une petite entrée en matière avec les documentations claires et de qualité d’Adrien de Linuxtricks.fr dont je ne dis pas assez de bien :
systemd : les commandes essentielles
systemd : Créer des services, timers (unités)

Contexte

Dans mon job je dois régulièrement migrer des clients d’un serveur VPS (Virtual Private Server, une machine virtuelle ou VM) vers un dédié (serveur physique). Cette semaine pour la première fois, j’ai migré un client d’un dédié vers un VPS.

Notre manière de procéder est de rsync la totalité du serveur du client vers la nouvelle machine (physique ou virtuelle) bootée en rescue. À la fin de la migration le client a vraiment la même configuration que précédemment. Cependant des services peuvent devenir inutiles et restent en erreur, par exemple le service smartd pour monitorer la santé des disques n’a plus d’intérêt si on est sur une machine virtuelle.

systemd-detect-virt

systemd fournit un outil peu connu permettant de détecter le contexte d’exécution du système dans un environnement virtuel. Sur un serveur physique il retournera none, sur une VM au boulot kvm, dans un conteneur Docker docker simplement avec la commande systemd-detect-virt. Pour lister les différentes technos de virtualisations reconnues systemd-detect-virt --list : none kvm qemu bochs xen uml vmware oracle microsoft zvm parallels bhyve qnx acrn vm-other systemd-nspawn lxc-libvirt lxc openvz docker podman rkt wsl container-other. Le man de cet outil et un court article pour aller plus loin (attention de 2013).

Cet outil permet donc aisément de modifier/scripter une action en fonction du contexte d’exécution mais on veut aller plus loin, faire en sorte que le service smartd ne démarre tout simplement pas si on est dans une machine virtuelle.

Drop-in et conditions

Un drop-in est le moyen employé sur systemd pour « surcharger » la configuration d’un service. Je donne toujours le même article en Français pour expliquer et s’initier aux drop-ins systemd, la documentation nécessitant une recherche sur le mot drop-in.

On va influencer le démarrage du service avec une condition, on en retrouve plus d’une vingtaine ici dont : ConditionArchitecture=, ConditionVirtualization=, ConditionKernelVersion=, ConditionFirstBoot=, ConditionPathExists=, ConditionUser=…

On retient ConditionVirtualization= pour savoir si on est dans un contexte d’exécution virtualisé/conteneurisé/physique/alien/mutant/inconnu/horrible. Avec systemd-analyze condition 'ConditionVirtualization=false' on peut tester notre condition (disponible à partir de systemd 243, Debian « Buster » 10 propose la 241).

systemd-analyze condition 'ConditionVirtualization=false' # Sur mon pc fixe
test.service: ConditionVirtualization=false succeeded.
Conditions succeeded.

Drop-in smartd

Rentrons maintenant dans le vif du sujet, nous allons modifier le fonctionnement du service smartd avec notre condition.

[Unit]
ConditionVirtualization=false

Voici les commandes à lancer. Seules les trois premières sont nécessaires, les deux dernières permettent juste de vérifier que la condition est fonctionnelle.

mkdir -p /etc/systemd/system/smartd.service.d/ # On crée le dossier pour notre drop-in systemd
nano /etc/systemd/system/smartd.service.d/smartd.conf # On renseigne notre drop-in systemd avec notre condition
systemctl daemon-reload # On recharge la configuration systemd
systemctl restart smartd # On redémarre le service smartd
systemctl status smartd # On vérifie si notre condition a été prise en compte et si le service a démarré ou pas

systemctl cat smartd a pour grande qualité de vous montrer la configuration par défaut du système (/lib/systemd/system/smartd.service), le drop-in configuré (/etc/systemd/system/smartd.service.d/smartd.conf) et leurs emplacements.

systemctl cat smartd
# /lib/systemd/system/smartd.service
[Unit]
Description=Self Monitoring and Reporting Technology (SMART) Daemon
Documentation=man:smartd(8) man:smartd.conf(5)

[Service]
EnvironmentFile=-/etc/default/smartmontools
ExecStart=/usr/sbin/smartd -n $smartd_opts
ExecReload=/bin/kill -HUP $MAINPID
StandardOutput=syslog

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/smartd.service.d/smartd.conf
[Unit]
ConditionVirtualization=false

Voici la sortie de la commande systemctl status smartd sur une machine virtuelle (donc smartd ne doit pas se lancer).

systemctl status smartd
● smartd.service - Self Monitoring and Reporting Technology (SMART) Daemon
   Loaded: loaded (/lib/systemd/system/smartd.service; disabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/smartd.service.d
           └─smartd.conf
   Active: failed (Result: exit-code) since Sat 2020-02-28 07:03:36 CET; 24s ago
Condition: start condition failed at Sat 2020-02-28 07:03:58 CET; 2s ago
           └─ ConditionVirtualization=false was not met
     Docs: man:smartd(8)
           man:smartd.conf(5)

Conclusion

On aurait pu utiliser systemctl edit smartd (à la place du mkdir -p /etc/systemd/system/smartd.service.d/ et nano /etc/systemd/system/smartd.service.d/smartd.conf) qui crée automatiquement le dossier /etc/systemd/system/smartd.service.d/ et le fichier override.conf qu’il ouvre en édition mais je suis pas fan, il est notamment pas foutu d’ouvrir un fichier nommé autrement que override.conf.

Les drop-ins systemd sont délicieux, je vous les recommande, je vous souhaite un bon dimanche et reste disponible dans les commentaires.

Les commentaires sont fermés.