Snapshots, copias de seguridad y clones de VPS
Una snapshot permanece en la infraestructura del proveedor y no sustituye a una copia de seguridad. Compare qué restaura cada opción y qué corregir en un clon.
Qué son realmente una snapshot, una copia de seguridad y un clon
Una snapshot de un VPS es una imagen de disco de su servidor que el proveedor conserva en su propia infraestructura, dentro de su cuenta. Una copia de seguridad es una copia independiente de sus datos que puede restaurar en otro lugar sin la ayuda del proveedor que almacenaba el original. Un clon es una instancia nueva desplegada a partir de una snapshot. Por tanto, comienza siendo una copia exacta del original, incluida su identidad.
Resuelven problemas distintos. Una snapshot permite revertir una actualización fallida en minutos, pero no sirve si la cuenta se cierra. Una copia de seguridad sobrevive a la desaparición del proveedor. La restauración tarda más porque primero debe reconstruir la máquina. Un clon le proporciona un segundo servidor en ejecución con un solo paso. También crea dos máquinas que creen ser la misma máquina.
Por qué un snapshot de un VPS no es una copia de seguridad
El problema es el dominio de fallo, no la calidad de la imagen. Un snapshot se almacena en la plataforma de almacenamiento del proveedor, normalmente en la misma región que el servidor de origen y siempre dentro de la misma cuenta. Un solo incidente puede afectar al servidor y a su snapshot al mismo tiempo.
- Se suspende la cuenta, falla un pago o alguien roba las credenciales de acceso.
- Una persona o un script con acceso a la API elimina la instancia. En muchos proveedores, eliminar una instancia también elimina sus snapshots. Consulte el comportamiento documentado de su proveedor antes de dar por hecho lo contrario.
- La región sufre una interrupción y todo lo que contiene deja de estar disponible al mismo tiempo.
- Algo que se ejecuta como root en el servidor encuentra el token de la API del proveedor que dejó en
/rooty elimina los snapshots antes de modificar el disco.
Una copia de seguridad es la copia que sobrevive a los cuatro casos. La prueba consiste en una pregunta: si su cuenta del proveedor dejara de existir esta tarde, ¿qué podría restaurar todavía y dónde lo restauraría? Todo lo que no supere esta prueba es una herramienta de rollback. Siga creando snapshots, porque nada se restaura más rápido. Después, conserve una segunda copia en un almacenamiento que el proveedor no controle.
La regla antigua sigue vigente: tres copias de los datos, en dos tipos de almacenamiento, con una de ellas fuera de la plataforma. Un snapshot del proveedor y un repositorio de copias de seguridad de restic en una infraestructura separada cubren este requisito con dos componentes.
Por qué una instantánea de una base de datos en ejecución puede restaurarse dañada
La instantánea de un proveedor copia el dispositivo de bloques tal como está en un instante concreto. No solicita que las aplicaciones se detengan antes y no puede ver los datos que todavía están en la caché de páginas. Por tanto, como mucho, la imagen es coherente tras un fallo. Es exactamente el estado que tendría el disco si alguien desconectara el cable de alimentación.
La mayor parte de la pila gestiona esta situación. ext4 y XFS reproducen su journal al montar el sistema de archivos, por lo que este se inicia correctamente. PostgreSQL reproduce su write-ahead log al iniciar, como muestra este mensaje:
LOG: database system was not properly shut down; automatic recovery in progressInnoDB hace lo mismo y muestra sus propios mensajes de recuperación tras un fallo durante el inicio. Esta recuperación forma parte del funcionamiento previsto de la base de datos, por lo que una instantánea de un solo volumen de PostgreSQL o MySQL inactivo normalmente se restaura sin problemas.
Los casos en los que la coherencia tras un fallo no es suficiente son reales y son los que causan problemas graves. Si los datos abarcan dos volúmenes, el disco raíz y el disco de datos independiente se capturan en instantes distintos. Por tanto, los archivos de datos y el directorio de logs pueden no coincidir, y la recuperación no tendrá datos correctos que reproducir. Cualquier archivo que una aplicación escriba sin llamar a fsync, como una carga que se haya recibido parcialmente o un archivo de cola, puede restaurarse truncado. Todo lo que la aplicación mantenga en memoria y vacíe con un temporizador no estará en la imagen.
Por tanto, escriba un dump en el disco antes de crear la instantánea. Así, la imagen contendrá un archivo cuya coherencia interna podrá comprobar, independientemente del estado de los archivos de datos activos.
sudo -u postgres pg_dumpall --clean --file=/var/backups/pg-$(date +%F).sql
sudo mysqldump --single-transaction --routines --all-databases > /var/backups/mysql-$(date +%F).sql--single-transaction genera un dump coherente de las tablas de InnoDB sin bloquear a los procesos que escriben, porque el dump se ejecuta dentro de una transacción con aislamiento repeatable-read. No incluye las tablas MyISAM, que requieren un bloqueo o un servidor detenido. Compruebe que el dump no esté vacío ni truncado antes de confiar en él: tail -n 1 /var/backups/mysql-$(date +%F).sql en un mysqldump completo termina con un comentario Dump completed.
Si tiene un volumen de datos independiente, puede congelarlo durante los segundos que necesite la instantánea:
sudo fsfreeze -f /srv
# take the snapshot from your provider's panel or API
sudo fsfreeze -u /srvCongele únicamente el volumen de datos. No congele nunca /. Un sistema de archivos raíz congelado bloquea todas las escrituras del equipo, incluida la shell que usaría para escribir el comando de descongelación. Por tanto, perderá el acceso y tendrá que esperar a un reinicio forzado.
La mitad externa: restic o Borg
La instantánea es la mitad rápida. La copia externa es la mitad que sobrevive al proveedor. restic es una buena opción predeterminada porque elimina duplicados, cifra en el cliente y escribe en almacenamiento de objetos compatible con S3, SFTP o un directorio normal. Un VPS de almacenamiento como destino externo funciona bien en este caso, porque los repositorios de copias de seguridad necesitan capacidad, no IOPS.
sudo apt update && sudo apt install -y restic
sudo sh -c 'umask 077; head -c 24 /dev/urandom | base64 > /root/.restic-pass'
sudo chmod 600 /root/.restic-pass
sudo cat /root/.restic-passCopie esa frase de contraseña ahora en un gestor de contraseñas, en un dispositivo que no sea este servidor. Un repositorio de restic no se puede abrir sin ella y no existe una vía de recuperación. Si la única copia de la contraseña estaba en el equipo que acaba de perder, la copia de seguridad es información cifrada inutilizable.
export RESTIC_REPOSITORY="s3:https://s3.example.com/vps-backups"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
sudo -E restic init
sudo -E restic backup /etc /srv /var/backups
sudo -E restic snapshotssudo -E conserva esas variables, porque sin él root obtiene un entorno limpio y restic informa de que no se especificó ninguna ubicación del repositorio. restic snapshots debería mostrar la ejecución que acaba de hacer, con su host y sus rutas. Verifique el repositorio de forma periódica y lea parte de los datos, en lugar de comprobar sólo la estructura:
sudo -E restic check --read-data-subset=5%
sudo -E restic restore latest --target /tmp/restore-check
sudo -E restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --pruneUna copia de seguridad no probada es una suposición. Restaure en otro VPS al menos una vez, mida el tiempo y anótelo, porque ese número es su objetivo real de recuperación. Borg es la otra opción sólida y almacena el repositorio mediante SSH en lugar de usar almacenamiento de objetos; las diferencias se explican en la comparación entre restic y BorgBackup.
Qué corregir antes de poner un VPS clonado en producción
Un clon es una réplica exacta. Esa es su utilidad y también el problema. Todo lo que hacía único al original se duplica, y las duplicaciones entran en conflicto.
Regenerar las claves de host de SSH. El clon contiene los archivos /etc/ssh/ssh_host_* del original, por lo que ambos servidores presentan la misma identidad de host. Cualquiera que controle uno puede suplantar al otro ante todos los clientes que hayan aceptado esa clave. SSH no muestra ninguna advertencia porque la clave es la que el cliente esperaba.
sudo rm -f /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart ssh
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pubssh-keygen -A escribe una clave nueva de cada tipo que espera el daemon. La huella digital del último comando debe ser distinta de la del original. La sesión actual continúa activa porque reiniciar sshd no cierra las conexiones establecidas. Hágalo antes de que alguien se conecte al clon. Si lo deja para más adelante, todos los clientes que ya confiaban en la clave heredada reciben WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! y deben ejecutar ssh-keygen -R <host> primero.
Restablecer el ID de máquina. /etc/machine-id es un identificador único que systemd genera una sola vez, durante el primer arranque, y que el clon hereda.
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 rebootUn /etc/machine-id vacío indica a systemd que genere un valor nuevo en el siguiente arranque. Por eso se trunca el archivo en lugar de eliminarlo. La duplicación provoca dos problemas. En las imágenes que obtienen su dirección mediante DHCP, systemd-networkd deriva de forma predeterminada el identificador de cliente DHCP a partir del ID de máquina. Por tanto, ambos clones solicitan una concesión como si fueran el mismo cliente y el servidor les asigna la misma dirección. Además, journald marca cada entrada con el ID de máquina, por lo que un recopilador central de registros archiva ambos servidores como una sola máquina. Ejecute cat /etc/machine-id después del reinicio y confirme que el valor ha cambiado.
Cambiar el nombre de host.
sudo hostnamectl set-hostname web-02
grep 127.0.1.1 /etc/hostshostnamectl escribe /etc/hostname y aplica el nombre de inmediato. No modifica /etc/hosts, por lo que debe editar la línea 127.0.1.1 para que coincida. Si omite este paso, el nombre nuevo no resolverá en ninguna parte, y cada llamada a sudo esperará una resolución fallida y mostrará sudo: unable to resolve host web-02: Name or service not known.
Rotar todas las credenciales integradas en la imagen. El clon contiene los secretos del original, y ahora dos máquinas pueden actuar como el original. Revise los archivos authorized_keys de SSH, los tokens de las API del proveedor y de DNS, los archivos .env de las aplicaciones, las contraseñas de las bases de datos, las claves privadas TLS, los tokens de registro de los sistemas de monitorización y la contraseña del repositorio de restic, entre otros. Esto permite encontrar la mayoría:
sudo grep -rIlE 'PASSWORD|SECRET|TOKEN|API_KEY' /etc /srv /opt /home 2>/dev/null
sudo find / -name '.env' -not -path '/proc/*' -not -path '/sys/*' 2>/dev/nullSi el clon es una copia de prueba que nunca prestará servicio, revoque las credenciales en lugar de rotarlas. Un servidor de staging que contiene un token activo de la API de producción es un servidor de producción con peor mantenimiento.
Desactivar los trabajos que ahora se ejecutan dos veces. Dos servidores con el mismo crontab acceden a los mismos sistemas externos en el mismo minuto.
systemctl list-timers --all
sudo crontab -l
sudo ls -l /etc/cron.d /etc/cron.dailyEl caso de restic merece una explicación, porque puede corromper la retención en lugar de limitarse a fallar de forma evidente. restic etiqueta cada snapshot con el nombre de host, y restic forget --keep-daily 7 aplica su política por host. Dos máquinas que informan del mismo nombre de host se tratan como un solo host. Por tanto, los siete snapshots "daily" pueden proceder todos del clon, mientras se eliminan los snapshots del original. Corrija el nombre de host antes de la primera ejecución de la copia de seguridad o detenga el timer en el clon. El caso de certbot es más sencillo: dos servidores que renuevan los mismos nombres alcanzan el límite de tasa de certificados duplicados de la autoridad certificadora, y la ejecución que pierde falla con un error que indica que ya se han emitido demasiados certificados para ese conjunto exacto de nombres. Un clon cuyo dominio todavía apunta al original tampoco puede superar un desafío HTTP, así que desactive la renovación allí.
Gestionar el agente de monitorización. La mayoría de los agentes se identifican mediante el nombre de host o mediante un archivo de ID escrito durante la instalación. Por tanto, dos agentes que informan como un solo host mezclan sus métricas en una misma serie. Los gráficos de CPU muestran entonces valores que ninguna máquina produjo por sí sola y las alertas se activan y desactivan de forma intermitente. Detenga y elimine el agente del clon, o vuelva a registrarlo con el nuevo nombre de host siguiendo el procedimiento documentado por el proveedor.
Comprobar la configuración de red para detectar la dirección del original. Si la imagen contiene una dirección estática en netplan, el clon reclama una IP que pertenece a otra máquina.
ip -br addr
sudo grep -r addresses /etc/netplan/Borrar el estado de cloud-init si este clon se convierte en una plantilla.
sudo cloud-init clean --logsEsto elimina el estado de cloud-init en /var/lib/cloud, por lo que el siguiente arranque vuelve a ejecutar los módulos del primer arranque. Entre ellos se incluye la generación de claves de host de SSH cuando no existen. Algunas versiones también ofrecen un flag para restablecer el ID de máquina. Ejecute cloud-init clean --help en su propia imagen para comprobar qué opciones admite, en lugar de confiar en una lista de flags obtenida de otra fuente.
Cuándo usar cada opción
Para revertir una actualización de riesgo: cree un snapshot. Créelo unos minutos antes del cambio, ejecute la actualización y restaure la imagen si algo falla. La restauración descarta todas las escrituras realizadas desde el snapshot. Por tanto, en un servidor que recibe tráfico en producción, vuelque primero la base de datos y determine exactamente qué intervalo de datos perdería. Para un do-release-upgrade en un equipo que pueda dejar fuera de línea durante diez minutos, un snapshot es todo el plan.
Para migrar a un plan más grande: implemente un clon. Cree el clon a partir de un snapshot en el plan más grande, revise la lista de identidades anterior y pruébelo en su propia IP antes de mover tráfico. Reduzca el TTL de DNS un día antes para que el cambio sea rápido y mantenga el equipo original en ejecución hasta que el nuevo haya recibido tráfico real. Confirme primero que el plan más grande es realmente más rápido para su carga de trabajo mediante el mismo método de benchmark en ambos servidores, porque tener más vCPU en hardware más ocupado no siempre supone una mejora.
Para crear una plantilla: cree un snapshot de una máquina limpia. Instale y refuerce un servidor. Después, elimine todo lo que sea específico antes de crear la imagen. No incluya host keys, deje vacío el machine ID, elimine cualquier authorized_keys personal y las credenciales, y limpie cloud-init. Cree el snapshot. Cada instancia implementada a partir de él genera su propia identidad durante el primer arranque, por lo que la lista de comprobación anterior deja de ser necesaria. Combínelo con los primeros diez minutos estándar en un VPS nuevo para que la plantilla ya contenga el trabajo que, de otro modo, tendría que repetir.
FAQ
¿Una instantánea de un VPS es una copia de seguridad?
No, porque comparte el dominio de fallo con el servidor del que procede. La instantánea se almacena en la infraestructura de su proveedor, dentro de su cuenta y, normalmente, en la misma región. Una suspensión de la cuenta, una clave de API robada o la eliminación accidental de una instancia pueden eliminar el servidor y sus instantáneas con una sola acción. En muchos proveedores, eliminar una instancia también elimina sus instantáneas por diseño. Una instantánea es la forma más rápida de revertir cambios, así que siga creándolas y conserve una segunda copia cifrada en una infraestructura que no controle su proveedor.
¿Tengo que detener la base de datos antes de crear una instantánea?
No siempre, pero debe aceptar el resultado obtenido. Una instantánea del proveedor es coherente frente a fallos, lo que significa que la imagen coincide con el estado que tendría el disco después de un corte de alimentación. PostgreSQL e InnoDB se recuperan de esa situación al iniciar, y PostgreSQL registra database system was not properly shut down; automatic recovery in progress durante el proceso. La recuperación no está garantizada cuando los datos abarcan dos volúmenes capturados en instantes diferentes o cuando una aplicación escribe sin fsync. Escriba primero un pg_dumpall o un mysqldump --single-transaction en el disco para que la imagen contenga un archivo cuya coherencia esté confirmada.
¿Por qué dos servidores clonados entran en conflicto por la misma dirección IP?
Porque comparten /etc/machine-id. En las imágenes que usan DHCP, systemd-networkd crea de forma predeterminada el identificador de cliente DHCP a partir del ID de máquina. Por eso, ambos clones solicitan una concesión como el mismo cliente y el servidor DHCP ofrece la misma dirección a los dos. Trunque /etc/machine-id a cero bytes, elimine /var/lib/dbus/machine-id, vuelva a crear el enlace simbólico hacia /etc/machine-id y reinicie para que systemd genere un valor nuevo. La otra causa habitual es una dirección estática escrita en /etc/netplan/ que el clon copió sin cambios. Compruébelo con ip -br addr.
¿Cuál es la forma más rápida de comprobar que un clon es seguro para ponerlo en producción?
Compare cuatro elementos con el original. Ejecute ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub en ambos y confirme que las huellas digitales sean diferentes. Ejecute cat /etc/machine-id en ambos y confirme que los valores sean diferentes. Ejecute hostnamectl status y confirme que el nombre sea nuevo y se resuelva correctamente, para que sudo no muestre ninguna advertencia. Después, ejecute systemctl list-timers --all y detenga todos los temporizadores que se comuniquen con un sistema compartido, como las copias de seguridad, la renovación de certificados o un agente de monitorización, hasta decidir qué máquina se encargará de esa tarea.