SSD Nodes Learn 🎉 VPS da $5.50/mese
Guide Matt ConnorDi Matt Connor

Correggere un machine-id duplicato dopo la clonazione VPS

Due VPS clonate con lo stesso /etc/machine-id possono contendersi il lease DHCP. Scopri i quattro comandi per rigenerarlo e azzerarlo prima dello snapshot.

Che cos’è /etc/machine-id e perché un duplicato è importante

Una VPS clonata si avvia con lo stesso /etc/machine-id del server da cui è stata clonata, ma questo valore dovrebbe appartenere a una sola installazione. La correzione richiede quattro comandi: svuotare il file, rimuovere la copia di D-Bus se è un file reale, rigenerare l’identificativo e riavviare. Il riavvio è il passaggio che spesso viene omesso, ma è quello che rende effettiva la modifica.

/etc/machine-id contiene una stringa esadecimale minuscola di 32 caratteri, terminata da un carattere di nuova riga. Decodificata, corrisponde a un valore di 16 byte (128 bit). La pagina del manuale di machine-id(5) la definisce riservata e specifica che non deve essere esposta sulla rete, perché chiunque la legga può riconoscere nuovamente la macchina in seguito. Viene scritta una sola volta, durante l’installazione del sistema, e in seguito non viene modificata.

In questo contesto si confondono tre identificativi, che è opportuno distinguere. Il nome host è un’etichetta scelta dall’amministratore e modificabile in qualsiasi momento. L’UUID del prodotto DMI (desktop management interface) in /sys/class/dmi/id/product_uuid proviene dall’hypervisor ed è leggibile soltanto da root. Il machine ID è il terzo identificativo: viene generato dal sistema operativo e può essere letto da qualsiasi utente della macchina.

Che cosa legge effettivamente il machine ID

L'identificatore client DHCP. È il caso più problematico. systemd.network(5) documenta ClientIdentifier= nella sezione [DHCPv4] come impostazione predefinita a duid, che invia un identificatore client RFC 4361 costruito a partire da un IAID e da un DUID (identificatore univoco DHCP). networkd.conf(5) documenta il tipo DUID predefinito come vendor, in cui il valore DUID viene generato usando 43793 come identificatore del fornitore (systemd) e il contenuto sottoposto a hash del machine ID. DHCPv6 usa lo stesso DUID. Due cloni con lo stesso machine ID producono lo stesso hash DUID e, se mantengono anche lo stesso nome dell'interfaccia, inviano un identificatore client identico a livello di byte. Il server DHCP vede quindi un solo client invece di due e assegna a entrambe le macchine lo stesso lease. Il sintomo è un indirizzo che passa da un server all'altro, oppure la perdita dell'indirizzo da parte di un server ogni volta che l'altro rinnova il lease.

journald. I file journal si trovano in /var/log/journal/<machine-id>/. La directory ha letteralmente il nome dell'ID. Se si inviano i journal di due cloni allo stesso collector, questi vengono salvati in un'unica directory e risultano appartenere a un solo host.

D-Bus. /var/lib/dbus/machine-id è il punto di origine di questo formato di file. Su Debian e Ubuntu è un symlink a /etc/machine-id. Su alcuni sistemi è un file reale separato che contiene una propria copia; questa copia è l'insidia descritta nella procedura seguente.

Agenti specifici per host. Gli agenti di monitoraggio, i controlli delle licenze, gli strumenti di inventario e i client di backup usano spesso il machine ID come identificatore host predefinito, perché è stabile e non richiede configurazione. Se due server comunicano la stessa identità, si ottiene un'unica serie di metriche aggregata oppure una sola licenza che copre due macchine. Verificare come l'agente ricava il proprio host ID invece di presumere che usi il nome host.

Come verificare se esiste un duplicato

Eseguire questo comando su entrambi i server e confrontare l’output.

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

ID macchina identici su due server attivi indicano che uno è stato clonato dall’altro. Se si preferisce usare un solo comando, hostnamectl stampa lo stesso valore nella relativa riga Machine ID:.

Il risultato di ls -l determina il passaggio successivo. Un link simbolico ha questo aspetto:

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

Una riga che inizia con -rw-r--r-- indica che si tratta di un file reale che contiene una propria copia del vecchio ID. È necessario rimuoverlo, perché systemd-machine-id-setup lo legge prima di eseguire qualsiasi altra operazione.

Anche l’UUID del prodotto è importante. systemd-machine-id-setup(1) usa l’UUID KVM prima di ricorrere alla generazione casuale. Se il provider ha assegnato ai due cloni lo stesso UUID SMBIOS (System Management BIOS), la rigenerazione produce due volte lo stesso ID macchina. UUID del prodotto diversi sui due server indicano che non ci sono problemi sotto questo aspetto.

Rigenerare l'ID della macchina su un VPS clonato

L'ordine è importante. systemd-machine-id-setup(1) specifica che, se nel sistema è già configurato un ID macchina D-Bus valido, quell'ID macchina D-Bus viene copiato e usato per inizializzare /etc/machine-id. Lasciate un /var/lib/dbus/machine-id reale al suo posto e rigenererete esattamente il valore che stavate cercando di eliminare.

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

È necessario troncare prima il file, perché lo strumento interviene solo quando il file è assente o vuoto e non modifica un file che contiene già un ID valido. systemd-machine-id-setup indica su standard error l'operazione eseguita. Su un VPS KVM verrà normalmente visualizzato:

Initializing machine ID from KVM UUID.

Initializing machine ID from random generator. è il messaggio visualizzato quando non è disponibile alcun UUID dell'hypervisor. Entrambi i risultati sono corretti, purché cat /etc/machine-id restituisca ora un valore diverso da quello dell'altro server.

Il collegamento simbolico mantiene D-Bus e systemd sullo stesso valore. Se preferite un file reale separato, eseguite invece sudo dbus-uuidgen --ensure: crea il file con un nuovo UUID quando il file non esiste. Se dbus non è installato, la directory /var/lib/dbus non esiste affatto, ln fallisce con No such file or directory e potete saltare entrambe le righe.

Quindi riavviate.

sudo reboot

Perché il riavvio non è facoltativo

Ogni processo che ha già letto il vecchio valore continua a utilizzarlo. sd_id128_get_machine() memorizza l'ID nel processo chiamante, quindi un demone in esecuzione non rileva mai la modifica del file. journald ha già aperto /var/log/journal/<old-id>/system.journal e continua ad aggiungervi dati. systemd-networkd ha determinato il proprio DUID all'avvio e continua a inviare il vecchio identificatore client a ogni rinnovo. Di solito, questo è esattamente il problema che si intende risolvere. Anche D-Bus legge il proprio ID all'avvio. È possibile riavviare i servizi uno alla volta, ma se ne dimenticherà qualcuno e anche PID 1 conserva il vecchio valore.

Dopo il riavvio, verificare entrambe le parti:

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

/var/log/journal/ ora contiene una seconda directory con il nuovo ID come nome e le nuove voci vengono scritte al suo interno. journalctl senza opzioni legge soltanto la directory della macchina corrente, quindi la cronologia precedente alla clonazione scompare dalla vista predefinita. I dati sono ancora presenti sul disco: journalctl --merge legge tutte le directory del journal, compresa quella precedente. Eliminare la directory precedente quando si è certi di non aver più bisogno di quei log.

Per questo non è possibile provare la procedura in un container. Un container condivide il kernel dell'host e non avvia un proprio PID 1; inoltre, il riavvio è il punto centrale della procedura. Eseguire il test come avverrebbe in produzione: clonare una VM, eseguire i comandi, riavviare e quindi confrontare l'ID con quello della macchina di origine.

Azzera il machine ID prima di creare lo snapshot, non dopo il clone

Correggere i cloni uno alla volta funziona. Correggere l'immagine è meglio, perché ogni server ripristinato da uno snapshot errato eredita lo stesso valore. Esegui questa operazione per ultima, prima di arrestare il 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

Svuota il file. Non eliminarlo. machine-id(5) consiglia un file vuoto per le immagini usate su più macchine, perché un file vuoto già presente consente di montare temporaneamente un file sopra quello reale tramite bind mount quando l'immagine viene usata in modalità di sola lettura. Su un /etc di sola lettura, l'ID generato durante il boot viene memorizzato in quel file temporaneo e systemd-machine-id-setup --commit lo scrive nel file definitivo quando il filesystem diventa scrivibile.

Considera un effetto collaterale: un machine ID non valorizzato identifica il boot successivo come primo boot. Di conseguenza, le unit che contengono ConditionFirstBoot=yes vengono eseguite durante quel boot e ignorate in tutti i boot successivi. Prima di creare il template, verifica cosa eseguirebbe la tua immagine con grep -rl ConditionFirstBoot /usr/lib/systemd/system/.

Un template e uno snapshot sono oggetti diversi e questa differenza determina se l'identità viene copiata. Un template è un artefatto di build che prepari intenzionalmente, mentre uno snapshot è una copia point-in-time di un server in esecuzione e ne conserva l'identità insieme ai dati.

Perché le immagini cloud gestiscono correttamente l’identità, mentre il tuo snapshot no

Le immagini cloud delle distribuzioni sono progettate per essere clonate. Per questo vengono fornite con il machine ID non valorizzato e il primo avvio lo genera. cloud-init include un passaggio documentato specificamente per questo caso. cloud-init clean --machine-id imposta /etc/machine-id sulla stringa letterale uninitialized nei sistemi systemd. La documentazione di riferimento della CLI di cloud-init lo indica come procedura consigliata quando si clona una golden image. Al successivo avvio dell’immagine viene quindi generato un machine ID univoco.

Uno snapshot creato autonomamente è diverso. Il file conteneva già un valore quando hai creato lo snapshot. Di conseguenza, ogni server ripristinato da quello snapshot mantiene lo stesso valore. Il processo di ripristino non lo rimuove. È la stessa classe di problema di spostare un server in esecuzione su un nuovo VPS, dove la copia è fedele e l’identità è proprio l’elemento che non volevi copiare.

Cos’altro duplica un clone

  • Chiavi host SSH. Anche /etc/ssh/ssh_host_* viene copiato, quindi entrambi i server presentano ai client la stessa impronta digitale. Rimuovi questi file ed esegui sudo ssh-keygen -A oppure sudo dpkg-reconfigure openssh-server su Debian e Ubuntu. In seguito i client segnaleranno la modifica della chiave host. Questo è il comportamento corretto.
  • Il nome host. Impostalo con sudo hostnamectl set-hostname app02, quindi verifica che /etc/hosts risolva ancora il nuovo nome.
  • Configurazione di rete statica. Un clone di un sistema con un indirizzo statico entra in conflitto con l’originale non appena viene avviato. Leggi /etc/netplan/ prima che il clone si colleghi alla rete.
  • L’orologio. Uno snapshot ripristinato riprende l’ora presente al momento della creazione dello snapshot. Un grande salto dell’orologio su un VPS ripristinato interrompe la convalida dei certificati TLS e altera l’ordine dei log finché la sincronizzazione dell’ora non si aggiorna.

Esegui anche sul clone la checklist dei primi dieci minuti per un nuovo VPS. Un sistema clonato eredita gli account utente, le chiavi SSH, le regole del firewall e i job pianificati del sistema di origine, ma nessuno di questi elementi è stato verificato per il compito che il clone dovrà svolgere.

FAQ

Devo riavviare dopo aver modificato /etc/machine-id?

Sì. I processi leggono il machine ID una sola volta e lo memorizzano nella cache, quindi il nuovo valore non viene applicato ai processi già in esecuzione. journald continua a scrivere nella directory del journal denominata con il vecchio ID e il client DHCP continua a inviare un identificatore client derivato dal vecchio valore, che è in genere il motivo della modifica. Il riavvio dei singoli servizi risolve il problema solo per alcuni di essi, ma anche PID 1 conserva il vecchio valore. Riavvia il sistema, quindi verifica con cat /etc/machine-id e confronta il risultato con quello dell'altro server.

/etc/machine-id corrisponde all'UUID dell'hardware?

No. L'UUID del prodotto DMI mostrato da /sys/class/dmi/id/product_uuid proviene dall'hypervisor ed è leggibile solo da root. Il machine ID viene generato dal sistema operativo e si trova in un file di testo che qualsiasi utente può leggere. Il collegamento funziona in una sola direzione: su un guest KVM, systemd-machine-id-setup usa l'UUID dell'hypervisor per generare un nuovo machine ID quando non esiste un ID D-Bus da copiare. Se due cloni condividono lo stesso UUID del prodotto, rigenereranno lo stesso machine ID. Prima di considerare affidabile il risultato, confronta quindi anche quel file.

Devo eliminare /etc/machine-id o lasciarlo vuoto?

Lascialo vuoto quando prepari un'immagine. machine-id(5) preferisce un file vuoto, perché systemd può montare temporaneamente un file sopra di esso quando l'immagine viene eseguita con un /etc in sola lettura. Eliminare il file funziona su un sistema scrivibile e alcuni script di clonazione adottano questo metodo, ma il file vuoto è l'impostazione predefinita più sicura. cloud-init scrive la parola uninitialized nel file per lo stesso scopo.

Perché i due server clonati hanno ricevuto lo stesso indirizzo DHCP?

Perché entrambi hanno inviato lo stesso identificatore client. systemd-networkd usa per impostazione predefinita ClientIdentifier=duid per DHCPv4 e il DUID predefinito viene costruito a partire da un hash di /etc/machine-id. Di conseguenza, machine ID identici producono identificatori identici sui cloni che hanno mantenuto anche lo stesso nome dell'interfaccia. Il server DHCP associa le richieste a quell'identificatore, considera entrambe le richieste provenienti dallo stesso client e assegna un unico lease. Assegna a ciascun server un proprio machine ID e riavviali entrambi. Se il server continua a offrire il vecchio indirizzo, elimina il lease obsoleto direttamente sul server DHCP.

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