SSD Nodes Learn 🎉 VPS desde $5.50/mes
Guías Matt ConnorPor Matt Connor

Cómo corregir un machine-id duplicado al clonar un VPS

Evita conflictos de DHCP entre clones que comparten /etc/machine-id. Vacíalo, regenera el identificador y reinicia; antes de crear la imagen, trúncalo.

Qué es /etc/machine-id y por qué importa que esté duplicado

Un VPS clonado arranca con el mismo /etc/machine-id que el servidor del que se clonó, aunque ese valor debe pertenecer a una sola instalación. La solución consta de cuatro comandos: vaciar el archivo, eliminar la copia de D-Bus si es un archivo real, regenerar el identificador y reiniciar. El reinicio es el paso que se suele omitir y es el que hace efectivo el cambio.

/etc/machine-id contiene una cadena hexadecimal en minúsculas, terminada en salto de línea y de 32 caracteres. Una vez decodificada, representa un valor de 16 bytes (128 bits). La página de manual de machine-id(5) la califica de confidencial e indica que no debe exponerse en la red, porque cualquier entidad que la lea puede reconocer de nuevo la máquina más adelante. Se escribe una vez, durante la instalación del sistema, y después nada la modifica.

Aquí se suelen confundir tres identificadores, por lo que conviene separarlos. El nombre de host es una etiqueta que se elige y se puede cambiar en cualquier momento. El UUID de producto DMI (desktop management interface) de /sys/class/dmi/id/product_uuid procede del hipervisor y sólo root puede leerlo. El machine ID es el tercero: lo genera el sistema operativo y cualquier usuario del equipo puede leerlo.

Qué lee realmente el ID de máquina

El identificador del cliente DHCP. Este es el caso más problemático. systemd.network(5) documenta ClientIdentifier= en la sección [DHCPv4] y establece duid como valor predeterminado. Esto envía un ID de cliente RFC 4361 creado a partir de un IAID y un DUID (identificador único DHCP). networkd.conf(5) documenta vendor como tipo de DUID predeterminado. En este tipo, el valor del DUID se genera usando 43793 como identificador del proveedor (systemd) y el contenido resumido del ID de máquina. DHCPv6 usa el mismo DUID. Dos clones con el mismo ID de máquina generan el mismo resumen y, si además conservan el mismo nombre de interfaz, envían un identificador de cliente idéntico byte a byte. El servidor DHCP los ve entonces como un solo cliente y ofrece la misma concesión a ambos equipos. El síntoma es una dirección que cambia de un servidor al otro, o que uno de los servidores pierde su dirección cada vez que el otro renueva la concesión.

journald. Los archivos del journal se encuentran en /var/log/journal/<machine-id>/. El directorio recibe literalmente el nombre del ID. Si envía los journals de dos clones a un mismo colector, ambos terminan en un solo directorio y se leen como si procedieran de un único host.

D-Bus. /var/lib/dbus/machine-id es el lugar donde se originó este formato de archivo. En Debian y Ubuntu es un enlace simbólico a /etc/machine-id. En algunos sistemas es un archivo real independiente que contiene su propia copia. Esa copia es el problema del procedimiento siguiente.

Agentes por host. Los agentes de monitorización, las comprobaciones de licencias, las herramientas de inventario y los clientes de copia de seguridad suelen usar el ID de máquina como identificador de host predeterminado, porque es estable y no requiere configuración. Si dos servidores notifican una sola identidad, se obtiene una única serie de métricas combinada o una sola licencia que cubre dos máquinas. Compruebe cómo deriva el agente su ID de host en lugar de suponer que usa el nombre de host.

Cómo saber si tiene un duplicado

Ejecute esto en ambos servidores y compare la salida.

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

Los mismos ID de máquina en dos servidores activos indican que uno se clonó a partir del otro. hostnamectl muestra el mismo valor en su línea Machine ID: si prefiere usar un solo comando.

El resultado de ls -l determina el siguiente paso. Un enlace simbólico tiene este aspecto:

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

Una línea que comienza por -rw-r--r-- indica que es un archivo real que contiene su propia copia del ID antiguo. Debe eliminarlo, porque systemd-machine-id-setup lo lee antes de hacer cualquier otra cosa.

El UUID del producto también es importante. systemd-machine-id-setup(1) usa el UUID de KVM antes de recurrir a la generación aleatoria. Por tanto, si su proveedor asignó a ambos clones el mismo UUID de SMBIOS (BIOS de gestión del sistema), al regenerarlo obtendrá dos veces el mismo ID de máquina. Si los UUID del producto son distintos en ambos servidores, no debe preocuparse por este aspecto.

Regenerar el ID de máquina en un VPS clonado

El orden es importante. systemd-machine-id-setup(1) indica que, si ya hay un ID de máquina D-Bus válido configurado para el sistema, ese ID de máquina D-Bus se copia y se usa para inicializar /etc/machine-id. Si deja un /var/lib/dbus/machine-id real en su lugar, regenerará exactamente el valor que intentaba eliminar.

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

Primero hay que truncar el archivo, porque la herramienta sólo actúa cuando el archivo no existe o está vacío. No hace nada si el archivo ya contiene un ID válido. systemd-machine-id-setup informa de lo que hizo en la salida de error estándar. En un VPS KVM normalmente verá:

Initializing machine ID from KVM UUID.

Initializing machine ID from random generator. es el mensaje que aparece cuando no hay ningún UUID del hipervisor disponible. Cualquiera de los dos resultados es correcto, siempre que cat /etc/machine-id muestre ahora un valor diferente del del otro servidor.

El enlace simbólico mantiene D-Bus y systemd en un único valor. Si prefiere un archivo real independiente, ejecute sudo dbus-uuidgen --ensure: crea el archivo con un UUID nuevo cuando el archivo no existe. Si dbus no está instalado, no existe ningún directorio /var/lib/dbus, ln falla con No such file or directory y puede omitir ambas líneas.

Después, reinicie el sistema.

sudo reboot

Por qué el reinicio no es opcional

Todos los procesos que ya leyeron el valor anterior siguen utilizándolo. sd_id128_get_machine() almacena el ID en la caché del proceso que realiza la llamada, por lo que un daemon en ejecución nunca detecta que el archivo ha cambiado. journald ya tiene /var/log/journal/<old-id>/system.journal abierto y sigue añadiendo contenido. systemd-networkd calculó su DUID al iniciarse y sigue enviando el identificador de cliente antiguo en cada renovación. Este suele ser exactamente el fallo que se pretendía corregir. D-Bus también leyó su ID durante el arranque. Puede reiniciar los servicios uno por uno, pero alguno quedará pendiente. Además, PID 1 también conserva el valor anterior.

Después del reinicio, compruebe las dos partes:

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

/var/log/journal/ ahora contiene un segundo directorio con el nuevo ID como nombre, y las entradas nuevas se escriben allí. journalctl sin opciones sólo lee el directorio de la máquina actual, por lo que el historial anterior al clonado desaparece de la vista predeterminada. Sigue estando en el disco: journalctl --merge lee todos los directorios del journal, incluido el antiguo. Elimine el directorio antiguo cuando esté seguro de que ya no necesita esos registros.

Por eso tampoco puede ensayar el procedimiento en un contenedor. Un contenedor comparte el kernel del host y nunca arranca su propio PID 1. El reinicio es la parte esencial del procedimiento. Pruébelo como se ejecutará en producción: clone una VM, ejecute los comandos, reinicie y compare el ID con el de la máquina de origen.

Trunque antes de crear la instantánea, no después de clonar

Corregir los clones uno por uno funciona. Corregir la imagen es mejor, porque cada servidor restaurado desde una instantánea defectuosa hereda el mismo valor. Haga esto como último paso antes de apagar la plantilla.

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

Vacíe el archivo. No lo elimine. machine-id(5) recomienda un archivo vacío para las imágenes que se utilizan en varias máquinas, porque mantener un archivo vacío en su lugar permite montar temporalmente otro archivo mediante bind mount sobre el archivo real cuando la imagen se utiliza en modo de solo lectura. En un /etc de solo lectura, el ID generado durante el arranque se almacena en ese archivo temporal y systemd-machine-id-setup --commit lo escribe cuando el sistema de archivos vuelve a admitir escritura.

Debe prever un efecto secundario: una máquina sin un ID de máquina establecido considera que el siguiente arranque es el primer arranque. Por eso, las unidades que contienen ConditionFirstBoot=yes se ejecutan durante ese arranque y se omiten en todos los siguientes. Compruebe qué ejecutaría su imagen con grep -rl ConditionFirstBoot /usr/lib/systemd/system/ antes de crear la plantilla.

Una plantilla y una instantánea son objetos distintos, y esa diferencia determina si se copia la identidad. Una plantilla es un artefacto de compilación que prepara deliberadamente, mientras que una instantánea es una copia de un servidor en ejecución tomada en un momento concreto y conserva la identidad de ese servidor junto con sus datos.

Por qué las imágenes de nube lo resuelven y su snapshot no

Las imágenes de nube de las distribuciones se crean para clonarse. Por eso se distribuyen con el machine ID sin inicializar y el primer arranque lo genera. cloud-init incluye un paso documentado específicamente para este caso. cloud-init clean --machine-id establece /etc/machine-id en la cadena literal uninitialized en sistemas systemd. La referencia de la CLI de cloud-init lo describe como una práctica recomendada al clonar una imagen maestra. Así, el siguiente arranque de esa imagen genera un machine ID único.

Un snapshot creado por usted es diferente. El archivo ya tenía un valor cuando creó el snapshot. Por eso, cada servidor restaurado a partir de él conserva ese mismo valor. Nada del proceso de restauración lo elimina. Es el mismo tipo de problema que mover un servidor en ejecución a un VPS nuevo, donde la copia es fiel y la identidad es el elemento que no quería copiar.

Qué más duplica un clon

  • Claves de host de SSH. También se copia /etc/ssh/ssh_host_*, por lo que ambos servidores presentan la misma huella digital a los clientes. Elimine esos archivos y ejecute sudo ssh-keygen -A o sudo dpkg-reconfigure openssh-server en Debian y Ubuntu. Después, los clientes advertirán de que la clave de host ha cambiado. Ese es el comportamiento correcto.
  • El nombre de host. Establézcalo con sudo hostnamectl set-hostname app02 y compruebe que /etc/hosts siga resolviendo el nombre nuevo.
  • Configuración de red estática. Un clon de un equipo con una dirección estática entra en conflicto con el original en cuanto se inicia. Consulte /etc/netplan/ antes de que el clon se conecte a la red.
  • El reloj. Una instantánea restaurada continúa con la hora que tenía cuando se creó la instantánea. Un salto grande del reloj en un VPS restaurado interrumpe la validación de certificados TLS y altera el orden de los registros hasta que la sincronización de hora se pone al día.

Aplique también al clon la lista de comprobación de los primeros diez minutos para un VPS nuevo. Un equipo clonado hereda las cuentas de usuario, las claves SSH, las reglas del firewall y las tareas programadas del equipo de origen. Nada de eso se revisó para la función que el clon va a desempeñar.

FAQ

¿Tengo que reiniciar después de cambiar /etc/machine-id?

Sí. Los procesos leen el ID de máquina una vez y lo almacenan en caché, por lo que el nuevo valor no llega a ningún proceso que ya esté en ejecución. journald sigue escribiendo en el directorio del journal cuyo nombre corresponde al ID antiguo, y el cliente DHCP sigue enviando un identificador de cliente derivado del valor antiguo. Esta suele ser la razón por la que se cambia el ID. Reiniciar servicios individuales corrige algunos casos, pero PID 1 también conserva el valor antiguo. Reinicie el sistema y confirme el valor con cat /etc/machine-id. Compárelo con el del otro servidor.

¿/etc/machine-id es lo mismo que el UUID del hardware?

No. El UUID de producto DMI que se muestra en /sys/class/dmi/id/product_uuid procede del hipervisor y sólo root puede leerlo. El ID de máquina lo genera el sistema operativo y se almacena en un archivo de texto que cualquier usuario puede leer. La relación funciona en una sola dirección: en un guest de KVM, systemd-machine-id-setup usa el UUID del hipervisor para generar un nuevo ID de máquina cuando no existe un ID de D-Bus que copiar. Si dos clones comparten el mismo UUID de producto, generarán de nuevo el mismo ID de máquina. Por tanto, compare también ese archivo antes de dar el resultado por válido.

¿Debo eliminar /etc/machine-id o dejarlo vacío?

Déjelo vacío cuando prepare una imagen. machine-id(5) prefiere un archivo vacío, porque systemd puede montar un archivo temporal sobre él cuando la imagen se ejecuta con un /etc de sólo lectura. Eliminar el archivo funciona en un sistema con permisos de escritura, y algunos scripts de clonación lo hacen así, pero el archivo vacío es la opción predeterminada más segura. cloud-init escribe la palabra uninitialized en el archivo con el mismo propósito.

¿Por qué mis dos servidores clonados recibieron la misma dirección DHCP?

Porque ambos enviaron el mismo identificador de cliente. systemd-networkd usa ClientIdentifier=duid de forma predeterminada para DHCPv4, y el DUID predeterminado se genera a partir de un hash de /etc/machine-id. Por tanto, los mismos IDs de máquina producen identificadores idénticos en clones que también conservaron el mismo nombre de interfaz. El servidor DHCP identifica las solicitudes mediante ese identificador, trata ambas como procedentes de un solo cliente y asigna una única concesión. Asigne a cada servidor su propio ID de máquina y reinicie ambos. Si el servidor sigue ofreciendo la dirección antigua, elimine la concesión obsoleta directamente en el servidor DHCP.

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