SSD Nodes Learn 🎉 VPS dès $5.50/mois
Guides Matt ConnorPar Matt Connor

Corriger un doublon de machine-id après clonage VPS

Deux clones partageant le même /etc/machine-id peuvent se disputer un bail DHCP. Régénérez-le correctement et videz-le avant de créer votre image maître.

Ce qu’est /etc/machine-id et pourquoi un doublon est problématique

Un VPS cloné démarre avec le même /etc/machine-id que le serveur depuis lequel il a été cloné, alors que cette valeur est censée appartenir à une seule installation. La correction tient en quatre commandes : vider le fichier, supprimer la copie D-Bus si c’est un fichier réel, régénérer l’identifiant, puis redémarrer. Le redémarrage est l’étape qui est souvent oubliée. C’est pourtant elle qui applique la modification.

/etc/machine-id contient une chaîne hexadécimale en minuscules de 32 caractères, terminée par un saut de ligne. Une fois décodée, elle représente une valeur de 16 octets (128 bits). La page de manuel de machine-id(5) la décrit comme confidentielle et indique qu’elle ne doit pas être exposée sur le réseau, car toute personne qui la lit peut reconnaître votre machine ultérieurement. Elle est écrite une seule fois, lors de l’installation du système, et plus rien ne la modifie ensuite.

Trois identifiants sont souvent confondus ici. Il est donc utile de les distinguer. Le nom d’hôte est un libellé que vous choisissez et que vous pouvez modifier à tout moment. L’UUID produit DMI (interface de gestion de bureau) dans /sys/class/dmi/id/product_uuid provient de l’hyperviseur et n’est lisible que par root. L’identifiant de machine est le troisième : le système d’exploitation le génère, et tous les utilisateurs de la machine peuvent le lire.

Ce qui lit réellement le machine ID

L’identifiant client DHCP. C’est le cas le plus problématique. systemd.network(5) documente ClientIdentifier= dans la section [DHCPv4] et indique que sa valeur par défaut est duid. Cette valeur envoie un identifiant client conforme à la RFC 4361, construit à partir d’un IAID et d’un DUID (identifiant unique DHCP). networkd.conf(5) documente le type de DUID par défaut comme étant vendor. Dans ce cas, la valeur du DUID est générée à partir de 43793 comme identifiant du fournisseur (systemd) et du contenu haché du machine ID. DHCPv6 utilise le même DUID. Deux clones ayant le même machine ID produisent le même hash de DUID. S’ils ont aussi conservé le même nom d’interface, ils envoient un identifiant client identique octet par octet. Le serveur DHCP voit alors un seul client au lieu de deux et propose le même lease aux deux machines. Le symptôme peut être une adresse qui passe d’un serveur à l’autre, ou un serveur qui perd son adresse chaque fois que l’autre renouvelle son lease.

journald. Les fichiers de journal se trouvent dans /var/log/journal/<machine-id>/. Le répertoire porte littéralement le nom de l’ID. Si vous envoyez les journaux de deux clones vers un même collecteur, ils sont placés dans un seul répertoire et lus comme s’ils provenaient d’un seul hôte.

D-Bus. /var/lib/dbus/machine-id est à l’origine de ce format de fichier. Sur Debian et Ubuntu, il s’agit d’un lien symbolique vers /etc/machine-id. Sur certains systèmes, c’est un fichier réel distinct qui contient sa propre copie. Cette copie est le piège décrit dans la procédure ci-dessous.

Agents propres à chaque hôte. Les agents de supervision, les contrôles de licence, les outils d’inventaire et les clients de sauvegarde utilisent souvent le machine ID comme identifiant d’hôte par défaut, car il est stable et ne nécessite aucune configuration. Deux serveurs qui déclarent une seule identité produisent une série de métriques fusionnée ou utilisent un seul siège de licence pour deux machines. Vérifiez comment votre agent détermine son identifiant d’hôte au lieu de supposer qu’il utilise le hostname.

Comment savoir si vous avez un doublon

Exécutez cette commande sur les deux serveurs, puis comparez la sortie.

cat /etc/machine-id
ls -l /var/lib/dbus/machine-id
sudo cat /sys/class/dmi/id/product_uuid

Des machine IDs identiques sur deux serveurs en production signifient que l’un a été cloné à partir de l’autre. hostnamectl affiche la même valeur sur sa ligne Machine ID: si vous préférez utiliser une seule commande.

Le résultat de ls -l détermine la suite des opérations. Un lien symbolique ressemble à ceci :

lrwxrwxrwx 1 root root 15 Aug 21 09:12 /var/lib/dbus/machine-id -> /etc/machine-id

Une ligne qui commence par -rw-r--r-- indique qu’il s’agit d’un fichier réel contenant sa propre copie de l’ancien ID. Vous devez le supprimer, car systemd-machine-id-setup le lit avant toute autre opération.

Le product UUID est également important. systemd-machine-id-setup(1) utilise l’UUID KVM avant de générer une valeur aléatoire. Si votre fournisseur a attribué le même UUID SMBIOS (BIOS de gestion système) aux deux clones, la régénération produit donc deux fois le même machine ID. Des product UUID différents sur les deux serveurs signifient que vous n’avez rien à faire à ce sujet.

Regénérer le machine ID sur un VPS cloné

L’ordre des opérations est important. systemd-machine-id-setup(1) indique que si un machine ID D-Bus valide est déjà configuré pour le système, ce machine ID D-Bus est copié et utilisé pour initialiser /etc/machine-id. Laissez un véritable /var/lib/dbus/machine-id en place et vous régénérerez exactement la valeur que vous cherchiez à supprimer.

sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id       # only if ls -l showed a real file
sudo systemd-machine-id-setup
sudo ln -sf /etc/machine-id /var/lib/dbus/machine-id
cat /etc/machine-id

La troncature préalable est nécessaire, car l’outil n’agit que lorsque le fichier est absent ou vide. Il ne fait rien si le fichier contient déjà un ID valide. systemd-machine-id-setup indique sur la sortie d’erreur standard ce qu’il a fait. Sur un VPS KVM, vous verrez généralement :

Initializing machine ID from KVM UUID.

Initializing machine ID from random generator. est le message affiché lorsqu’aucun UUID d’hyperviseur n’est disponible. Les deux résultats conviennent, à condition que cat /etc/machine-id affiche maintenant une valeur différente de celle de l’autre serveur.

Le lien symbolique conserve une valeur unique pour D-Bus et systemd. Si vous préférez un fichier réel distinct, exécutez plutôt sudo dbus-uuidgen --ensure : cette commande crée le fichier avec un nouvel UUID lorsqu’il n’existe pas. Si dbus n’est pas installé, le répertoire /var/lib/dbus n’existe pas du tout, ln échoue avec No such file or directory et vous pouvez ignorer ces deux lignes.

Redémarrez ensuite.

sudo reboot

Pourquoi le redémarrage est obligatoire

Chaque processus qui a déjà lu l’ancienne valeur continue de l’utiliser. sd_id128_get_machine() met l’ID en cache dans le processus appelant : un daemon en cours d’exécution ne voit donc jamais que le fichier a changé. journald a déjà ouvert /var/log/journal/<old-id>/system.journal et continue d’y ajouter des entrées. systemd-networkd a déterminé son DUID au démarrage et continue d’envoyer l’ancien identifiant client à chaque renouvellement. C’est généralement exactement le problème que vous cherchez à corriger. D-Bus a lui aussi lu son ID au démarrage. Vous pouvez redémarrer les services un par un, mais vous en oublierez un, et PID 1 utilise également l’ancienne valeur.

Après le redémarrage, vérifiez les deux éléments :

cat /etc/machine-id
ls /var/log/journal/

/var/log/journal/ contient maintenant un deuxième répertoire nommé d’après le nouvel ID, et les nouvelles entrées y sont écrites. La commande standard journalctl ne lit que le répertoire de la machine actuelle. Votre historique antérieur au clonage disparaît donc de la vue par défaut. Il est toujours présent sur le disque : journalctl --merge lit tous les répertoires de journaux, y compris l’ancien. Supprimez l’ancien répertoire lorsque vous êtes certain de ne plus avoir besoin de ces journaux.

C’est également pourquoi vous ne pouvez pas répéter la procédure dans un conteneur. Un conteneur partage le kernel de l’hôte et ne démarre jamais son propre PID 1. Or le redémarrage est précisément l’objectif de cette procédure. Testez-la comme en production : clonez une VM, exécutez les commandes, redémarrez, puis comparez l’ID avec celui de la machine source.

Tronquez avant de créer un snapshot, pas après le clonage

Corriger les clones un par un fonctionne. Corriger l’image est préférable, car chaque serveur restauré depuis un mauvais snapshot récupère la même valeur. Faites-le en dernier, juste avant d’arrêter le template.

sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id
sudo shutdown -h now

Videz le fichier. Ne le supprimez pas. machine-id(5) recommande un fichier vide pour les images utilisées sur plusieurs machines, car un fichier vide déjà présent permet de monter temporairement un fichier par bind par-dessus le fichier réel lorsque l’image est utilisée en lecture seule. Sur un /etc en lecture seule, l’identifiant généré au démarrage est stocké dans ce fichier temporaire, puis systemd-machine-id-setup --commit l’écrit une fois que le système de fichiers est accessible en écriture.

Un effet secondaire est à prendre en compte : un machine ID absent indique que le prochain démarrage est le premier démarrage. Les unités qui contiennent ConditionFirstBoot=yes s’exécutent donc lors de ce démarrage, puis sont ignorées lors de tous les démarrages suivants. Vérifiez ce que votre image exécuterait avec grep -rl ConditionFirstBoot /usr/lib/systemd/system/ avant de créer le template.

Un template et un snapshot sont deux objets différents. Cette différence détermine si l’identité est copiée. Un template est un artefact de build que vous préparez volontairement, tandis que un snapshot est une copie à un instant donné d’un serveur en fonctionnement et conserve l’identité de ce serveur avec ses données.

Pourquoi les images cloud gèrent correctement ce cas, contrairement à votre snapshot

Les images cloud des distributions sont conçues pour être clonées. Leur machine ID n’est donc pas renseigné lors de la création, puis le premier démarrage le génère. cloud-init prévoit une étape documentée pour cela. cloud-init clean --machine-id définit /etc/machine-id sur la chaîne littérale uninitialized dans les systèmes systemd. La référence de la CLI cloud-init recommande cette méthode pour cloner une image de référence. Au démarrage suivant, cette image génère ainsi un machine ID unique.

Un snapshot que vous avez créé vous-même fonctionne différemment. Le fichier contenait déjà une valeur lorsque vous avez lancé la création du snapshot. Tous les serveurs restaurés depuis ce snapshot reprennent donc cette même valeur, et rien dans le processus de restauration ne la supprime. C’est le même type de problème que déplacer un serveur en fonctionnement vers un nouveau VPS : la copie est fidèle, alors que l’identité est précisément l’élément que vous ne vouliez pas copier.

Ce qu’un clone duplique également

  • Les clés d’hôte SSH. /etc/ssh/ssh_host_* est également copié, et les deux serveurs présentent donc la même empreinte aux clients. Supprimez ces fichiers, puis exécutez sudo ssh-keygen -A ou sudo dpkg-reconfigure openssh-server sur Debian et Ubuntu. Vos clients signaleront ensuite une modification de la clé d’hôte, ce qui est le comportement attendu.
  • Le nom d’hôte. Définissez-le avec sudo hostnamectl set-hostname app02, puis vérifiez que /etc/hosts résout toujours le nouveau nom.
  • La configuration réseau statique. Le clone d’une machine dotée d’une adresse statique entre en conflit avec l’original dès qu’il démarre. Consultez /etc/netplan/ avant que le clone rejoigne le réseau.
  • L’horloge. Un snapshot restauré reprend l’heure à laquelle le snapshot a été créé. Un important décalage de l’horloge sur un VPS restauré empêche la validation des certificats TLS et désorganise l’ordre des journaux jusqu’à la resynchronisation de l’heure.

Suivez également la checklist des dix premières minutes pour un nouveau VPS sur le clone. Un clone hérite des comptes utilisateur, des clés SSH, des règles de pare-feu et des tâches planifiées de la machine source, sans qu’aucun de ces éléments n’ait été vérifié pour le rôle que le clone va remplir.

FAQ

Dois-je redémarrer après avoir modifié /etc/machine-id ?

Oui. Les processus lisent l’identifiant de la machine une seule fois et le mettent en cache. La nouvelle valeur n’atteint donc aucun processus déjà en cours d’exécution. journald continue d’écrire dans le répertoire du journal portant l’ancien identifiant. Le client DHCP continue aussi d’envoyer un identifiant client dérivé de l’ancienne valeur. C’est généralement la raison pour laquelle vous avez modifié cette valeur. Redémarrer les services individuellement en corrige certains, mais PID 1 conserve lui aussi l’ancienne valeur. Redémarrez, puis vérifiez avec cat /etc/machine-id et comparez avec l’autre serveur.

/etc/machine-id est-il identique à l’UUID matériel ?

Non. L’UUID produit DMI dans /sys/class/dmi/id/product_uuid provient de l’hyperviseur et n’est lisible que par root. L’identifiant de la machine est généré par le système d’exploitation et se trouve dans un fichier texte lisible par tout utilisateur. Ils sont liés dans un seul sens : sur un invité KVM, systemd-machine-id-setup utilise l’UUID de l’hyperviseur pour générer un nouvel identifiant de machine lorsqu’il n’existe aucun identifiant D-Bus à copier. Si deux clones partagent le même UUID produit, ils régénéreront le même identifiant de machine. Comparez donc aussi ce fichier avant de considérer le résultat comme fiable.

Dois-je supprimer /etc/machine-id ou le laisser vide ?

Laissez-le vide lorsque vous préparez une image. machine-id(5) préfère un fichier vide, car systemd peut monter temporairement un fichier par-dessus lorsque l’image s’exécute avec un /etc en lecture seule. La suppression du fichier fonctionne sur un système accessible en écriture, et certains scripts de clonage procèdent ainsi. Cependant, le fichier vide constitue le choix par défaut le plus sûr. cloud-init écrit le mot uninitialized dans le fichier pour la même raison.

Pourquoi mes deux serveurs clonés ont-ils reçu la même adresse DHCP ?

Parce qu’ils ont envoyé le même identifiant client. systemd-networkd utilise par défaut ClientIdentifier=duid pour DHCPv4, et le DUID par défaut est construit à partir d’un hachage de /etc/machine-id. Des identifiants de machine identiques produisent donc des identifiants clients identiques sur des clones qui ont également conservé le même nom d’interface. Le serveur DHCP fait la correspondance avec cet identifiant, considère les deux requêtes comme provenant d’un seul client et attribue un seul bail. Attribuez à chaque serveur son propre identifiant de machine, puis redémarrez les deux serveurs. Si le serveur propose encore l’ancienne adresse, supprimez l’ancien bail directement sur le serveur DHCP.

#machine-id#systemd#cloning#snapshots#dhcp