Images cloud de 28 systèmes : 8 pièges corrigés

28 systèmes, chacun tiré de l'image cloud de sa distribution, chacun avec ses habitudes. Les pièges qui nous ont coûté du temps, ce que vous voyez quand ils vous tombent dessus, et le correctif que portent maintenant nos images.

Des images disque empilées, dont une marquée d'un signal d'alerte

Notre catalogue compte désormais 28 systèmes d'exploitation. Chacun part de l'image cloud que publie sa distribution, et cloud-init fait le travail du premier démarrage : le compte, votre clé SSH, le réseau, le nom d'hôte. Toutes ces images parlent cloud-init, mais aucune ne se comporte tout à fait comme sa voisine.

Voici les huit différences qui nous ont coûté le plus de temps pendant l'ajout d'openSUSE, d'Oracle Linux et des autres : ce que vous voyez quand l'une d'elles vous tombe dessus, et le correctif que portent maintenant nos images. Si vous fabriquez vos propres images, c'est la liste qu'on aurait aimé avoir au départ.

1. Le compte par défaut change d'une image à l'autre

cloud-init crée un seul compte au premier démarrage, le default_user déclaré dans la configuration de l'image. Ce n'est jamais root, et son nom dépend de qui a fabriqué l'image :

openSUSE nous a surpris : son image cloud crée sles, le nom de la distribution entreprise de SUSE, et non opensuse. Alpine n'a pas de sudo du tout ; le compte reçoit doas, qui s'emploie de la même façon (doas apk add htop). Pour savoir quel compte une image va créer, lisez sa configuration cloud-init. Celle d'openSUSE Leap 16.0 :

bash
$ grep -A3 'default_user:' /etc/cloud/cloud.cfg
  default_user:
    name: sles
    lock_passwd: True
    gecos: sles Cloud User

Oracle Linux la range plutôt dans /etc/cloud/cloud.cfg.d/90_ol.cfg. La console affiche le bon compte à côté de chaque machine, et la page des images le donne pour chaque système.

2. Une racine sur LVM qui ne grandit pas

Les images KVM officielles d'Oracle arrivent avec un disque de 37 Go : une racine XFS de 32 Go et 4 Go de swap, le tout sur LVM. cloud-init agrandit une partition simple et son système de fichiers, mais sur cette image il n'a rien fait de la chaîne LVM. Sur un disque de 40 Go, nous avons obtenu une racine de 31 Go et un groupe de volumes sans la moindre place libre :

bash
$ sudo vgs -o vg_name,vg_size,vg_free
  VG      VSize  VFree
  vg_main 35.80g     0

XFS ne sait pas rétrécir, l'image ne tiendra donc jamais sur un disque de moins de 37 Go : Oracle Linux commence à notre offre Starter. Sur les plus grands disques, l'espace en plus restait tout simplement inaccessible. Nous avons ajouté à l'image un petit service qui lance trois commandes à chaque démarrage (le vrai script trouve lui-même le disque et la partition) :

bash
growpart /dev/vda 4
pvresize /dev/vda4
lvextend --resizefs -l +100%FREE /dev/vg_main/lv_root

À chaque démarrage, pas seulement au premier : un disque agrandi par un changement d'offre est pris en compte au redémarrage suivant. Le premier démarrage sur un disque de 40 Go donne ceci dans le journal :

bash
ffxf-grow-root[936]: data blocks changed from 8336384 to 9122816
ffxf-grow-root[919]:   Extended file system xfs on vg_main/lv_root.
ffxf-grow-root[919]:   Logical volume vg_main/lv_root successfully resized.

La racine est passée à 34,8 Go, puis à 74,8 Go après avoir porté le disque à 80 Go et redémarré. Quand il n'y a plus rien à prendre, growpart répond NOCHANGE et le service s'arrête sans rien toucher. SELinux étant en mode enforcing, nous avons posé les étiquettes SELinux des fichiers ajoutés avant le premier démarrage, puis vérifié le journal d'audit : aucun refus.

3. sshd installé, mais éteint

L'image cloud d'Arch livre OpenSSH installé et l'unité sshd désactivée. cloud-init pose le mot de passe et dépose votre clé, et personne n'écoute sur le port 22. La machine tourne, et on ne peut pas l'atteindre.

Notre configuration de premier démarrage lançait systemctl try-restart après avoir modifié les réglages SSH. Cette commande ne touche pas à une unité arrêtée : sans effet sur les autres images, fatal sur Arch. Elle active désormais le service d'abord :

bash
runcmd:
  - systemctl enable --now sshd

4. Pas de DNS, pas de paquets

Avec un réseau configuré en statique et aucun serveur DNS dans les données cloud-init, cloud-init n'écrit aucun réglage DNS. Debian et Ubuntu s'en sortent grâce à systemd-resolved. Alpine, elle, démarrait sans /etc/resolv.conf : apk update sortait en code 4, et tous les paquets prévus au premier démarrage échouaient, y compris l'agent qui remonte l'occupation du disque et de la mémoire à la console.

Nous envoyons maintenant les serveurs DNS avec la configuration réseau, et gardons un filet de sécurité dans bootcmd, qui passe avant l'installation des paquets :

bash
bootcmd:
  - |
    if [ ! -L /etc/resolv.conf ] && [ ! -s /etc/resolv.conf ]; then
      printf 'nameserver 1.1.1.1\nnameserver 8.8.8.8\n' > /etc/resolv.conf
    fi

Les deux tests comptent. Sur Debian et Ubuntu, /etc/resolv.conf est un lien symbolique géré par systemd-resolved, et l'écraser y casserait la résolution de noms. Autre détail : l'étape packages de cloud-init abandonne au premier échec et ne réessaie jamais. Nous relançons donc l'installation de l'agent plus tard, dans runcmd, une fois le réseau en place.

5. Un lecteur de configuration que le noyau ne voit pas

Les images genericcloud de Debian sont taillées pour du matériel virtuel et laissent de côté les pilotes dont un cloud n'a pas besoin, dont les vieux contrôleurs IDE. Branchez les données cloud-init comme un CD-ROM sur un bus IDE, et le noyau ne le voit jamais. ds-identify ne trouve aucune source de données et désactive cloud-init sans un mot sur la console. La machine démarre sous le nom localhost, sans adresse IP, et ssh.service échoue faute de clés d'hôte.

Les données doivent se trouver sur un bus que le noyau de l'image connaît, virtio ou SCSI. Sur une machine qui a démarré ainsi, ces deux commandes disent pourquoi :

bash
cat /run/cloud-init/ds-identify.log
cloud-init status --long

6. Des clés d'hôte qui changent après un redémarrage

cloud-init régénère les clés d'hôte SSH chaque fois qu'il pense tourner sur une nouvelle instance. Chez nous, changer le nom d'hôte ou le mot de passe, ou ajouter une carte réseau, donne au démarrage suivant un nouvel identifiant d'instance. Un client a ainsi reçu WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED d'une machine à laquelle personne n'avait touché.

Le correctif tient en une ligne, écrite à la fin du premier démarrage seulement, pour que chaque machine reçoive quand même ses propres clés à sa création :

99-ffxf-keep-hostkeys.cfg
# /etc/cloud/cloud.cfg.d/99-ffxf-keep-hostkeys.cfg
ssh_deletekeys: false

7. Une mise à niveau complète au premier démarrage

cloud-init peut mettre à niveau tous les paquets au premier démarrage (package_upgrade: true), et certaines plateformes l'activent par défaut. La mise à niveau garde le verrou d'apt ou de dnf pendant plusieurs minutes, et votre premier apt update reste bloqué, ou échoue avec Could not get lock /var/lib/dpkg/lock-frontend.

Nous la laissons désactivée. Les images sont à jour quand nous les construisons, et le moment de la mise à niveau vous appartient. Si vous scriptez votre première connexion, attendez cloud-init avant de toucher au gestionnaire de paquets :

bash
cloud-init status --wait
sudo apt update && sudo apt full-upgrade -y

La suite de cette première session est dans notre guide pour sécuriser un VPS Ubuntu.

8. La version 10 exige un processeur récent

Rocky Linux 10, AlmaLinux 10, Oracle Linux 10 et CentOS Stream 10 sont compilés pour x86-64-v3, qui comprend AVX2. Sur un processeur qui ne l'a pas, rien ne démarre. Nous l'avons vu sur une machine de construction en préparant l'image d'Oracle Linux 10, dès la première tentative de lancer un shell dedans :

bash
Fatal glibc error: CPU does not support x86-64-v3

Nos VM voient le processeur de l'hôte, qui prend en charge v3 : ces systèmes y tournent normalement. Si vous les faites tourner sur votre propre hyperviseur avec un modèle de processeur virtuel générique, vérifiez d'abord. Sur cette machine de construction, v3 n'apparaît pas comme pris en charge :

bash
$ /lib64/ld-linux-x86-64.so.2 --help | grep x86-64-v
  x86-64-v4
  x86-64-v3
  x86-64-v2 (supported, searched)

La version 9 des mêmes distributions se contente de x86-64-v2 et démarre toujours sur cette machine.

Trois couches empilées : le disque a grandi, la partition et le système de fichiers s'étirent à sa suite

Agrandir un disque Linux à chaud : ext4, XFS, LVM

Après un passage à une formule plus grande, df affiche souvent l'ancienne taille : le disque a grandi, pas la partition ni le système de fichiers. ext4, XFS et LVM, agrandis à chaud sur une machine de test, sorties réelles à l'appui.

Lire l'article 7 min de lecture

Un workflow confie un job à une machine neuve, comptée au chronomètre, avec son cache à côté ; les machines des jobs précédents sont déjà parties

Runners GitHub Actions : la moitié du prix, mesuré

Les runners GitHub Actions de FFxF sont ouverts à tous, en bêta. Le même workflow lancé chez GitHub et chez nous : compilation un peu plus rapide, facture divisée par deux, docker build plus lent à froid et 4 secondes avec le cache Docker.

Lire l'article 7 min de lecture

Support & discussions

Questions techniques, retours d'incidents ou discussions d'infrastructure, l'équipe est présente sur Discord, Telegram, X, Instagram, Reddit et IRC.