Snapshot, backup o clone VPS: quale scegliere?
Snapshot, backup e clone VPS non sono equivalenti: scopri cosa ripristinano, dove risiedono e quali problemi correggere su un clone prima dell'avvio.
Che cosa sono realmente uno snapshot, un backup e un clone
Uno snapshot di un VPS è un'immagine del disco del server, conservata dal provider sulla propria infrastruttura, all'interno del tuo account. Un backup è una copia indipendente dei dati che puoi ripristinare altrove, senza l'intervento del provider che conservava l'originale. Un clone è una nuova istanza distribuita a partire da uno snapshot. Viene quindi avviata come copia esatta dell'originale, inclusa l'identità del sistema.
Risolvono problemi diversi. Uno snapshot consente di annullare un aggiornamento non riuscito in pochi minuti, ma non è disponibile se l'account viene chiuso. Un backup resta disponibile anche se il provider cessa l'attività e richiede più tempo per il ripristino, perché prima devi ricreare la macchina. Un clone ti fornisce un secondo server operativo in un solo passaggio, ma crea anche due macchine convinte di essere la stessa macchina.
Perché lo snapshot di un VPS non è un backup
Il problema è il dominio di errore, non la qualità dell'immagine. Uno snapshot risiede sulla piattaforma di storage del provider, in genere nella stessa regione del server da cui proviene, e sempre nello stesso account. Un singolo evento può rendere indisponibili insieme il server e il relativo snapshot.
- L'account viene sospeso, un pagamento non va a buon fine oppure qualcuno ruba le credenziali di accesso.
- Una persona o uno script con accesso all'API elimina l'istanza. Per molti provider, l'eliminazione di un'istanza elimina anche i relativi snapshot. Verifica il comportamento documentato dal provider prima di dare per scontato il contrario.
- La regione ha un problema e tutte le risorse al suo interno diventano contemporaneamente irraggiungibili.
- Un processo in esecuzione come root sul server trova il token API del provider che hai lasciato in
/roote rimuove gli snapshot prima di intervenire sul disco.
Un backup è la copia che sopravvive a tutti e quattro gli scenari. La verifica consiste in una sola domanda: se questo pomeriggio il tuo account presso il provider smettesse di esistere, che cosa potresti ancora ripristinare e dove lo ripristineresti? Tutto ciò che non supera questa verifica è uno strumento di rollback. Continua a creare snapshot, perché nulla consente un ripristino più rapido. Conserva poi una seconda copia su uno storage che non sia sotto il controllo del provider.
La regola tradizionale è ancora valida: tre copie dei dati, su due tipi di storage, di cui una esterna alla piattaforma. Uno snapshot del provider più un repository di backup restic su un'infrastruttura separata soddisfano questo requisito con due soli componenti operativi.
Perché uno snapshot di un database in esecuzione può essere ripristinato in modo non integro
Lo snapshot del provider copia il dispositivo a blocchi nello stato in cui si trova in un determinato istante. Non chiede alle applicazioni di arrestarsi prima e non può vedere i dati che si trovano ancora nella page cache. L'immagine è quindi, al massimo, coerente dopo un arresto anomalo. Corrisponde esattamente allo stato del disco dopo la rimozione dell'alimentazione.
La maggior parte dello stack gestisce questa situazione. ext4 e XFS riproducono il journal durante il mount, quindi il filesystem torna disponibile. PostgreSQL riproduce il write-ahead log all'avvio, come mostra il log:
LOG: database system was not properly shut down; automatic recovery in progressInnoDB esegue la stessa operazione e stampa le proprie righe di crash recovery durante l'avvio. Questo ripristino è il comportamento previsto del database, quindi uno snapshot di un singolo volume PostgreSQL o MySQL non sottoposto a operazioni intensive viene generalmente ripristinato correttamente.
Esistono casi in cui la coerenza dopo un arresto anomalo non è sufficiente, e sono quelli che causano i problemi più gravi. Se i dati si estendono su due volumi, il disco root e il disco separato dei dati vengono sottoposti a snapshot in istanti diversi. I file dei dati e la directory dei log possono quindi non essere coerenti tra loro e il ripristino non ha dati corretti da riprodurre. Qualsiasi file scritto da un'applicazione senza chiamare fsync, ad esempio un upload ricevuto solo parzialmente o un file di coda, può essere ripristinato troncato. I dati che l'applicazione mantiene in memoria e scarica su disco a intervalli regolari non vengono inclusi nell'immagine.
Prima di creare lo snapshot, scrivi quindi un dump su disco. In questo modo l'immagine contiene almeno un file di cui sai che è internamente coerente, indipendentemente dallo stato dei file dei dati attivi.
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 crea un dump coerente delle tabelle InnoDB senza bloccare le operazioni di scrittura, perché il dump viene eseguito all'interno di una singola transazione repeatable-read. Non include le tabelle MyISAM, che richiedono un lock o l'arresto del server. Prima di considerare affidabile il dump, verifica che non sia vuoto e che non sia troncato: tail -n 1 /var/backups/mysql-$(date +%F).sql in un mysqldump completo termina con un commento Dump completed.
Se disponi di un volume separato per i dati, puoi congelarlo per i secondi necessari allo snapshot:
sudo fsfreeze -f /srv
# take the snapshot from your provider's panel or API
sudo fsfreeze -u /srvCongela soltanto il volume dei dati. Non congelare mai /. Un filesystem root congelato blocca ogni operazione di scrittura sul sistema, inclusa la shell che useresti per digitare il comando di scongelamento. In questo modo perdi l'accesso al sistema e devi attendere un hard reset.
La parte fuori sede: restic o Borg
Lo snapshot è la parte rapida. La copia fuori sede è quella che sopravvive al provider. restic è una buona scelta predefinita perché elimina i duplicati, cifra i dati sul client e scrive su object storage compatibile con S3, SFTP o una directory semplice. Un VPS di storage come destinazione fuori sede è adatto in questo caso, perché i repository di backup richiedono capacità più che 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-passCopia subito questa passphrase in un password manager, su un dispositivo diverso da questo server. Non è possibile aprire un repository restic senza di essa e non esiste una procedura di recupero. Se l'unica copia della password era sul server che hai appena perso, il backup è solo dati cifrati inutilizzabili.
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 queste variabili, perché senza di esso root riceve un ambiente pulito e restic segnala che non è stata specificata alcuna posizione del repository. restic snapshots dovrebbe elencare l'esecuzione appena effettuata, con host e percorsi. Verifica periodicamente il repository stesso e recupera alcuni dati, invece di controllarne soltanto la struttura:
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 --pruneUn backup non testato è soltanto un'ipotesi. Esegui almeno una volta un ripristino su un VPS diverso, misura la durata e annotala, perché quel valore è il tuo reale obiettivo di ripristino. Borg è l'altra scelta affidabile e archivia il repository tramite SSH invece che su object storage; i compromessi sono descritti nel confronto tra restic e BorgBackup.
Cosa correggere prima di portare un VPS clonato in produzione
Un clone è una replica esatta. Questo è il suo vantaggio e anche il problema. Tutto ciò che rendeva unico il sistema originale viene duplicato, e i duplicati entrano in conflitto.
Rigenerare le chiavi host SSH. Il clone contiene i file /etc/ssh/ssh_host_* originali, quindi due server presentano la stessa identità host. Chiunque controlli uno dei due può impersonare l'altro verso ogni client che ha accettato quella chiave. SSH non mostra alcun avviso, perché la chiave corrisponde a quella attesa dal client.
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 scrive una nuova chiave per ogni tipo previsto dal demone. L'impronta digitale restituita dall'ultimo comando deve essere diversa da quella del server originale. La sessione corrente resta attiva dopo il riavvio, perché il riavvio di sshd non chiude le connessioni già stabilite. Esegui questa procedura prima che qualcuno si connetta al clone. Se la rimandi, ogni client che ha già considerato attendibile la chiave ereditata riceve WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! e deve eseguire prima ssh-keygen -R <host>.
Reimpostare il machine ID. /etc/machine-id è un identificatore univoco che systemd genera una sola volta, al primo avvio, e che il clone eredita.
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 file /etc/machine-id vuoto indica a systemd di generare un nuovo valore al successivo avvio. Per questo il file viene troncato invece di essere eliminato. La duplicazione causa due problemi. Nelle immagini che ricevono l'indirizzo tramite DHCP, systemd-networkd ricava per impostazione predefinita l'identificatore del client DHCP dal machine ID. Di conseguenza, entrambi i cloni richiedono un lease come se fossero lo stesso client e il server assegna loro lo stesso indirizzo. Inoltre, journald associa ogni voce al machine ID, quindi un collettore centralizzato archivia entrambi i server come un'unica macchina. Dopo il riavvio, esegui cat /etc/machine-id e verifica che il valore sia cambiato.
Cambiare il nome host.
sudo hostnamectl set-hostname web-02
grep 127.0.1.1 /etc/hostshostnamectl scrive /etc/hostname e applica immediatamente il nuovo nome. Non modifica /etc/hosts, quindi devi modificare la riga 127.0.1.1 in modo che corrisponda. Se salti questo passaggio, il nuovo nome non viene risolto e ogni chiamata a sudo attende una ricerca DNS non riuscita e stampa sudo: unable to resolve host web-02: Name or service not known.
Ruotare tutte le credenziali incorporate nell'immagine. Il clone contiene i secret originali, quindi ora due macchine possono agire come il sistema originale. Controlla i file authorized_keys di SSH, i token API del provider e del DNS, i file .env delle applicazioni, le password dei database, le chiavi private TLS, i token di registrazione del sistema di monitoraggio, la password del repository restic e tutto il resto. Questo comando individua la maggior parte delle credenziali:
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/nullSe il clone è una copia di test che non gestirà mai traffico, revoca le credenziali invece di ruotarle. Un server di staging che contiene un token API di produzione ancora attivo è un server di produzione con una gestione delle patch peggiore.
Disattivare i job che ora vengono eseguiti due volte. Due server con lo stesso crontab contattano gli stessi sistemi esterni nello stesso minuto.
systemctl list-timers --all
sudo crontab -l
sudo ls -l /etc/cron.d /etc/cron.dailyIl caso di restic merita un chiarimento, perché può corrompere la retention invece di limitarsi a fallire in modo evidente. restic applica a ogni snapshot il nome host e restic forget --keep-daily 7 applica la relativa policy per host. Due macchine che riportano lo stesso nome host vengono trattate come un unico host. Di conseguenza, sette snapshot "giornalieri" possono provenire tutti dal clone, mentre gli snapshot del server originale vengono eliminati. Correggi il nome host prima della prima esecuzione del backup oppure arresta il timer sul clone. Il caso di certbot è più semplice: due server che rinnovano gli stessi nomi raggiungono il rate limit dell'autorità di certificazione per i certificati duplicati e l'esecuzione che perde termina con un errore relativo a un numero eccessivo di certificati già emessi per quell'esatto insieme di nomi. Un clone il cui dominio punta ancora al server originale non può comunque superare una verifica HTTP, quindi disabilita il rinnovo.
Gestire l'agent di monitoraggio. La maggior parte degli agent identifica il server tramite il nome host o un file ID scritto durante l'installazione. Di conseguenza, due agent che riportano lo stesso host inseriscono le metriche nella stessa serie. I grafici della CPU mostrano quindi valori che nessuna singola macchina ha prodotto e gli alert diventano instabili. Arresta e rimuovi l'agent dal clone oppure registralo nuovamente con il nuovo nome host seguendo la procedura documentata dal fornitore.
Controllare la configurazione di rete per verificare la presenza dell'indirizzo originale. Se l'immagine contiene un indirizzo statico in netplan, il clone rivendica un IP appartenente a un'altra macchina.
ip -br addr
sudo grep -r addresses /etc/netplan/Cancellare lo stato di cloud-init se questo clone diventerà un template.
sudo cloud-init clean --logsQuesta operazione rimuove lo stato di cloud-init da /var/lib/cloud, quindi al successivo avvio vengono eseguiti nuovamente i moduli del primo avvio, inclusa la generazione delle chiavi host SSH quando non sono presenti. Alcune versioni offrono anche un flag per reimpostare il machine ID. Esegui cloud-init clean --help sulla tua immagine per verificare le opzioni supportate, invece di affidarti a un elenco di flag trovato altrove.
Quando utilizzare ciascuna opzione
Ripristino dopo un aggiornamento rischioso: create uno snapshot. Create lo snapshot pochi minuti prima della modifica, eseguite l’aggiornamento e ripristinate l’immagine se qualcosa va storto. Il ripristino elimina tutte le scritture effettuate dopo lo snapshot. Su un server che gestisce traffico reale, eseguite prima il dump del database e stabilite con precisione quale intervallo di dati potreste perdere. Per un do-release-upgrade su un sistema che potete mettere offline per dieci minuti, lo snapshot è l’intero piano operativo.
Migrazione a un piano più grande: distribuite un clone. Create il clone da uno snapshot sul piano più grande, verificate tutti gli elementi dell’elenco relativo all’identità, quindi collaudatelo sul relativo indirizzo IP prima di spostare il traffico. Riducete il TTL DNS con un giorno di anticipo, in modo che il passaggio sia rapido, e mantenete operativo il server originale finché il nuovo sistema non avrà gestito traffico reale. Verificate prima che il piano più grande sia effettivamente più veloce per il vostro carico di lavoro, usando lo stesso metodo di benchmark su entrambi i server, perché un numero maggiore di vCPU su hardware più carico non costituisce sempre un miglioramento.
Creazione di un template: create lo snapshot di una macchina ripulita. Installate e mettete in sicurezza un server, quindi rimuovete ogni elemento specifico del sistema prima di creare l’immagine. Nessuna host key, un machine ID vuoto, nessun authorized_keys personale, nessuna credenziale e cloud-init ripulito. Create lo snapshot. Ogni istanza distribuita da questo snapshot genera la propria identità al primo avvio, quindi l’elenco precedente non è più necessario come procedura manuale. Associatelo a i primi dieci minuti standard su un nuovo VPS, così il template contiene già le attività che altrimenti dovreste ripetere.
FAQ
Un'istantanea di un VPS è un backup?
No, perché condivide il dominio di errore con il server da cui proviene. L'istantanea risiede nello storage del provider, nel tuo account, di solito nella stessa regione. La sospensione dell'account, il furto di una chiave API o l'eliminazione accidentale dell'istanza possono rimuovere il server e le relative istantanee con una sola operazione; inoltre, presso molti provider, l'eliminazione di un'istanza elimina per progettazione anche le sue istantanee. Un'istantanea è il rollback più rapido disponibile, quindi continua a crearle e conserva una seconda copia crittografata su un'infrastruttura non controllata dal provider.
Devo arrestare il database prima di creare un'istantanea?
Non sempre, ma devi accettare il risultato ottenuto. Un'istantanea del provider è coerente dopo un arresto anomalo: l'immagine corrisponde allo stato che il disco avrebbe dopo un'interruzione dell'alimentazione. PostgreSQL e InnoDB eseguono il ripristino all'avvio e PostgreSQL registra database system was not properly shut down; automatic recovery in progress durante l'operazione. Il ripristino non è garantito quando i dati si estendono su due volumi acquisiti in istanti diversi oppure quando un'applicazione scrive senza fsync. Scrivi prima su disco un pg_dumpall o un mysqldump --single-transaction, in modo che l'immagine contenga un file di cui conosci la coerenza.
Perché due server clonati entrano in conflitto per lo stesso indirizzo IP?
Perché condividono /etc/machine-id. Nelle immagini che usano DHCP, systemd-networkd costruisce per impostazione predefinita l'identificatore del client DHCP a partire dall'ID della macchina. Di conseguenza, entrambi i cloni richiedono una concessione come se fossero lo stesso client e il server DHCP offre a entrambi lo stesso indirizzo. Tronca /etc/machine-id a zero byte, rimuovi /var/lib/dbus/machine-id, ricrealo come link simbolico verso /etc/machine-id e riavvia, così systemd genera un nuovo valore. L'altra causa comune è un indirizzo statico scritto in /etc/netplan/, che il clone ha copiato senza modifiche; verifica con ip -br addr.
Qual è il modo più rapido per verificare che un clone sia sicuro da mettere in produzione?
Confronta quattro elementi con l'originale. Esegui ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub su entrambi e verifica che le impronte digitali siano diverse. Esegui cat /etc/machine-id su entrambi e verifica che i valori siano diversi. Esegui hostnamectl status e verifica che il nome sia nuovo e venga risolto, in modo che sudo non produca avvisi. Poi esegui systemctl list-timers --all e arresta ogni timer che comunica con un sistema condiviso, ad esempio per i backup, il rinnovo dei certificati o un agente di monitoraggio, finché non avrai deciso quale macchina deve gestire quell'attività.