PROJET AUTOBLOG


Shaarli - Les discussions de Shaarli

Archivé

Site original : Shaarli - Les discussions de Shaarli du 23/07/2013

⇐ retour index

Systemd-logind dans un LXC : un avant-goût de l'enfer

mercredi 2 décembre 2015 à 19:03
GuiGui's Show - Liens
À lire par ceux et celles qui vont mettre à jour leur LXC Debian à Jessie ou qui vont créer de nouveaux LXC Debian qui seront donc avec Jessie+systemd par défaut.

Par défaut,  le comportement documenté de systemd est de lancer un agetty sur tty1 et de traiter tous les autres tty à la demande (genre si tu crtl+alt+f3 pouf, ça spawn un agetty sur tty3 et si tu fais rien bah y'a que tty1 :D). Le nombre max de tty est défini dans /etc/systemd/logind.conf (et plus inittab comme avant) et vaut 6 par défaut.

Ce mécanisme de spawn automatique repose sur dbus. Heureusement, s'il n'est pas installé ou qu'une erreur est survenue durant son lancement, /lib/systemd/system/getty-static.service prévoit un mécanisme de secours en spawnant le nombre de tty défini dans /etc/systemd/logind.conf quoi qu'il arrive.

Par défaut, dbus n'est pas installé dans un LXC donc on a bien 6 tty lancés au boot. Or, un LXC n'a que 4 tty (/dev/tty1-4) par défaut. Donc les agetty sur tty5 et tty6 hurlent à la mort toutes les 5 ou 10 secondes dans les logs (auth.log ou journalctl -xn) :
« déc. 02 14:28:42 test agetty[155]: /dev/tty6: No such file or directory
déc. 02 14:28:42 test agetty[154]: /dev/tty5: No such file or directory »

Il est hors de question que je me fasse pourrir mes logs comme ça. Sachant que dbus est obligatoire pour l'autocomplétion et la bonne exécution des commandes systemctl, on l'installe. Si votre LXC est un LXC créé à l'instant, vous pouvez reboot. Si c'est un LXC mis à jour depuis wheezy, ne rebootez pas encore. :)

En temps normal, /lib/systemd/system/getty@.service est utilisé comme template pour instancier les getty à la demande. Sauf qu'il précise « ConditionPathExists=/dev/tty0 » c'est-à-dire que cette unit doit être exécutée uniquement si /dev/tty0 est présent. C'est le cas par défaut... mais pas dans un LXC. Donc les tty ne seront pas spawnées donc un lxc-console ne donnera pas un prompt de login, juste « Connected to tty 1 ». De quelles tty je parle ? Celles définies dans /etc/systemd/system/getty.target.wants/ (qui sont des liens symboliques vers /lib/systemd/system/getty@.service).

Pourtant, j'ai dit plus haut que, sur un LXC créé from scratch avec Jessie, ça fonctionnait de base ? Oui, car le template LXC crée une copie de /lib/systemd/system/getty@.service dans /etc/systemd/system/getty@.service dans laquelle « ConditionPathExists=/dev/tty0 » est commentée. Et c'est ce fichier qui est pointé par les units dans /etc/systemd/system/getty.target.wants/, ce qui fait que ça fonctionne.

Qui crée les fichiers dans /etc/systemd/system/getty.target.wants/ ? systemd-getty-generator (/lib/systemd/system-generators/systemd-getty-generator). Quand ? « systemd will execute those binaries very early at bootup and at configuration reload time -- before the unit files are loaded. » (https://wiki.freedesktop.org/www/Software/systemd/Generators/). Dans un LXC, ni un boot, ni un systemctl daemon-reload  n'exécute le generator... En réalité, c'est le template LXC Debian qui génère les units à la création du LXC :
« ( cd ${rootfs}/etc/systemd/system/getty.target.wants
       for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty@tty${i}.service; done ) »

Donc, que faut-il faire sur un ancien LXC mis à jour depuis Wheezy ? Il faut copier /lib/systemd/system/getty@.service dans /etc/systemd/system/getty@.service en *commentant* « ConditionPathExists=/dev/tty0 » puis regénérer les units dans /etc/systemd/system/getty.target.wants/ : cd /etc/systemd/system/getty.target.wants/ && rm getty@tty*.service && for i in `ls /dev/tty[0-9]* | grep -o [[:digit:]]`; do ln -s ../getty@.service getty@tty${i}.service; done . Soit un reboot, soit systemctl daemon-reload && systemctl start getty@tty*.service et vous aurez le bon nombre de tty en attente de votre tentative de connexion.

Il reste un dernier point à comprendre : pourquoi le spawn automatique ne fonctionne-t-il pas ? C'est une bonne question. Normalement, c'est /lib/systemd/system/autovt@.service qui s'occupe de ça comme l'indique le man logind.conf : « when switched to and are previously unused, "autovt" services are automatically spawned on. These services are instantiated from the template unit autovt@.service for the respective VT TTY name, for example, autovt@tty4.service. By default, autovt@.service is linked to getty@.service. In other words, login prompts are started dynamically as the user switches to unused virtual terminals. ». Par défaut, un tty est réservé et ne sera pas donné à un quelconque sous-sytème. Le numéro de tty est indiqué dans « ReserveVT= » dans /etc/systemd/logind.conf et vaut 6 par défaut. Même en décommentant « ConditionPathExists=/dev/tty0 » dans /lib/systemd/system/getty@.service pour tester, même en changeant le numéro du tty réservé, même en vérifiant que dbus et systemd-logind sont lancés sans erreur (systemctl status), rien à faire : le tty réservé n'a pas de prompt de login et aucun agetty n'est spawné quand on lxc-console sur tty2-4... Visiblement, les devs de LXC ont décidé de feinter avec la méthode présentée précédemment donc je vais faire pareil afin d'avoir une totale harmonisation entre mes LXC existants et mes futurs LXC, pas envie de me prendre la tête une fois de plus sur ce problème.

Voici les ressources que je n'ai pas encore citées qui m'ont aidé à y voir plus clair :
   * https://wiki.archlinux.org/index.php/Systemd_FAQ#How_do_I_change_the_default_number_of_gettys.3F
   * https://lists.linuxcontainers.org/pipermail/lxc-devel/2013-May/004433.html
   * https://lists.linuxcontainers.org/pipermail/lxc-devel/2013-May/004433.html
(Permalink)