SSD Nodes Learn 🎉 VPS ab $5.50/Monat
Anleitungen Matt ConnorVon Matt Connor

Doppelte machine-id nach VPS-Klon beheben

Zwei VPS-Klone mit derselben /etc/machine-id konkurrieren um DHCP-Leases. Leeren Sie die Datei, entfernen Sie die D-Bus-Kopie und starten Sie danach neu.

Was /etc/machine-id ist und warum ein Duplikat relevant ist

Ein geklonter VPS startet mit derselben /etc/machine-id wie der Server, von dem er geklont wurde. Dieser Wert darf jedoch nur zu genau einer Installation gehören. Die Korrektur besteht aus vier Befehlen: Datei leeren, die D-Bus-Kopie entfernen, falls es sich um eine echte Datei handelt, die ID neu erzeugen und das System neu starten. Den Neustart überspringen viele. Er sorgt jedoch dafür, dass die Änderung wirksam wird.

/etc/machine-id enthält eine mit einem Zeilenumbruch abgeschlossene hexadezimale Zeichenfolge mit 32 Kleinbuchstaben und -ziffern. Decodiert entspricht sie einem 16 Byte (128 Bit) langen Wert. Die Handbuchseite zu machine-id(5) bezeichnet diesen Wert als vertraulich. Sie weist darauf hin, dass er nicht über das Netzwerk offengelegt werden darf, weil jedes System, das ihn ausliest, Ihren Rechner später wiedererkennen kann. Der Wert wird bei der Installation des Systems einmalig geschrieben. Danach wird er nicht mehr geändert.

Hier werden drei Kennungen häufig verwechselt. Daher sollten sie getrennt betrachtet werden. Der Hostname ist eine Bezeichnung, die Sie selbst festlegen und jederzeit ändern können. Die DMI-Produkt-UUID (Desktop Management Interface) in /sys/class/dmi/id/product_uuid wird vom Hypervisor bereitgestellt und kann nur von root gelesen werden. Die Machine-ID ist die dritte Kennung: Das Betriebssystem erzeugt sie, und jeder Benutzer auf dem Rechner kann sie lesen.

Was die Maschinen-ID tatsächlich ausliest

Die DHCP-Clientkennung. Das ist der kritische Punkt. systemd.network(5) dokumentiert im Abschnitt [DHCPv4], dass ClientIdentifier= standardmäßig auf duid gesetzt ist. Dadurch wird eine RFC-4361-Clientkennung aus einer IAID und einer DUID (eindeutige DHCP-Kennung) gesendet. networkd.conf(5) dokumentiert vendor als standardmäßigen DUID-Typ. Dabei wird der DUID-Wert mit 43793 als Herstellerkennung (systemd) und aus gehashten Inhalten der Maschinen-ID erzeugt. DHCPv6 verwendet dieselbe DUID. Zwei Klone mit derselben Maschinen-ID erzeugen dieselbe DUID. Wenn sie außerdem denselben Schnittstellennamen beibehalten, senden sie eine byte-identische Clientkennung. Der DHCP-Server erkennt dann einen Client statt zwei und bietet beiden Systemen dieselbe Lease an. Das äußert sich darin, dass eine Adresse zwischen den beiden Servern wechselt oder ein Server seine Adresse verliert, sobald der andere die Lease erneuert.

journald. Journaldateien liegen in /var/log/journal/<machine-id>/. Das Verzeichnis trägt wörtlich den Namen der ID. Wenn Sie die Journals zweier Klone an einen Collector senden, landen sie unter einem gemeinsamen Verzeichnis und werden als ein Host gelesen.

D-Bus. In /var/lib/dbus/machine-id hat dieses Dateiformat seinen Ursprung. Unter Debian und Ubuntu ist dies ein symbolischer Link auf /etc/machine-id. Auf manchen Systemen handelt es sich um eine separate reguläre Datei mit einer eigenen Kopie. Diese Kopie ist der kritische Punkt im folgenden Verfahren.

Pro-Host-Agenten. Monitoring-Agenten, Lizenzprüfungen, Inventarisierungswerkzeuge und Backup-Clients verwenden die Maschinen-ID häufig standardmäßig als Hostkennung, weil sie stabil ist und keine Konfiguration benötigt. Wenn zwei Server dieselbe Identität melden, entsteht eine zusammengeführte Metrikserie oder ein Lizenzplatz deckt zwei Systeme ab. Prüfen Sie, wie Ihr Agent seine Host-ID ableitet, statt anzunehmen, dass er den Hostnamen verwendet.

So erkennen Sie, ob eine Duplikatkopie vorliegt

Führen Sie dies auf beiden Servern aus und vergleichen Sie die Ausgabe.

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

Identische Machine IDs auf zwei aktiven Servern bedeuten, dass einer vom anderen geklont wurde. hostnamectl gibt in seiner Machine ID:-Zeile denselben Wert aus, wenn Sie einen einzelnen Befehl bevorzugen.

Das Ergebnis von ls -l bestimmt den nächsten Schritt. Ein symbolischer Link sieht so aus:

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

Eine mit -rw-r--r-- beginnende Zeile bedeutet, dass es sich um eine echte Datei mit einer eigenen Kopie der alten ID handelt. Sie müssen diese Datei entfernen, weil systemd-machine-id-setup sie liest, bevor es irgendetwas anderes tut.

Auch die Product UUID ist relevant. systemd-machine-id-setup(1) verwendet zuerst die KVM-UUID und greift erst danach auf eine zufällige Generierung zurück. Wenn Ihr Provider beiden Klonen dieselbe SMBIOS-UUID (System-Management-BIOS-UUID) zugewiesen hat, erzeugt die Neugenerierung daher zweimal dieselbe Machine ID. Unterschiedliche Product UUIDs auf den beiden Servern bedeuten, dass Sie sich darüber keine Gedanken machen müssen.

Die Machine-ID auf einem geklonten VPS neu erzeugen

Die Reihenfolge ist wichtig. systemd-machine-id-setup(1) legt fest, dass eine bereits gültige D-Bus-Machine-ID des Systems kopiert und zur Initialisierung von /etc/machine-id verwendet wird. Lassen Sie eine echte /var/lib/dbus/machine-id bestehen, erzeugen Sie genau den Wert erneut, den Sie eigentlich entfernen wollten.

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

Das vorherige Leeren ist erforderlich, weil das Tool nur ausgeführt wird, wenn die Datei fehlt oder leer ist. Bei einer Datei, die bereits eine gültige ID enthält, führt es keine Aktion aus. systemd-machine-id-setup meldet seine Aktion auf der Standardfehlerausgabe. Auf einem KVM-VPS sehen Sie normalerweise:

Initializing machine ID from KVM UUID.

Initializing machine ID from random generator. ist die Meldung, wenn keine Hypervisor-UUID verfügbar ist. Beide Ergebnisse sind in Ordnung, solange cat /etc/machine-id jetzt einen anderen Wert als der andere Server ausgibt.

Der symbolische Link sorgt dafür, dass D-Bus und systemd denselben Wert verwenden. Wenn Sie stattdessen eine separate reguläre Datei bevorzugen, führen Sie sudo dbus-uuidgen --ensure aus. Der Befehl erstellt die Datei mit einer neuen UUID, wenn sie nicht vorhanden ist. Wenn dbus nicht installiert ist, gibt es das Verzeichnis /var/lib/dbus überhaupt nicht, ln schlägt mit No such file or directory fehl, und Sie können beide Zeilen überspringen.

Starten Sie den Server anschließend neu.

sudo reboot

Warum der Reboot nicht optional ist

Jeder Prozess, der den alten Wert bereits eingelesen hat, verwendet ihn weiterhin. sd_id128_get_machine() cached die ID im aufrufenden Prozess. Ein laufender Daemon bemerkt daher nie, dass sich die Datei geändert hat. journald hat /var/log/journal/<old-id>/system.journal bereits geöffnet und hängt weiterhin Einträge daran an. systemd-networkd hat seine DUID beim Start ermittelt und sendet bei jeder Erneuerung weiterhin den alten Client-Identifier. Das ist normalerweise genau der Fehler, den Sie beheben wollten. Auch D-Bus hat seine ID beim Start eingelesen. Sie können die Dienste einzeln neu starten. Dabei werden Sie jedoch einen Dienst übersehen. Außerdem hält PID 1 den alten Wert ebenfalls noch.

Prüfen Sie nach dem Reboot beide Seiten:

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

/var/log/journal/ enthält jetzt ein zweites Verzeichnis, das nach der neuen ID benannt ist. Neue Einträge werden dort abgelegt. Einfaches journalctl liest nur das Verzeichnis der aktuellen Maschine. Daher verschwindet der Verlauf vor dem Klonen aus der Standardansicht. Er befindet sich weiterhin auf der Festplatte: journalctl --merge liest jedes Journalverzeichnis einschließlich des alten. Löschen Sie das alte Verzeichnis, sobald Sie sicher sind, dass Sie diese Logs nicht mehr benötigen.

Deshalb können Sie den Ablauf auch nicht in einem Container testen. Ein Container verwendet den Kernel des Hosts und startet niemals eine eigene PID 1. Der Reboot ist jedoch der zentrale Zweck dieses Ablaufs. Testen Sie ihn so, wie er in der Produktion ausgeführt wird: Klonen Sie eine VM, führen Sie die Befehle aus, starten Sie sie neu und vergleichen Sie anschließend die ID mit der Quellmaschine.

Vor dem Snapshot leeren, nicht nach dem Klonen

Clones einzeln zu korrigieren funktioniert. Besser ist es, das Image zu korrigieren, weil jeder aus einem fehlerhaften Snapshot wiederhergestellte Server denselben Wert übernimmt. Führen Sie diesen Schritt als Letztes aus, bevor Sie das Template herunterfahren.

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

Leeren Sie die Datei. Löschen Sie sie nicht. machine-id(5) empfiehlt für Images, die auf mehreren Maschinen verwendet werden, eine leere Datei, weil eine vorhandene leere Datei durch eine temporäre Datei über der eigentlichen Datei per Bind-Mount eingebunden werden kann, wenn das Image schreibgeschützt verwendet wird. Auf einem schreibgeschützten /etc wird die beim Booten erzeugte ID in dieser temporären Datei gespeichert. Sobald das Dateisystem beschreibbar ist, schreibt systemd-machine-id-setup --commit die ID dauerhaft.

Planen Sie einen Nebeneffekt ein: Eine nicht befüllte Machine ID kennzeichnet den nächsten Boot als ersten Boot. Daher werden Units mit ConditionFirstBoot=yes bei diesem Boot ausgeführt und bei jedem weiteren Boot übersprungen. Prüfen Sie mit grep -rl ConditionFirstBoot /usr/lib/systemd/system/, was Ihr Image ausführen würde, bevor Sie das Template erstellen.

Ein Template und ein Snapshot sind unterschiedliche Objekte. Dieser Unterschied entscheidet darüber, ob die Identität kopiert wird. Ein Template ist ein bewusst vorbereitetes Build-Artefakt. Ein Snapshot ist dagegen eine Momentaufnahme eines laufenden Servers und übernimmt dessen Identität zusammen mit den Daten.

Warum Cloud-Images dies richtig machen und Ihr Snapshot nicht

Cloud-Images von Distributionen werden zum Klonen erstellt. Deshalb enthalten sie zunächst keine gesetzte machine ID, die beim ersten Boot-Vorgang eingetragen wird. cloud-init verfügt dafür über einen dokumentierten Schritt. cloud-init clean --machine-id setzt /etc/machine-id auf die Literalzeichenfolge uninitialized auf systemd-Systemen. Die CLI-Referenz von cloud-init beschreibt dies beim Klonen eines Golden Image als Best Practice. Beim nächsten Boot-Vorgang dieses Images wird dadurch eine eindeutige machine ID erzeugt.

Bei einem selbst erstellten Snapshot ist die Situation anders. Die Datei enthielt bereits einen Wert, als Sie den Snapshot erstellt haben. Deshalb übernimmt jeder daraus wiederhergestellte Server diesen Wert. Der Wiederherstellungsvorgang löscht ihn nicht. Dies ist dieselbe Problemklasse wie beim Verschieben eines laufenden Servers auf einen neuen VPS. Die Kopie ist vollständig. Die Identität ist jedoch genau der Teil, der nicht kopiert werden sollte.

Was ein Klon außerdem dupliziert

  • SSH-Hostschlüssel. /etc/ssh/ssh_host_* wird ebenfalls kopiert, daher präsentieren beide Server den Clients denselben Fingerabdruck. Löschen Sie diese Dateien und führen Sie sudo ssh-keygen -A oder unter Debian und Ubuntu sudo dpkg-reconfigure openssh-server aus. Ihre Clients warnen anschließend vor einem geänderten Hostschlüssel. Das ist das erwartete Verhalten.
  • Der Hostname. Setzen Sie ihn mit sudo hostnamectl set-hostname app02 und prüfen Sie anschließend, ob /etc/hosts den neuen Namen weiterhin auflöst.
  • Statische Netzwerkkonfiguration. Ein Klon eines Systems mit einer statischen Adresse verursacht in dem Moment einen Konflikt mit dem Original, in dem er gestartet wird. Lesen Sie /etc/netplan/, bevor der Klon dem Netzwerk beitritt.
  • Die Uhrzeit. Ein wiederhergestellter Snapshot läuft mit der Uhrzeit weiter, die beim Erstellen des Snapshots gültig war. Ein großer Zeitsprung auf einem wiederhergestellten VPS verhindert die Validierung von TLS-Zertifikaten und bringt die Reihenfolge der Logs durcheinander, bis die Zeitsynchronisierung aufgeholt hat.

Arbeiten Sie auch auf dem Klon die Checkliste für die ersten zehn Minuten mit einem neuen VPS durch. Ein geklontes System übernimmt die Benutzerkonten, SSH-Schlüssel, Firewall-Regeln und geplanten Jobs des Quellsystems. Nichts davon wurde für die Aufgabe geprüft, die der Klon ausführen soll.

FAQ

Muss ich nach einer Änderung an /etc/machine-id neu starten?

Ja. Prozesse lesen die Machine-ID einmal ein und speichern sie zwischen. Der neue Wert erreicht daher nichts, was bereits läuft. journald schreibt weiterhin in das Journalverzeichnis, das nach der alten ID benannt ist. Der DHCP-Client sendet weiterhin einen aus dem alten Wert abgeleiteten Client-Identifier. Das ist normalerweise der Grund für die Änderung. Das Neustarten einzelner Dienste behebt einige dieser Probleme. PID 1 verwendet jedoch ebenfalls weiterhin den alten Wert. Starten Sie das System neu. Prüfen Sie anschließend mit cat /etc/machine-id und durch einen Vergleich mit dem anderen Server, ob der Wert stimmt.

Ist /etc/machine-id dasselbe wie die Hardware-UUID?

Nein. Die DMI-Produkt-UUID in /sys/class/dmi/id/product_uuid stammt vom Hypervisor und ist nur für root lesbar. Die Machine-ID wird vom Betriebssystem erzeugt und steht in einer normalen Datei, die jeder Benutzer lesen kann. Die Werte hängen nur in eine Richtung zusammen: Bei einem KVM-Gast verwendet systemd-machine-id-setup die UUID des Hypervisors als Grundlage für eine neue Machine-ID, wenn keine D-Bus-ID zum Kopieren vorhanden ist. Wenn zwei Klone dieselbe Produkt-UUID haben, erzeugen sie erneut dieselbe Machine-ID. Vergleichen Sie daher auch diese Datei, bevor Sie dem Ergebnis vertrauen.

Sollte ich /etc/machine-id löschen oder leer lassen?

Lassen Sie die Datei leer, wenn Sie ein Image vorbereiten. machine-id(5) bevorzugt eine leere Datei, weil systemd eine temporäre Datei darüber binden kann, wenn das Image mit einem schreibgeschützten /etc ausgeführt wird. Das Löschen der Datei funktioniert auf einem beschreibbaren System, und manche Klon-Skripte gehen so vor. Die leere Datei ist jedoch die sicherere Standardeinstellung. cloud-init schreibt zu diesem Zweck das Wort uninitialized in die Datei.

Warum haben meine beiden geklonten Server dieselbe DHCP-Adresse erhalten?

Weil beide denselben Client-Identifier gesendet haben. systemd-networkd verwendet für DHCPv4 standardmäßig ClientIdentifier=duid. Der Standard-DUID wird aus einem Hash von /etc/machine-id gebildet. Identische Machine-IDs erzeugen daher bei Klonen, die auch denselben Schnittstellennamen beibehalten haben, identische Identifier. Der DHCP-Server ordnet beide Anfragen anhand dieses Identifiers demselben Client zu und vergibt eine Lease. Geben Sie jedem System eine eigene Machine-ID und starten Sie beide neu. Wenn der Server weiterhin die alte Adresse anbietet, löschen Sie die veraltete Lease direkt auf dem DHCP-Server.

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