Alla Ricerca del Backup Perfetto: Borg e Restic

/images/backup.thumbnail.png

Backup: tecniche principali

In passato ho già affrontato l'argomento backup ponendo alcune basi e dando alcune indicazioni sulle principali modalità e sul perché è fondamentale farlo, sul perché il RAID non può essere considerato una forma di backup e su alcuni software da me presi in esame e utilizzati in precedenza. Invito dunque a leggere l'articolo collegato, per una base di partenza. Questa volta, però, daro delle guide su come io realizzo i backup e su come io riesca a garantire un certo grado di sicurezza.

Backup: le basi di partenza

Proporrò l'argomento sotto forma di elenco puntato, onde coprire le principali problematiche da gestire:

  • Sistema Operativo e dati da salvare: ogni sistema operativo è un universo. E' ragionevole pensare che non esista una soluzione universale, anche se molti dei principali software open source sono multi-piattaforma. Il principale divario è tra i sistemi Unix-Like (GNU/Linux, BSD, MacOS, ecc.) e Windows. Lo stesso software, pur essendo disponibile per più piattaforme, potrebbe non essere il migliore per la propria o per le proprie necessità.
  • Tipo di dati da salvare: ogni tipo di backup richiede soluzioni diverse. Ci sono situazioni in cui si ha la necessità di copie pressoché sempre incrementali in quanto i file crescono ma non vengono modificati. In questo caso, un qualunque sistema appunto incrementale (es: Duplicity ) può essere sufficiente. Nel caso, invece, di backup sempre diversi (es: un database che cambia costantemente), un sistema come quello precedente può essere estremamente inefficiente, specialmente nel lungo periodo.
  • Necessità di crittografia o meno: i backup delle mie fatture, ad esempio, potrei anche evitare di crittarli...
  • Rapidità di esecuzione e di recupero: ci sono strumenti che sono estremamente efficienti nell'effettuare l'operazione di copia, ma che rendono estremamente lento il recupero. Una delle (poche) carenze da me riscontrate in BURP Backup, di cui ho parlato nell'articolo precedente e che utilizzo ancora con successo in certe situazioni, è che richiede il restore dei file e non consente, per lo meno direttamente, di navigare nel backup come fosse un file system locale. Stesso discorso vale, ad esempio, per il backup nativo di Proxmox: è comodissimo da impostare, completo e nativo ma il tempo di recupero può essere importante, specialmente se effettuato in postazioni remote e su connessioni lente. Recuperare un file richiederà, molto spesso, il recupero totale della macchina.
  • Snapshot: ultima in lista, ma questione di primaria importanza. Un backup di un file system "live" avrà un momento di inizio e un momento di fine. Nel frattempo, i dati cambieranno all'interno di esso e potrebbe generarsi incoerenza. In passato ho avuto problemi del genere: un database (mysql) di qualche GB è stato rovinato da un cliente e me ne è stato chiesto il recupero. Ho preso, con baldanza, l'ultimo backup e ho ripristinato i vari file (non un dump). Inutile dire che è stato impossibile farlo ripartire: il file molto grande era cambiato troppo tra l'inizio del backup dello stesso e la fine, per cui era incoerente. Per i maliziosi: avevo anche il dump, ovviamente, per cui ho recuperato quello. Ma la questione resta chiara: fare un backup di un file system live è periocoloso, a meno che non si stia copiando la cartella "Documenti" o "Immagini". Un database aperto, come anche semplicemente quello del browser, ha altissime probabilità di corrompersi e rendere inutile la copia di sicurezza fatta. La tecnica è fare uno snapshot dell'intero file system prima di iniziare la copia. Ci sono margini di rischio anche in questo (il backup avrà all'incirca lo stesso stato che avrebbe la macchina se venisse improvvisamente staccata la spina), ma largamente inferiori. Ad oggi, utilizzando snapshot, sono stato in grado di recuperare tutto.

Backup: Snapshot

Effettuare uno snapshot del file system è importante al fine di avere un backup sufficientemente coerente. Nel tempo ho provato varie soluzioni: Windows ha il suo VSS, su Linux ci sono varie opzioni diverse. Ne elencherò le principali:

  • Snapshot nativo del File System (es: BTRFS o ZFS): se il file system supporta nativamente la possibilità di fare uno snapshot, è opportuno sfruttare questo sistema. Sarà senza dubbio il meno dispendioso e il più corretto, a livello formale.
  • LVM snapshot: se si utilizza LVM, si può chiedere uno snapshot del volume logico, montarlo ed effettuare il backup dello stesso. Bisognerà specificare una dimensione massima di variazione (ovvero quanti dati al massimo il sistema può variare nel tempo di esistenza dello snapshot stesso) e questo spazio dovrà essere parte del VG ma non allocato ad alcun LV. Ci sarà dunque dello spazio sprecato e direttamente proporzionale al working set, ovvero ai dati che vengono maneggiati e scritti in uno specifico lasso di tempo. E' una soluzione che utilizzo ancora ma che mi ha causato alcuni problemi. In determinate circostanze, infatti, il file system si inchioda durante la distruzione dello snapshot, richiedendo un riavvio. Cosa poco carina, per fortuna è capitata di rado ma in situazioni diverse, dunque non imputabili a uno specifico disco/controller/hardware.
  • DattoBD: ho seguito lo sviluppo di questo strumento sin dai suoi albori e ho avuto, nelle primissime versioni, dei problemi che però sono spariti release dopo release. Ha repository per le principali distribuzioni e il funzionamento è ora stabile e, per ciò che ho potuto sperimentare fino ad oggi, sicuro. Per effettuare gli snapshot con Datto utilizzo gli script di UrBackup (altro ottimo sistema di backup che ho utilizzato molto ma che sto ormai usando solo per sistemi Windows), comodi e rapidi.

Backup: push o pull?

Una delle diatribe che da sempre divide gli esperti è proprio quella sulla tipologia di gestione e iniziazione del backup: dovrebbe essere il client a collegarsi al server (push), di fatto "iniziando" il backup, oppure il server a connettersi ai client e "chiedere" il backup (pull)?

A mio avviso, dipende. Nel complesso, tendo ad avere dei sistemi di backup centralizzati su server dedicati che, di conseguenza, tengo in massima sicurezza, facendo girare solo i servizi fondamentali. In alcuni casi, utilizzo Docker per inscatolare l'intero sistema di backup ed evitare il più possibile un coinvolgimento di altri servizi. Proprio per questa ragione tendo a preferire l'approccio "pull", in cui è il server che si collega al client e chiede l'operazione, oppure l'approccio misto del già citato BURP, in cui il client si collega al server che, però, decide se è il momento o meno di fare il backup e ne contingenta l'operazione. Il server, in questo caso, non è dunque uno "stupido" storage, ma un vero e proprio software che svolge la sua funzione.

Purtroppo, però, gli attuali sistemi da me preferiti non supportano questo genere di funzionalità. Ragion per cui ho messo in piedi delle soluzioni alternative che possano in qualche maniera ovviare la situazione.

Prenderò ora in esame i due strumenti che utilizzo maggiormente (insieme al già citato BURP), ovvero Borg Backup e Restic.

Borg Backup

Borg Backup è lo strumento che, da più di un anno, garantisce la sicurezza di quasi tutti i miei backup. Le peculiarità solo:

  • Compressione e deduplicazione dei dati all'interno dello stesso repository
  • Possibilità di effettuare il mount dei backup in una directory, permettendone navigazione, consultazione e ripristino in maniera semplice & comoda
  • Rapido nelle operazioni, genera una cache locale per tenere traccia dei file già copiati e la utilizza per i backup successivi

Addio dunque ai sistemi incrementali, ecc. Borg consente di avere tutti backup deduplicati e compressi come se fossero tutti completi, evitando lente ricostruzioni in fase di consultazione o ripristino.

Ho riscontrato alcuni difetti che, a mio avviso, non sono importantissimi ma è opportuno tenerne conto:

  • Il principale: si consiglia di utilizzare un repository per server in quanto l'operazione di backup è bloccante. Questo implica che la deduplicazione verrà effettuata solo tra "generazioni di backup" e dati dello stesso server. Nel mio caso, che ho centinaia di server "simili" (per OS, configurazioni, ecc.) ci sarà una grossa perdita di spazio. Questo può essere considerato sia un difetto che un pregio (la rottura di un repository sarà limitata a quel repository, non a tutti i backup). Dipende dalle situazioni.
  • Essendo in Python (adoro il Python), impiega qualche secondo a caricarsi ed eseguirsi. Niente di estremo, sia chiaro, ed è rapido e snello nel funzionamento, ma in alcuni casi può essere un po' fastidioso
  • Quando viene effettuato il mount di un repository, lui deve creare degli indici interni per mostrare le directory. Quando i backup cominciano a diventare molti e di molti dati, questa operazione può richiedere anche qualche minuto. Nessun problema se non si ha fretta, ma quando si ha il cliente al telefono e chiede disperatamente di rimettere in piedi un sito o recuperare un documento importantissimo e urgente, quei minuti sono preziosi
  • Anche lui è push, per cui è il client che si collega allo storage per piazzarci i dati. Se lo storage, come nel mio caso, è un server provvisto dell'eseguibile di borg, l'operazione sarà più rapida ed efficace pur girando comunque via ssh

Borg è rapido, efficace e la mia esperienza diretta mi suggerisce che sia sicuro. In molte occasioni sono stato in grado di recuperare server interi, oltre che dati sparsi, in brevissimo tempo e in maniera completa.

Restic

Seguo Restic già da un po', ho fatto esperimenti ma fino ad un po' di tempo fa ho continuato a preferire Borg. Sono due software molto diversi (Restic è scritto in Go) eppure molto simili, sia come approccio che come funzionalità.

Ultimamente, però, le cose stanno prendendo una buona piega per Restic: è diventato molto più rapido e lo sviluppo si sta direzionando verso una delle principali carenze di questo software (alla data odierna): la mancanza di compressione dei dati.

Ecco alcuni vantaggi di Restic:

  • Deduplicazione dei dati anche tra server diversi: Restic, a differenza di Borg, suggerisce l'utilizzo di un unico repository di dati per aumentare la possibilità di deduplicazione anche tra macchine diverse. E' un grosso vantaggio in situazioni, come la mia, in cui ci sono moltissimi server molto simili e ne snellisce anche il primo backup
  • Rapido: i miei test spannometrici dicono sia più rapido di borg, forse perché non comprime
  • Possibilità di effettuare il mount dei backup in una directory, permettendone navigazione, consultazione e ripristino in maniera semplice & comoda. La navigazione è rapida e divisa per snapshot, per host, per tag, rendendo molto semplice l'identificazione del backup richiesto. A differenza di Borg, le strutture vengono create man mano che si naviga all'interno delle directory, rallentando (di un pelo) l'accesso alle stesse ma garantendo prestazioni sempre accettabili.
  • Possibilità di separare le operazioni di "forget" e "prune": alla fine del backup, tendo a far dire al client "ok, butta via i backup più vecchi di..." e lui risponde immediatamente. L'operazione vera e propria di cancellazione verrà poi effettuata successivamente, lanciando il comando "prune". Nel mio caso, questo viene fatto dal server e per tutto il repository (garantendo differenti politiche di tenuta dati in base al server e al cliente), riducendo il tempo effettivo di backup allo stretto indispensabile
  • Community estremanente valida: lo sviluppatore principale, Alexander Neumann è estremamente gentile, cortese e disponibile, nel forum ufficiale, ad aiutare e ricevere feedback e proposte da chiunque.

Restic, come qualunque software, non è perfetto. Ecco alcuni lati negativi che ho riscontrato nell'utilizzo:

  • Mancanza di compressione: a oggi un problema, per me, ma lo sviluppatore ci sta lavorando ed è una feature che arriverà sufficientemente presto
  • Anche Restic è una soluzione push
  • Sembra una banalità, ma nell'uso può essere scomodo: quando si effettua il mount del repository (per navigare nei backup), non viene restituito il prompt ma un messaggio che dice di effettuare l'unmount alla fine dell'operazione. Alias c'è necessità di avere una seconda shell disponibile per entrare nel backup stesso. A volte la cosa può essere frustrante, specialmente se si ha un accesso d'emergenza. Quando me ne ricordo, apro un tmux prima del mount e una seconda shell sotto la prima, per non dimenticare di fare l'unmount alla fine

Esempio: Script utilizzato per effettuare il backup del mio portatile usando Borg e Restic

Passiamo ad un esempio pratico: lo script che utilizzo per effettuare il backup dei miei notebook. In primis, controllo che il computer non stia funzionando a batteria e che il server di backup sia presente (non siamo in una rete diversa o non sia giù per manutenzione). A quel punto, metto un lock ed effettuo uno snapshot utilizzando DattoBD, redirezionando tutto l'output su un file nella directory temporanea:

Borg:

#!/bin/bash
PATH="/usr/local/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/pkg/bin:/usr/pkg/sbin"
export PATH
server=192.168.2.254
export server
STATE=`upower -i /org/freedesktop/UPower/devices/battery_BAT0|grep state|grep discharging`
export STATE
if [[ $STATE == *'discharging'* ]]; then
       exit
fi
if nc -w 10 -z $server 22 2>/dev/null; then
echo "$server ✓";
else
echo "$server ✗";
       exit;
fi
if mkdir /tmp/backuphappening; then
  echo "Locking succeeded" >&2
else
  echo "Lock failed - exit" >&2
  exit 1
fi
exec > /tmp/borg_backup_log
exec 2>&1
date;
/usr/local/share/urbackup/dattobd_create_filesystem_snapshot 1 /
REPOSITORY=user@$server:repo
TAG=daily
ionice -c3 borg create -v --progress --compression zlib --stats                          \
    $REPOSITORY::$TAG'-{now:%Y-%m-%dT%H:%M:%S}'          \
    /mnt/urbackup_snaps/ /boot /boot/efi                                       \
    --exclude '*.cache*'                  \
    --exclude '*/home/*/.cache*'                  \
    --exclude '*/home/*/Scaricati*'                  \
    --exclude '*.datto*'                  \
    --exclude '*.overlay*'                  \
    --exclude '*.crdownload'                  \
    --exclude '*.rpm'                  \
    --exclude '*.deb'                  \
    --exclude '*swapfile*'                  \
    --exclude '*/home/*/Virtualbox VMs*'          \
    --exclude '*/home/*/VirtualBox VMs*'          \
    --exclude '*/home/*/.vagrant.d*'              \
    --exclude '*/root/.cache*'                    \
    --exclude '*/var/lib/docker*'                    \
    --exclude '*/tmp'
/usr/local/share/urbackup/dattobd_remove_filesystem_snapshot 1 /mnt/urbackup_snaps/1
borg prune -v $REPOSITORY --stats --prefix $TAG'-' \
    --keep-hourly=12 --keep-daily=60 --keep-weekly=12 --keep-monthly=24
rm -Rf /tmp/backuphappening
date;

Restic:

#!/bin/bash
PATH="/usr/local/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/pkg/bin:/usr/pkg/sbin"
export PATH
STATE=`upower -i /org/freedesktop/UPower/devices/battery_BAT0|grep state|grep discharging`
export STATE
if [[ $STATE == *'discharging'* ]]; then
       exit
fi
if nc -w 10 -z $server 22 2>/dev/null; then
echo "$server ✓";
else
echo "$server ✗";
exit;
fi
if mkdir /tmp/backuphappening; then
  echo "Locking succeeded" >&2
else
  echo "Lock failed - exit" >&2
  exit 1
fi
exec > /tmp/restic_backup_log
exec 2>&1
date;
/usr/local/share/urbackup/dattobd_create_filesystem_snapshot 1 /
ionice -c3 restic -r myrepo \
    backup                                     \
    --exclude='*/home/*/.cache*'                  \
    --exclude='*.cache*'                  \
    --exclude='*/home/*/Scaricati*'                  \
    --exclude='*.datto*'                  \
    --exclude='*.overlay*'                  \
    --exclude='*.crdownload'                  \
    --exclude='*.rpm'                  \
    --exclude='*.deb'                  \
    --exclude='*swapfile*'                  \
    --exclude='*/home/*/Virtualbox VMs*'          \
    --exclude='*/home/*/VirtualBox VMs*'          \
    --exclude='*/home/*/.vagrant.d*'              \
    --exclude='*/root/.cache*'                    \
    --exclude='*/var/lib/docker*'                    \
    --exclude='/sys'                    \
    --exclude='/proc'                    \
    --exclude='/dev'                    \
    --exclude='*/tmp'                    \
    --exclude='/run'    \
    /mnt/urbackup_snaps/1/
/usr/local/share/urbackup/dattobd_remove_filesystem_snapshot 1 /mnt/urbackup_snaps/1
restic forget -d 30 -w 8 -m 12 -y 1 --host myhost -r myrepo
rm -Rf /tmp/backuphappening
date;

Lo script di Restic è molto più grezzo, è solo un adattamento di quello di Borg per farlo andare e, come già scritto, non effettua il prune effettivo del repository ma marca solo come "da rimuovere" i backup più vecchi. Consiglio una lettura, almeno superficiale, dei manuali dei due strumenti, in modo da non avere i classici problemi da copia & incolla.

Conclusioni

In questo momento sto utilizzando sia Borg che Restic, il primo come sistema principale, il secondo come "emergente", nel senso che lo sto testando nel dettaglio e promette davvero bene. L'arrivo della compressione potrà, probabilmente, colmare il gap e permettermi di sostituire Borg, grazie alla maggiore efficienza di deduplicazione. In entrambi i casi, di notte effettuo un rsync dell'intero repository su uno storage remoto per avere backup replicati in più posti. E un Jenkins che si occupa di collegarsi alle singole macchine, effettuare il backup e avvisarmi in caso di problemi.

Docker e la nuova separazione dei servizi

Se c'è una cosa che mi piace, nell'ambito informatico, è il trovare nuove soluzioni a vecchi problemi. O nuovi problemi a vecchie soluzioni, ma allo scopo di risolvere eventuali punti lasciati in sospeso da tempo, per mancanza di tempo o per mancanza di soluzioni a disposizione.

Una delle questioni più annose, per chi lavora nel settore (ma non solo) è sempre la vecchia scelta operativa: accentrare i servizi su un server o separarli il più possibile?

Alla domanda non esiste una risposta semplice. Dipende dalle risorse a disposizione, da come uno è abituato a gestire e, nel complesso, da quanto tempo si avrà poi per fare la manutenzione del tutto. Più semplice (e più rischioso) fare manutenzione o aggiornamenti ad un singolo server piuttosto che ad uno stuolo di macchine più piccole.

La mia filosofia, per quanto possibile, è sempre stata similare al concetto principale dei sistemi Unix: K.I.S.S. (ovvero Keep It Simple and Stupid), separazione massima per ottimizzare la resa e frammentare eventuali criticità future. Già nei primi anni 2000 utilizzavo OpenVZ e, successivamente, lxc anche su piccoli server Atom domestici per tenere tutto separato. Un container come file server, un altro come mail server, un altro come media server, un altro come backup server, ecc. Il vantaggio è sempre stato quello di separare il più possibile i servizi e ridurre le possibilità di guai in caso di aggiornamenti fasulli o, peggio, compromissione di una delle macchine.

Ho per questo osservato con interesse (e ne ho già scritto in passato) l'avvento di Docker, anche se inizialmente non ho avuto un grosso impatto emotivo. Non mi piaceva o, per lo meno, lo reputavo estremamente immaturo. Tutto è corso e il risultato è che oggi, finalmente, riesco ad avere la separazione che ho tanto sognato. Non più una macchina virtuale per servizio, ma un contenitore per servizio, con tutte le sue dipendenze all'interno. Un overhead inferiore, un risultato equivalente.

Questo approccio, apparentemente complesso, rende in realtà semplicissima la gestione successiva delle risorse. Non dovendomi preoccupare di non incrociare dipendenze, librerie, distribuzioni, servizi, ecc., sarà semplicemente necessario sapere quali sono le richieste di un contenitore ed, eventualmente, collegarlo ad un altro. Stop, il risultato è presto detto: servizio attivo, isolato, aggiornabile, sicuro. E, non da sottovalutare, migrabile da un server all'altro senza particolari problemi.

Mi è recentemente capitato di dover installare un sito che necessitasse di mysql 5.7 su un server con mysql 5.5. Aggiornare il secondo non l'ho neanche preso in considerazione (preferisco restare fedele ai repository ufficiali della distribuzione), far andare il primo su una versione più vecchia sarebbe stato un hack sporco e inaffidabile. Risultato: ho tirato su un bel container con mysql 5.7 e fatto puntare ad esso il CMS. Ho inoltre potuto installare un bel PhpMyAdmin solo per esso e il tutto è stabile e aggiornabile.

Uno dei vantaggi, inoltre, del setup docker-style è quello di non dover perdere più troppo tempo con la macchina da installare. Il sistema operativo del server che farà girare Docker, infatti, servirà ad interfacciarsi con l'hardware (fisico o virtuale) e a gestire gli eventuali backup. Il risultato è presto detto: semplicità di gestione in quanto il centro del tutto non è più il server, fisico o virtuale, ma il singolo servizio.

Un assaggio di Proxmox

/images/Proxmox.thumbnail.png

Proxmox, la storia

Proxmox nasce nel 2008 come sistema completo di virtualizzazione (alternativo a prodotti come VMWare) "a pacchetto". Lo scopo è sempre stato, ed è ancora, quello di fornire un sistema semplice e pratico di preparazione di hardware fisico allo scopo di ospitare macchine virtuali, il tutto gestito attraverso una comoda interfaccia web.

Fino alla versione 3.0, Proxmox ha sofferto di serie problematiche di gioventù. Pur essendo, infatti, già sufficientemente maturo, c'erano alcuni problemi (bug o mancanza di feature) che non lo rendevano estremamente adatto ad ambienti di produzione importanti. Dalla 3.0 in poi, invece, si è assistito al lancio verso l'olimpo in quanto le funzionalità di base erano ormai mature e affidabili e le nuove opzioni erano tutte incentrate sul renderlo sempre più un prodotto enterprise.

Sviluppato e diretto dall'Austriaca Proxmox Server Solutions GmbH, è un progetto in rapido progresso e con interessantissime funzionalità che si aggiungono versione dopo versione.

Il sistema è interamente Open Source, prevede la possibilità di acquistare un abbonamento (a prezzi molto vantaggiosi) per accedere al repository di aggiornamento enterprise, più collaudato e sicuro di quello standard, e tutto il supporto e l'assistenza necessari al sistemista che ne possa avere necessità.

Proxmox, l'architettura e l'installazione

Pur essendosi evoluto in maniera esponenziale negli ultimi anni, Proxmox mantiene la stessa architettura delle origini. A oggi il sistema è strutturato in maniera molto semplice e allo stesso tempo logica. Si basa, infatti, sulla distribuzione Debian standard (wheezy per 3.x, jessie per 4.x, stretch per 5.x) su cui vengono installati i relativi pacchetti provenienti da uno dei repository di Proxmox stesso.

L'installazione può avvenire in due modi:

  • Direttamente dalla ISO di Proxmox stesso, fornita di un comodo, semplice e idiot proof installer grafico, che in pochissimi minuti vi fornirà un sistema completo e configurato.
  • Aggiungendo il repository di Proxmox ad una installazione Debian preesistente (es: installazione su Debian 9.0 Jessie, procedura utilissima nel caso si voglia procedere ad effettuare delle configurazioni non standard o non supportate dalla ISO ufficiale. Con l'installazione del metapacchetto, tutte le dipendenze verranno inserite e, dopo un reboot, si avrà un sistema con le stesse funzionalità di quello installato attraverso la ISO ufficiale.

In entrambi i casi, si discosteranno da Debian standard alcune cose come il kernel (che, normalmente, è in versione più recente e ottimizzata) e pochi altri pacchetti.

Personalmente non ho avuto alcun problema, anche nelle configurazioni più strane, ad installare Proxmox su Debian altamente personalizzata. Ho avuto più noie, invece, ad installare tramite la ISO ufficiale su alcuni hardware parzialmente supportati o obsoleti.

Una delle feature più interessanti di Proxmox è l'attivazione del KSM, ovvero il Kernel Samepage Merging. Capita spesso, infatti, di avere in esecuzione più VM con la stessa versione di sistema operativo, applicativi, ecc. Ebbene, KSM è in grado di fare una scansione di memoria, rilevare queste uguaglianze e deduplicare la memoria. Il risparmio di RAM è consistente e, spesso, può consentire un miglior utilizzo delle risorse della macchina. Di contro, KSM si attiva solo quando la RAM comincia ad avere un utilizzo importante (computazionalmente non è economicissimo) ed è comunque da considerarsi, a mio avviso, qualcosa di "emergenza". Si pensi ad un aggiornamento di una delle macchine virtuali: tutti i software che si aggiornano saranno diversi dagli altri e il KSM non si applicherà ad essi, andando ad aumentare di colpo e drasticamente le risorse richieste rispetto all'equilibrio precedente.

Proxmox, l'utilizzo e le funzionalità

Dopo essersi installato in maniera semplice, sarà semplice anche metterlo in funziona. Al primo avvio ci si troverà di fronte ad una schermata di login con scritto l'indirizzo IP della macchina e l'url di accesso all'interfaccia web. Infatti Proxmox si gestisce quasi integralmente da una comoda interfaccia web, che si è evoluta nel corso della versione 4.x, e consente di fare tutte le operazioni di gestione e buona parte delle operazioni di configurazione e messa in funzione.

/images/Proxmox_interfaccia.thumbnail.png

Sarà dunque necessario accedere alla stessa per iniziare ad esplorare tutto ciò che questo ottimo sistema ci mette a disposizione.

Come detto già in precedenza, Proxmox mette insieme strumenti preesistenti Open Source e crea una comodissima interfaccia di gestione e monitorizzazione. Nello specifico, ci fornisce due strade principali:

  • L'opzione container: era OpenVZ fino alla 4.0, ora invece rimpiazzato da lxc. Il tipo di isolamento fornito da lxc è la base anche di Docker, di cui ho già brevemente parlato, ed è adatta a soluzioni che non richiedono l'installazione di un diverso sistema operativo (alias: lxc permette di usare Linux su Linux)
  • L'opzione virtualizzatore, la cui scelta è ovviamente caduta su KVM, principe dei virtualizzatori su GNU/Linux e con ampio supporto di sistemi operativi Guest e relativi driver virtualizzati Virtio.

OpenVZ era un bel progetto ma, oggi, meno interessante di qualche anno fa. Ne ho fatto largo uso circa 10 anni fa, ma poi l'obsolescenza del kernel in uso e varie altre ragioni mi spinsero verso altri lidi. lxc, invece, l'ho utilizzato con successo fino al 2015 in alcune realtà. Non ho smesso per motivi specifici, semplicemente non mi è più servito e ho optato sempre di più per virtualizzazione completa o, più recentemente, container (Docker) puri.

Tutta la gestione delle VM (o dei container lxc) avviene via web. Sarà dunque possibile creare macchine, lanciarle, agganciare e sganciare dispositivi e lettori virtuali, modificarne le risorse, gestire lo storage, aprire delle console virtuali sia dentro la schermata principali che in un tab separato, ecc.

Proxmox, i cluster

Proxmox supporta in maniera nativa la possibilità di creare dei cluster. Per cluster si intende una serie di server fisici che verranno raggruppati, all'interno dell'interfaccia web, in un "Datacenter" e che possono interagire tra di loro. Si potrà, ad esempio, creare uno storage condiviso (NFS, Gluster, Ceph, ecc.) per migrare a caldo le singole VM da un server fisico all'altro, creare una infrastruttura in Alta Affidabilità (HA) con rilancio automatico delle VM in caso di guasto o down di uno dei nodi fisici.

Si potrà inoltre, da interfaccia, gestire la creazione di uno storage replicato e ridondato Ceph (di cui faccio larghissimo uso in molte delle infrastrutture che gestisco, anche inter-datacenter), controllarne lo stato, aggiungere e rimuovere dischi, ecc.

Un cluster Proxmox andrebbe gestito sempre con numeri di macchine dispari (numero minimo: 3) per assicurare una consistenza ed evitare lo split brain, ovvero che si creino due cluster paralleli e indipendenti che si ignorano.

Proxmox, i backup

Poche soluzioni di virtualizzazione integrate offrono un sistema di backup interno. Proxmox, invece, ha un sistema completo e affidabile già pronto all'uso. Selezionando quali VM salvare, la frequenza, quanti backup tenere e lo storage di riferimento, sarà possibile configurare un sistema automatico di salvataggio a orari prestabiliti e ricevere una e-mail in caso di problemi (oppure, a scelta, sempre).

Il vantaggio di questa soluzione è la totale integrazione con Proxmox stesso. Ripristinare da un backup sarà un gioco da ragazzi, questione di due click (scegliendo se si vuole sovrascrivere la macchina attualmente in produzione o crearne una nuova, parallela). L'unico svantaggio, non da poco, è che tutti i backup sono sempre completi. Sarà dunque necessaria una importante quantità di spazio (e di tempo) per i salvataggi, oppure l'implementazione di sistemi diversi, tra cui l'ottimo Urbackup (di cui non ho ancora parlato).

Proxmox, uno sguardo d'insieme

Utilizziamo Proxmox in produzione da anni, in setup diversificati (da semplici setup un server locale/molte VM a cluster di server ridondati georeplicati su file system condivisi come Gluster o Ceph, in HA), e non siamo mai rimasti delusi. Se ben implementato e configurato, è in grado di fornire ottime prestazioni, una stabilità invidiabile, un giusto utilizzo di risorse e una perfetta gestibilità sia per l'Amministratore con esperienza, sia per l'utente medio che dovrà appunto occuparsi solo delle funzioni base.

Abbiamo oltre 50 nodi fisici proxmox e centinaia di macchine virtuali. Non abbiamo mai avuto un down, un crash o un problema derivato da esso e le funzioni di snapshot, backup integrato, clonazione a caldo di vm (es: per testare un aggiornamento senza toccare la macchina di produzione), ecc. hanno aiutato nella gestione di un parco macchine abbastanza importante come quello che gestiamo quotidianamente.

Usiamo Proxmox, gli storage ridondati e i sistemi di HA per gestire le infrastrutture di alcune tra le più importanti web agency presenti nel nostro Paese e i clienti sono sempre rimasti soddisfatti dei risultati.

Nel complesso, dopo aver provato varie soluzioni diverse in passato e testato varie soluzioni in evoluzioni del presente, Proxmox è ad oggi probabilmente ciò che coniuga meglio la stabilità, la semplicità di utilizzo e di aggiornamento e la versatilità.

Un assaggio di Alfa Romeo Giulietta

/images/giulietta_nera.thumbnail.jpg

Preambolo

Poco meno di due anni fa ho raccontato di come mi sia trovato con la Nuova Panda a Metano e riportato la mia (ottima) esperienza in merito. Percorrendo molti km ogni anno, c'era però necessità di una vettura più "concreta", sia come spazio che come comfort.

La scelta è dunque caduta sulla vettura che aveva mio padre, ovvero una Alfa Romeo Giulietta. La vettura è stata immatricolata nel Dicembre del 2010 (dunque aveva circa sei anni a Marzo, quando l'ho presa in carico) ma aveva solo 30.000 km.

Ecco le caratteristiche:

Modello: Alfa Romeo Giulietta 1.4 Distinctive
Colore: Nero
Motorizzazione: 1.4 MultiAir Turbo 170 Cavalli (Benzina)
Km quando l'ho presa:
  30.000 circa
Km al momento della stesura di questo articolo:
  50.500 esatti
Optional: vari, tra cui cruise control, interno in pelle, ecc.

La vettura era in ottimo stato, condizioni pari al nuovo. E' dotata di sensori posteriori (non originali) che funzionano decisamente male per cui sono praticamente inutili. Per il resto, nulla da segnalare.

Prime esperienze di guida

La prima volta che l'ho guidata sono rimasto decisamente senza parole. La Giulietta, sin dal suo debutto, mi è sempre esteticamente piaciuta ma l'ho sempre considerata poco in quanto ho sempre avuto un certo pregiudizio (a causa delle esperienze precedenti) sulle vetture nostrane. Ne parlerò, prima o poi, in un articolo.

La posizione di guida mi ha subito colpito, così come il sedile. Comodo, avvolgente, decisamente ben fatto. Appena acceso il motore, poi, ho subito apprezzato la sonorità e la silenziosità del benzina. Siamo ormai abituati ai trattoretti Diesel (o ai camion, come chiamo io i Diesel di cilindrata maggiore) e sentire la rotondità e il silenzio del motore a benzina è quasi una sorpresa.

La prima guida è stata interessante: ho apprezzato immediatamente lo sterzo, molto preciso e diretto (ma con pessimo diametro di sterzata) e il telaio. Metterla in difficoltà, pur essendo una vettura a trazione anteriore, è abbastanza difficile (in condizioni di guida in strada), i freni sono pronti ed efficaci. Frizione leggera, cambio preciso.

Ho però notato un fastidioso turbo-lag, simile a quello che avevo notato sulla Panda ma con una differenza: appena il turbo partiva, la vettura sembrava perdere un minimo prima di andare. Dopo una breve ricerca in Rete, ho considerato la cosa come normale e mi sono abituato alla cosa.

Ho provveduto a cambiare batteria e gomme (ancora originali ma sfaldate, come spesso accade sulle gomme moderne dopo qualche anno) e ho iniziato a macinare chilometri.

Consumi

La prima sorpresa (positiva) è stata nei consumi: su strade extraurbane, senza spingere molto, sono riuscito a stare sui 16/17 km/litro mentre in autostrada sui 13/14 km/l, in base all'andatura. Per una vettura a benzina con quei cavalli, un dato decisamente interessante. Non ho valutato, inizialmente, i consumi in città in quanto ne faccio raramente o comunque in scarse percentuali.

Uso Normale

Dopo circa 1000 km, però, ho riscontrato un problema: in accelerazione la vettura strappava, sembrava una specie di sfiato della turbina. Ho dunque optato per una visita in officina e il meccanico ha sostituito le candele (che andrebbero cambiate ogni 30.000 km, ma non costano molto) e un tubetto di sfiato della turbina che s'era rotto. Oltre a ciò, ha provveduto ad effettuare un aggiornamento alle centraline dell'auto e me l'ha riconsegnata.

Vettura trasformata: turbo-lag ridotto enormemente e anche la spinta ne ha beneficiato in maniera esponenziale. Probabilmente il tubino dava già noie e comprometteva le prestazioni. Ah, per chi sta già pensando "ecco, solita auto italiana che si perde nei dettagli": nel 2004 la mia Audi A4 con 40.000 km (e due anni e mezzo di vita) iniziò a ridurre drasticamente la frenata in autostrada. In Audi volevano cambiarmi tutti i dischi, il mio meccanico di fiducia, invece, cambiò solo un tubo di sfiato del servofreno con 10 euro. La vettura andò perfettamente.

La trasformazione a GPL

I consumi a benzina sono buoni ma mal si sposano con le mie percorrenze. Dopo una ricerca accurata, dunque, ho pensato di trasformare la vettura a GPL. Mi sono consultato con alcuni installatori di fiducia e ho fatto montare un impianto della BRC, con polmone sovradimensionato visto il rapporto cilindrata/cavalli. Ho effettuato circa 12.000 km a GPL e non ho riscontrato alcun problema. La differenza di prestazioni è impercettibile e, a parte un leggero strattone quando varia da benzina a GPL, la vettura si comporta egregiamente. La bombola è stata installata al posto della ruota di scorta (che comunque entra bene, nella sua sacca, nel bagagliaio) e il pianale s'è leggermente alzato, non in maniera scomoda. L'autonomia varia dai 450 km (in autostrada, a 130, con climatizzatore acceso) a 570/580 km su strade extraurbane. Decisamente buona, considerata la potenza del motore.

Pregi e difetti

PREGI:

  • Linea: a mio avviso, ancora bellissima.
  • Assetto: tenuta di strada degna di nota, comportamento stradale eccelso.
  • Motore: un pelo vuoto sotto i 2000 giri (prima che entri in gioco la turbina), poderoso e pieno poi
  • Consumi: ottimi, per un benzina. A GPL poi...

DIFETTI:

  • Qualità percepita: non eccelsa, si sente qualche scricchiolio in giro. Gli assemblaggi sembrano buoni, ma sulla qualità delle plastiche interne avrei qualcosa da ridire.
  • Visibilità: ormai su vetture così i sensori sono d'obbligo.
  • Diametro di sterzata: scarso, decisamente scarso. La BMW Serie 1 (grazie alla trazione posteriore) era decisamente più gestibile, così come qualsiasi Mercedes, anche di quasi 5 metri.

Considerazioni finali

La Giulietta è una vettura che mi sta davvero dando delle grandi soddisfazioni. A oggi la consiglierei senza riserve a chi è cosciente di star acquistando una vettura dalle ottime doti stradali, un motore eccelso ed esteticamente molto valida, pur essendo un progetto ormai datato. A chi invece è alla ricerca solo di un marchio tedesco "perché va di moda", senza soffermarsi sulla qualità stradale del singolo progetto, probabilmente la Giulietta non piacerà poi tanto. Ma ognuno è libero di scegliere ciò che vuole.

Un assaggio di Docker

/images/docker.thumbnail.png

Preambolo

Ho fatto i primi passi nella virtualizzazione nel lontano 1998. Mi affascinava l'idea di inscatolare un intero computer all'interno del mio PC e non dover più essere schiavo di installare, cancellare, reinstallare, avere due sistemi operativi diversi per scopi diversi contemporaneamente nella stessa macchina e avere eventuali problemi di boot all'aggiornamento di uno ei due.

Sperimentai dunque VMWare e capii subito che la virtualizzazione sarebbe stata il futuro. Nel corso degli anni la penalizzazione sulle prestazioni si è via via assottigliata e nella mia tesi di laurea, nel 2003, mi occupai proprio degli internal di vari virtualizzatori tra cui il neonato i QEMU. Il bello di qemu era proprio la possibilità di emulare piattaforme hardware diverse per lo sviluppo o l'emulazione, e in maniera sufficientemente (per l'epoca) rapida grazie alla traslazione dinamica delle chiamate di sistema, un metodo per l'epoca rivoluzionario. C'erano anche i primordi di Xen, che dava risultati assolutamente interessanti ma richiedeva modifiche al sistema operativo guest. Venne poi fuori un modulo kernel per qemu (divenuto poi KVM, la base dei principali virtualizzatori moderni) che gestiva la virtualizzazione passando direttamente le chiamate all'hardware sottostante, abbattendo l'overhead prestazionale a livelli bassissimi e consentendo di avere un buon numero di VM su un server fisico.

Da allora mi occupo di virtualizzazione ma ho sempre cercato anche altre possibilità proprio perché nell'informatica bisogna sempre avere fame di novità.

Ho lavorato (con estremo successo, ne racconterò prima o poi l'esperienza) già dal 2005 con OpenVZ, che mi ha permesso (per anni) di far girare il mio server principale sia sul VIA EPIA che su un server esterno a cui migravo il tutto in base alle necessità. I container, insomma, mi sono sempre piaciuti.

Nel 2010, ho iniziato a implementare soluzioni basate su FreeBSD proprio per avere le sue jail, ovvero degli ambienti non emulati ma separati dal sistema operativo principale. In pratica, stesso kernel ma userland completamente diversa. Nessun overhead di virtualizzazione ma semplice separazione degli ambienti. Non era un concetto nuovo, infatti Solaris utilizza i container (o zone) già dal 2004, ma di sicuro un concetto vincente: se il mio scopo non è avere sistemi operativi diversi ma solo tenere separati i servizi, perché dover lanciare n macchine virtuali con n sistemi operativi uguali in esecuzione?

Poco dopo è arrivato anche GNU/Linux, e già nel 2011 sperimentavo con lxc, pur sapendo che non c'erano ancora i requisiti di sicurezza necessari, ma avevo già degli strumenti per tenere separati vari ambienti basati su GNU/Linux.

Proprio su lxc si basa Docker, una soluzione di inscatolamento di ambienti, che ne consente la creazione e l'utilizzo su qualsiasi piattaforma compatibile e crea un ambiente standard in un solo comando.

I miei primi passi con Docker

...sono stati disastrosi, come credo quelli di tutti quelli che hanno iniziato ai suoi albori. Docker è un progetto relativamente recente e, come tale, in forte sviluppo. Uno dei problemi, infatti, è che lo sviluppo è rapido e, a volte, distruttivo. Basta un aggiornamento e cambia qualcosa nella riga di comando, nel setup della rete, nella funzionalità e ci si può trovare con un sistema malfunzionante. Il primo passo che feci non fu diverso. Installai Docker, lo misi in funzione per alcuni test, aggiornai alla nuova versione stabile e tutti i miei contenitori smisero di funzionare per variazioni di struttura. Decisi di buttare via tutto e aspettare tempi migliori.

D'altronde si sa come funziona: o una tecnologia diventa sufficientemente matura in poco tempo, oppure muore. Nel primo caso, l'attesa non è così lunga. Nel secondo, non conviene perdere tempo con qualcosa che non avrà futuro.

Alcuni mesi fa ho deciso di rimettere in piedi il discorso. Di solito imparo qualcosa per necessità, poi lo espando e lo riutilizzo. A volte la necessità è puro vezzo privato, magari per fare qualcosa di non strettamente lavorativo ma si sa, l'animo nerd non lo si tiene a freno e, anzi, guai se ciò avvenisse!

Docker su strada

Rimettere in strada Docker non è stato difficile. A oggi, infatti, le cose sono state rese più facili (sia per architetture tradizionali che per le ARM come Raspberry PI o similari) da un rapido & semplice comando:

curl -sSL get.docker.com | sh

ovviamente a patto di avere curl installato, cosa non del tutto scontata in tutte le installazioni (Debian base non ce l'ha).

In un lampo, sono stato pronto col mio eseguibile pronto da usare e libero di fare dei test.

Ho iniziato. Immediatamente mi sono trovato a mio agio sia con la sintassi (anche se, a mio avviso, va ancora un po' uniformata tra un container normale e uno Swarm sia col funzionamento generale. Il vantaggio dell'inscatolamento delle risorse è indubbiamente evidente. Ogni cosa resta nel suo mondo, con le sue dipendenze, senza andare a intaccare o modificare alcunché sul resto del sistema.

Ho subito iniziato ad aver bisogno di alcune funzionalità non ancora presenti nei container presenti nell'hub ufficiale (specialmente per quanto riguarda le architetture ARM in mio possesso) per cui ho esplorato la creazione di una immagine personalizzata. Anche qui semplicità assoluta, un Dockerfile con tutte le istruzioni necessarie e una bella procedura. In un lampo ho avuto tutto il necessario.

Gli Swarm

Uno Swarm è un gruppo di sistemi su cui Docker è installato che si uniscono in un cluster. In uno swarm, ogni worker può far partire uno dei container e metterlo a disposizione. In uno swarm, un container può essere definito come servizio singolo (farne girare sempre uno su uno dei nodi), oppure come servizio multiplo (far girare n copie, che verranno distribuite nei nodi dello swarm) e milioni di sfumature di configurazione.

In uno Swarm, per scelta progettuale, una porta esposta da un container sarà raggiungibile connettendosi all'IP di uno qualunque dei nodi. Se, ad esempio, abbiamo due nodi (nodo1 e nodo2) e un container che espone la porta 80 (un server http), una volta configurato il servizio come parte dello Swarm sarà possibile connettersi al container stesso sia sull'IP del nodo1 che su quello del nodo2.

Conclusioni

Questo articolo voleva essere solo una rapida carrellata su quella che è stata la mia recente esperienza con Docker e sul perché ho deciso non solo di utilizzarlo ma di approfondirne sempre di più le potenzialità.

Seguiranno altri articoli in merito, quando il tempo me lo consentirà, che spiegheranno come ho risolto alcune delle problematiche principali che possono occorrere nell'utilizzo quotidiano e in produzione di un sistema del genere (es: storage condiviso tra nodi, ecc.)

Suggerisco a tutti di cominciare a prendere in considerazione questo tipo di tecnologia, sia per ragioni di sicurezza che di scalabilità e praticità. Volenti o nolenti, sarà il futuro. O il presente.