# Ceph Technology Know-How (Seconda parte) ## Indice Introduzione ed architettura nella [prima parte](https://hackmd.io/a4-zNuV6R6WiV9ZKlREOZw) ### Seconda parte: - [2. Setup del cluster ed esempi](#2-Setup-del-cluster-ed-esempi) - [2.1. Preparazione macchine](#2.1.-Preparazione-macchine) - [2.2. Bootstrap del cluster](#2.2.-Bootstrap-del-cluster) - [2.3. Aggiunta dei Monitor](#2.3.-Aggiunta-dei-Monitor) - [2.4. Aggiunta degli OSD](#2.4.-Aggiunta-degli-OSD) - [2.5. Verifiche effettuate](#2.5.-Verifiche-effettuate) - [2.5.1. Prova del Ceph Storage Cluster tramite la RADOS CLI](#2.5.1.-Prova-del-Ceph-Storage-Cluster-tramite-la-RADOS-CLI) - [2.5.2. Prova di Ceph File System (CephFS)](#2.5.2.-Prova-di-Ceph-File-System-(CephFS)) - [2.5.3. Prova di Ceph Block Device (RBD)](#2.5.3.-Prova-di-Ceph-Block-Device-(RBD)) - [2.5.4. Prova di Ceph Object Gateway (RadosGW)](#2.5.4.-Prova-di-Ceph-Object-Gateway-(RadosGW)) - [2.6. Requisiti minimi in ambiente di produzione](#2.6.-Requisiti-minimi-in-ambiente-di-produzione) - [3. Stress test](#3.-Stress-test) - [3.1. Disponibilità degli oggetti a seguito di un fallimento di un OSD](#3.1.-Disponibilità-degli-oggetti-a-seguito-di-un-fallimento-di-un-OSD) - [3.2. Simulazione blackout](#3.2.-Simulazione-blackout) - [3.3. Scrittura di file di grandi dimensioni tramite CephFS](#3.3.-Scrittura-di-file-di-grandi-dimensioni-tramite-CephFS) - [3.4. Verifica di situazioni di recupero dai fallimenti](#3.4.-Verifica-di-situazioni-di-recupero-dai-fallimenti) - [4. Benchmark: Linda](#4.-Benchmark:-Linda) - [5. Pros & Cons e scenari di utilizzo](#5.-Pros-amp-Cons-e-scenari-di-utilizzo) - [Bibliografia](#Bibliografia) <!-- TODO CORREZIONE -Spiegare cosa fanno alcuni dei comandi più importanti, ad esempio perchè spargiamo le chiavi ssh, come mai apriamo determinate porte - Spiegare cosa fanno alcuni dei comandi specifici di ceph - Panoramica? --> ## 2. Setup del cluster ed esempi In questa sezione descriviamo le macchine che abbiamo utilizzato, il procedimento per effettuare il setup del cluster ed i test eseguiti per verificare le principali funzionalità di Ceph. Per prima cosa abbiamo creato le macchine virtuali sul quale andremo a lavorare, vi abbiamo installato il sistema operativo e le abbiamo configurate per lavorare su due reti differenti: una rete utilizzata per comunicare con la macchina host e con la rete esterna, ed una rete interna per collegare l'intero cluster Ceph. Una volta configurata la rete vi abbiamo installato tutti i pacchetti necessari come ntp, per sincronizzare il clock delle macchine, docker-ce, perchè utilizzato da Ceph per containerizzare i propri servizi, ed infine cephadm e ceph-common, che sono i pacchetti utilizzati per operare con lo storage cluster; ceph-common fornisce tutti i tool per operare con lo storage cluster mentre cephadm è un software utilizzato per il bootstrap e come orchestratore per i servizi Ceph. Terminata l'installazione di tutto il necessario abbiamo configurato le chiavi ssh in modo tale che ogni macchina possa accedere a tutte le altre facenti parte del cluster senza la necessità di inserire la password; questo è necessario per il funzionamento dell'orchestratore. In seguito abbiamo effettuato il bootstrap del cluster ed aggiunto tutti i servizi necessari al suo funzionamento, quindi altri due monitor (oltre a quello creato dal bootstrap nel client utilizzato) e tre OSD. Nella parte finale abbiamo verificato le principali funzionalità di Ceph; per ogni client abbiamo prima preparato l'ambiente e testato il suo funzionamento con delle semplici prove di scrittura e lettura. ### 2.1. Preparazione macchine - Creare una macchina virtuale con le seguenti caratteristiche - 4 GB RAM - 50 GB di disco - Installare Ubuntu server 20.04.1 aggiungendo Openssh-server nell'installazione, noi abbiamo utilizzato queste credenziali - nome utente: ceph - nome macchina: ceph-00 - password: 123 - Aggiungere un secondo disco da 15 GB, questo sarà lo spazio destinato ed utilizzato dagli OSD - (facoltativo: se si vuole accedere tramite ssh dalla macchina host) Aggiungere la regola di port forwarding per ssh (porta 22) alla scheda di rete con NAT, nel nostro caso abbiamo mappato la porta 22 del guest alla porta 1022 dell'host - Aggiungere una seconda scheda di rete come "Rete interna" chiamata cephnet - Avviare la macchina virtuale e configurare la rete interna - Creare o modificare la configurazione con uno degli editor di testo presenti, noi abbiamo utilizzato "nano" eseguendo l'istruzione seguente ``` sudo nano /etc/netplan/00-installer-config.yaml ``` - Copiare questa configurazione nel file ``` network: ethernets: enp0s3: dhcp4: true enp0s8: dhcp4: false addresses: [192.168.1.20/24] gateway4: 192.168.1.255 nameservers: addresses: [8.8.8.8,8.8.4.4] version: 2 ``` questa configurazione serve ad impostare un indirizzo statico per la rete interna - Applicare la configurazione ``` sudo netplan --debug apply ``` - Verificare che l'indirizzo della macchina sia quello appena aggiornato usando il comando ifconfig (installarlo se necessario con la seguente istruzione) ``` sudo apt install net-tools ``` - Aggiornare tutto ``` sudo apt update sudo apt upgrade ``` - Abilitare l'account root per ssh - Modificare la configurazione di ssh: ``` sudo nano /etc/ssh/sshd_config ``` - Togliere il commento alla linea commentata seguente e sostituirla con: ``` PermitRootLogin yes ``` - Riavviare il servizio sshd ``` sudo systemctl restart sshd ``` - Modificare la password di root con il comando: ``` sudo passwd root ``` - Ottenere i privilegi di root ``` sudo su root ``` - Verificare di aver installato python3 ``` python3 --version ``` nel nostro caso la versione utilizzata è la 3.8.5 - Installare ntp e selezionare la timezone corretta ``` sudo apt update sudo apt install ntp sudo timedatectl set-timezone Europe/Rome ``` - Modificare il file hosts per abbinare il nome degli host agli indirizzi, in modo tale che tutte le macchine virtuali possano riconoscersi all'interno della rete e identificarsi tramite un nome univoco - Aprire il file /etc/hosts ``` sudo nano /etc/hosts ``` - Aggiungere i seguenti host ``` 192.168.1.20 ceph-00 192.168.1.21 ceph-01 192.168.1.22 ceph-02 192.168.1.23 ceph-03 ``` - Installare docker-ce ``` sudo apt-get install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add – sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt update sudo apt-get install docker-ce sudo systemctl start docker sudo systemctl enable docker ``` abbiamo utilizzato docker-ce perchè con altri software come docker e podman abbiamo riscontrato problemi in fase di bootstrap del cluster - Scaricare cephadm, aggiungergli i permessi di esecuzione ed installarlo ``` curl --remote-name --location https://github.com/ceph/ceph/raw/octopus/src/cephadm/cephadm chmod +x cephadm ./cephadm add-repo --release octopus ./cephadm install ``` - Verificare la corretta installazione ``` which cephadm ``` che dovrà ritornare /usr/sbin/cephadm - Riavviare il sistema ed installare ceph-common ``` apt install ceph-common ``` - Aprire la porta 8443 nella scheda di rete NAT per poter visualizzare la dashboard al di fuori della macchina virtuale - Clonare la macchina in altre 3 chiamate ceph-01, ceph-02 e ceph-03, e per ognuna - Modificare le porte di forwarding da VirtualBox La nostra configurazione è la seguente | Macchina | Porta host | Porta guest | | -------- | ---------- | ----------- | | ceph-00 | 1022 | 22 | | ceph-00 | 8443 | 8443 | | ceph-01 | 1023 | 22 | | ceph-01 | 8444 | 8443 | | ceph-02 | 1024 | 22 | | ceph-02 | 8445 | 8443 | | ceph-03 | 1025 | 22 | | ceph-03 | 8446 | 8443 | - Modificare l'indirizzo statico della macchina nella rete interna ``` sudo nano /etc/netplan/00-installer-config.yaml ``` sostituire l'indirizzo 192.168.1.20 con quello della macchina corrente (192.168.1.21 per ceph-01) ed applicare la modifica: ``` sudo netplan --debug apply ``` - Modificare l'hostname ``` sudo hostnamectl set-hostname ceph-01 ``` - Modificare il nome dell'host per l'indirizzo 127.0.1.1 con il nome della macchina relativa all'interno del file /etc/hosts ``` nano /etc/hosts ``` modificare la seguente riga con il nome dell'host corretto: ``` 127.0.1.1 ceph-00 ``` - Generare e condividere la chiave ssh (compreso ceph-00) - Generare la chiave ``` ssh-keygen ``` - Condividere la chiave con gli altri nodi (queste istruzioni sono quelle eseguite dal guest ceph-00) ``` ssh-copy-id root@ceph-01 ssh-copy-id root@ceph-02 ssh-copy-id root@ceph-03 ``` ### 2.2. Bootstrap del cluster - Eseguire il bootstrap utilizzando cephadm dal nodo ceph-00 ``` cephadm bootstrap --mon-ip 192.168.1.20 --initial-dashboard-user admin --initial-dashboard-password 123 --dashboard-password-noupdate ``` Alla fine del processo di bootstrap si avrà un cluster con un unico host su cui sono presenti un servizio "manager" ed un "monitor", più altri servizi di supporto come prometheus e grafana. Sarà inoltre possibile accedere alla dashboard da un browser della macchina host all'indirizzo: http://192.188.56.1:8443. Le credenziali saranno quelle inserite in precedenza nella fase di bootstrap. ### 2.3. Aggiunta dei Monitor - Dall'host ceph-00 configurare gli indirizzi (della rete interna) degli host che ospiteranno gli altri monitor ``` ceph config set mon.ceph-01 public_addr 192.168.1.21 ceph config set mon.ceph-02 public_addr 192.168.1.22 ceph config set mon.ceph-03 public_addr 192.168.1.23 ``` questo modificherà la configurazione del cluster definendo per ogni host l'indirizzo pubblico con il quale effettuare il setup dei monitor - Condividere la chiave pubblica di ceph con gli altri host ``` ssh-copy-id -f -i /etc/ceph/ceph.pub root@ceph-01 ssh-copy-id -f -i /etc/ceph/ceph.pub root@ceph-02 ssh-copy-id -f -i /etc/ceph/ceph.pub root@ceph-03 ``` - Aggiungere gli altri host al cluster utilizzando l'orchestratore (ceph orch utilizza l'orchestratore configurato, nel nostro caso cephadm) ``` ceph orch host add ceph-01 ceph orch host add ceph-02 ceph orch host add ceph-03 ``` al cluster saranno quindi aggiunti i 3 host ed in essi sarà fatto il deploy di altri 3 monitor ed un altro manager. - Una volta che i monitor sono entrati nel quorum, generare il file di configurazione minimale e sostituirlo a quello attuale ``` ceph config generate-minimal-conf > /etc/ceph/ceph-temp.conf mv /etc/ceph/ceph-temp.conf /etc/ceph/ceph.conf ``` questa operazione risulta necessaria in quanto all'interno del file di configurazione del cluster è presente solamente l'indirizzo del monitor generato automaticamente dal processo di bootstrap, cioè quello risiedente su ceph-00. Generando invece una nuova configurazione, saranno aggiunti a tale file anche gli indirizzi delle macchine contenenti i monitor generati nel passo precedente, consentendo all'host di conoscere dove risiedono tutti i monitor con il quale potranno comunicare. In caso contrario, se dovesse fallire il monitor presente su ceph-00 non sarebbe più possibile comunicare col cluster in quanto risulterebbe non disponibile l'unico monitor conosciuto. - Copiare la configurazione ed il keyring sugli altri host ``` scp /etc/ceph/ceph.client.admin.keyring /etc/ceph/ceph.conf root@ceph-01:/etc/ceph/ scp /etc/ceph/ceph.client.admin.keyring /etc/ceph/ceph.conf root@ceph-02:/etc/ceph/ scp /etc/ceph/ceph.client.admin.keyring /etc/ceph/ceph.conf root@ceph-03:/etc/ceph/ ``` la configurazione consente agli altri host di conoscere come è fatto il cluster e dove sono situati i monitor mentre il keyring è la chiave di accesso per poter gestire il cluster. ### 2.4. Aggiunta degli OSD - Dal nodo ceph-00 fare il deploy degli osd sui tre nodi ceph-01, ceph-02 e ceph-03: ``` ceph orch daemon add osd ceph-01:/dev/sdb ceph orch daemon add osd ceph-02:/dev/sdb ceph orch daemon add osd ceph-03:/dev/sdb ``` ### 2.5. Verifiche effettuate #### 2.5.1. Prova del Ceph Storage Cluster tramite la RADOS CLI - Abilitare l'autoscale dei pg dei pool ``` ceph config set global osd_pool_default_pg_autoscale_mode on ``` - Creare un pool e assegnare un'applicazione ``` ceph osd pool create test-pool ceph osd pool application enable test-pool test-rados ``` - Creare un file ``` nano hello.txt scrivere qualcosa al suo interno e salvare il file ``` - Aggiungere il file al cluster ``` rados -p test-pool put ciao hello.txt ``` - Da un altro guest (ad esempio ceph-01) elencare gli oggetti presenti per verificare che sia presente l'oggetto "ciao" e scaricarlo verificandone il contenuto ``` rados -p <pool-name> ls rados -p test-pool get ciao hello2.txt nano hello2.txt ``` - Rimuovere l'oggetto dal cluster ``` rados -p test-pool rm ciao ``` #### 2.5.2. Prova di Ceph File System (CephFS) - Dal nodo ceph-00 creare il file system ``` ceph fs volume create test-fs ``` - Creare la cartella sulla quale montare il file system e montarlo ``` mkdir /mnt/mycephfs mount -t ceph :/ /mnt/mycephfs -o name=admin ``` - Creare un file ``` nano /mnt/mycephfs/hello.txt scrivere qualcosa al suo interno e salvare il file ``` - Da un altro guest (ad esempio ceph-01) creare la cartella e montare il file system ``` mkdir /mnt/mycephfs mount -t ceph :/ /mnt/mycephfs -o name=admin ``` - Verificare la presenza del file e del suo contenuto ``` nano /mnt/mycephfs/hello.txt ``` #### 2.5.3. Prova di Ceph Block Device (RBD) - Creare un pool ed inizializzarlo per RBD ``` ceph osd pool create block-pool rbd pool init block-pool ``` - Creare l'immagine del dispositivo a blocchi ``` rbd create test-image --size 2048 --pool block-pool ``` - Mappare l'immagine ``` rbd map test-image -p block-pool ``` - Formattare l'immagine ``` mkfs.ext4 /dev/rbd0 ``` - Montare l'immagine e scrivere un file ``` mkdir /mnt/mycephbd mount /dev/rbd0 /mnt/mycephbd nano /mnt/mycephbd/hello.txt scrivere qualcosa al suo interno e salvare il file ``` - Smontare l'immagine ``` umount /mnt/mycephbd ``` - Da un altro guest (ad esempio ceph-01) mappare l'immagine, montarla e verificare presenza e contenuto del file ``` rbd map test-image -p block-pool mkdir /mnt/mycephbd mount /dev/rbd0 /mnt/mycephbd nano /mnt/mycephbd/hello.txt ``` #### 2.5.4. Prova di Ceph Object Gateway (RadosGW) - Creare un reame ``` radosgw-admin realm create --rgw-realm=reame --default ``` - Creare un zonegroup ``` radosgw-admin zonegroup create --rgw-zonegroup=eu --rgw-realm=reame --master --default ``` - Creare una zona ``` radosgw-admin zone create --rgw-zone=it --rgw-zonegroup=eu --rgw-realm=reame --master --default ``` - Aggiornare il period ``` radosgw-admin period update --rgw-realm=reame --commit ``` - Mappare la porta 80 del guest su una porta dell'host (noi abbiamo utilizzato la 7080) - Fare il deploy del gateway ``` ceph orch apply rgw reame it --placement="1 ceph-00" ``` - Creare un utente system per la dashboard ed iniettare le sue credenziali nella configurazione della dashboard ``` radosgw-admin user create --uid=system --display-name=system --system copiare l'access-key e la secret-key ed inserirle nelle seguenti istruzioni: ceph dashboard set-rgw-api-access-key <access_key> ceph dashboard set-rgw-api-secret-key <secret_key> ``` - Riavviare il gateway ``` ceph orch restart rgw ``` A questo punto dovremmo poter vedere l'Object Gateway dalla dashboard - Creare un altro utente e segnarsi le sue credenziali ``` radosgw-admin user create --uid=johndoe --display-name=johndoe copiare l'access-key e la secret-key che saranno usate nello script python ``` - Testare il funzionamento eseguendo il seguente script python sostituendo access_key e secret_key con le credenziali ottenute nel passo precedente ``` import boto.s3.connection access_key = '<USER-ACCESS-KEY>' secret_key = '<USER-SECRET-KEY>' print('\nConnessione come utente ') conn = boto.connect_s3( aws_access_key_id = access_key, aws_secret_access_key = secret_key, host = '192.168.56.1', port = 7080, is_secure=False, calling_format = boto.s3.connection.OrdinaryCallingFormat(), ) print('\nCreazione bucket my-new-bucket') bucket = conn.create_bucket('my-new-bucket') print('\nCreazione oggetto ciao.txt') key = bucket.new_key('ciao.txt') key.set_contents_from_string('Hello World!') print('\nElenco dei bucket\n') for bucket in conn.get_all_buckets(): print('\t{name}\t{created}'.format( name = bucket.name, created = bucket.creation_date, )) print('\nElenco degli oggetti contenuti nel bucket\n') for key in bucket.list(): print ('\t{name}\t{size}\t{modified}'.format( name = key.name, size = key.size, modified = key.last_modified, )) print('\nRecupero dell\'oggetto ciao.txt dal bucket') key = bucket.get_key('ciao.txt') print('\nStampa del contenuto dell\'oggetto\n') print('\t{text}'.format(text = key.get_contents_as_string().decode('utf-8'))) print('\nSalvataggio del contenuto nel file hello.txt') key.get_contents_to_filename('C:/Users/UTENTE/Documenti/hello.txt') print('\nRimozione di tutti gli oggetti dal bucket my-new-bucket') for key in bucket.list(): bucket.delete_key(key.name) print('\nCancellazione del bucket my-new-bucket') conn.delete_bucket('my-new-bucket') ``` Una volta eseguito lo script il risultato dovrebbe essere il seguente: ``` Connessione come utente johndoe Creazione bucket my-new-bucket Creazione oggetto ciao.txt Elenco dei bucket my-new-bucket 2020-11-19T14:35:51.110Z Elenco degli oggetti contenuti nel bucket ciao.txt 12 2020-11-19T14:35:51.143Z Recupero dell'oggetto ciao.txt dal bucket Stampa del contenuto dell'oggetto Hello World! Salvataggio del contenuto nel file hello.txt Rimozione di tutti gli oggetti dal bucket my-new-bucket Cancellazione del bucket my-new-bucket ``` ### 2.6. Requisiti minimi in ambiente di produzione Ceph è stato progettato per funzionare su hardware di base, il che rende economicamente fattibile la creazione e la manutenzione di cluster di dati su grande scala. Quando si pianifica l'hardware del cluster, è necessario effettuare una serie di considerazioni, inclusi i domini di errore e potenziali problemi di prestazioni. La pianificazione dell'hardware dovrebbe includere la distribuzione di tutti i demoni e di tutti i processi che utilizzano Ceph su molti host; solitamente è consigliata l'esecuzione di un determinato demone su un host che si è pianificato e configurato per ospitare quel tipo di demone. Gli esempi che abbiamo mostrato precedentemente li abbiamo eseguiti utilizzando hardware che non soddisfa i requisiti minimi consigliati in un ambiente di produzione, infatti abbiamo riscontrato parecchi problemi e limitazioni anche se ci è stato comunque possibile realizzare un sistema funzionante sul quale eseguire i test. Nell'immagine in Figura 10 è possibile vedere i requisiti minimi consigliati in ambiente di produzione per ogni demone, inoltre si vuole ricordare che per avere un sistema con funzionalità e proprietà essenziali, è consigliato avere almeno 3 Monitor, 3 OSD e, nel caso si voglia utilizzare CephFS, almeno un MDS. | ![](https://i.imgur.com/SIQmgY3.png) Figura 10 - Requisiti minimi per demone | |:----------------------------------------------------------------------------:| ## 3. Stress test In questo capitolo andremo a descrivere i test effettuati per verificare alcune caratteristiche e limitazioni della tecnologia. ### 3.1. Disponibilità degli oggetti a seguito di un fallimento di un OSD In questa prova si vuole verificare la disponibilità di un oggetto nel caso un OSD dovesse fallire, in particolare se quello in questione è l'OSD identificato come primario. Per farlo ci si pone nella condizione di un cluster interamente funzionante e si effettua una scrittura di un oggetto, in questo caso abbiamo utilizzato lo strumento a linea di comando eseguendo le seguenti istruzioni: ``` ceph osd pool create test-pool ceph osd pool application enable test-pool test-rados nano hello.txt scrivere qualcosa al suo interno e salvare il file rados -p test-pool put ciao hello.txt ``` Una volta scritto l'oggetto, abbiamo spento un host, ceph-01, cioè quello contenente l'OSD primario sul quale è stata effettuata la scrittura (identificato osservando la dashboard). A quel punto si è passati ad un host diverso da quello dal quale abbiamo effettuato la scrittura e abbiamo verificato che l'oggetto fosse ancora presente, in seguito lo abbiamo scaricato per verificarne il contenuto: ``` rados -p test-pool ls rados -p test-pool get ciao hello2.txt nano hello2.txt ``` In questo modo abbiamo verificato che non sono necessarie tutte le macchine attive per poter leggere e scrivere oggetti, in particolare che non è obbligatoria la presenza dell'OSD primario che ha effettuato la scrittura dell'oggetto nel momento della lettura, fatto dovuto alla configurazione di default del cluster che esegue automaticamente le repliche dei placement group. ### 3.2. Simulazione blackout Come seconda prova si è pensato di verificare che il cluster tornasse integro e funzionante a seguito dello spegnimento completo di tutti gli host, simulando un possibile blackout. In questo caso la prova è stata semplice, da una condizione funzionante sono state spente tutte le macchine virtuali e sono state riavviate; una volta che tutti gli host sono tornati online verranno riattivati automaticamente tutti i demoni ed il cluster ritornerà alla condizione iniziale di funzionamento. Inoltre abbiamo notato che nel momento di riaccensione degli host, il sistema si autoconfigura e rigenera automaticamente, senza alcun intervento da parte nostra, che come detto in precedenza è una proprietà chiave di Ceph. ### 3.3. Scrittura di file di grandi dimensioni tramite CephFS Come terza prova abbiamo voluto verificare il funzionamento dello storage cluster nel caso di file di grandi dimensioni; per far ciò siamo partiti dalla condizione iniziale di un cluster funzionante composto da 3 OSD, ciascuno con un disco di 15 GB, e abbiamo deciso di utilizzare l'interfaccia CephFS per salvare il file. Abbiamo deciso di verificare tre condizioni al variare della dimensione dei file, la prima con un file molto grande ma che non eccede la dimensione massima di un OSD (un file di circa 10 GB), la seconda con un file che eccede la dimensione di un'OSD ma che è inferiore alla capacità massima di storage del cluster (un file di circa 25 GB mentre la capacità massima del cluster è di 45 GB) e la terza con un file che eccede la capacità massima del cluster. Nella prima situazione volevamo osservare il comportamento nel caso di un file di grande dimensione e abbiamo visto che il sistema non ha avuto problemi in questa operazione, abbiamo inoltre notato che senza cambiare le impostazioni di default viene utilizata una politica di replicazione (quindi non viene utilizzato l'erasure coding ma deve essere attivato manualmente alla creazione dei pool) a 3 copie quindi in tutto verranno occupati 30 GB della capacità totale (10 GB dell'originale e 20 GB per le due repliche). Nella seconda situazione abbiamo voluto variare leggermente quella precedente, cioè aggiungere un file che superi la capacità massima di ogni singolo OSD ma che rimanga entro i limiti della capacità massima del cluster. Dato che viene effettuato lo striping dei file in oggetti e questi vengono distribuiti in modo uniforme sull'intero cluster, da questa situazione ci si aspetta che non sorga alcun problema, cioè i dati dovrebbero essere distribuiti e dovrebbero occupare in ugual modo tutti gli OSD. Per replicare questa situazione si è pensato di copiare un file di circa 25 GB ma, dato che il cluster ha una capacità massima di circa 45 GB, abbiamo disattivato la replicazione scrivendo una sola copia del file, cioè l'originale; in caso di configurazione di default avremmo occupato 75 GB per le 3 copie, eccedendo la capacità massima dell'intero cluster che verificheremo poi come terza condizione. Il risultato di questa prova è quello previsto anche se si è osservato che la distribuzione dei dati ottenuta è stata un pelo sbilanciata rispetto quella immaginata; comunque anche se non è una distribuzione uniforme esatta è comunque abbastanza equilibrata (OSD1 con 9,4 GB, OSD2 con 9,9 GB e OSD3 con 8,7 GB). L'ultima situazione che abbiamo voluto verificare è il superamento della capacità massima per vedere come si comporta lo storage cluster nel caso venga occupato interamente; per far ciò abbiamo utilizzato il file da 25 GB e abbiamo ripristinato la replicazione. In questa casistica si è pensato a comportamenti totalmente diversi che potevano accadere: poteva essere effettuato un controllo iniziale dal client confrontando lo spazio disponibile con la dimensione del file e delle sue repliche in modo da terminare subito l'operazione con un messaggio di errore; oppure poteva essere effettuata una singola copia del solo file originale ed avvistare l'utente che non è stata effettuata la replicazione a causa di spazio insufficiente; oppure poteva avvenire la copia dando un errore ed annullando il salvataggio una volta raggiunta la capacità massima del cluster. In realtà il comportamento che abbiamo notato è ancora diverso dei precedentemente pensati; il client CephFS non effettua un controllo iniziale, quindi effettua la copia del file nel cluster fino al raggiungimento della capienza massima, momento nel quale il sistema va in panico. Dal client l'operazione non viene interrotta ma rimane in stallo come se la stesse ancora effettuando e non viene segnalato il problema in nessun modo; gli OSD ed il pool utilizzato per il file vengono visualizzati tutti come completamente pieni, inoltre si è notato che gli OSD si sono riavviati tutti ma uno dei tre, ceph-03, è rimasto down. Sono presenti alcune configuarazioni che permettono di attivare dei warning di salute del cluster o addirittura bloccare le scritture dei client, al raggiungimento di determinate percentuali di riempimento dei singoli OSD, in particolare ne esistono tre: - "Full ratio", di default impostata al 95% della capacità di un OSD, al suo raggiungimento impedisce le operazioni di scrittura da parte dei client; - "Backfillfull ratio", di default impostato al 90%, indica quanto un nuovo OSD, inserito all'intenro di un determinato active set, può riempirsi tramite le operazioni di ribilanciamento dei dati; - "Nearfull ratio", definita di default all'85% della capacità degli OSD, al suo raggiungimento genererà un avviso di salute per indicare lo stato dell'OSD in questione, che sarà visibile anche tramite la dashboard. Durante l'esecuzione della prova queste limitazioni non hanno impedito il riempimento degli OSD e si pensa sia dovuto al fatto che nessun file è stato scritto tra le soglie imposte ed il completo riempimento degli OSD ma è stato utilizzato un file unico che ha riempito completamente tutti gli OSD; in un caso reale probabilmente non potrebbe venirsi a presentare tale condizione in quanto non verrà mai utilizzato Ceph per storage cluster di piccole capacità come nel nostro caso. ### 3.4. Verifica di situazioni di recupero dai fallimenti In questa prova abbiamo voluto verificare alcune caratteristiche e condizioni che non abbiamo trovato sulla documentazione, in modo da capire come si comporta lo storage cluster in alcune situazioni. La prima casistica verificata è come vengono gestiti e trattati i manager, abbiamo notato che la gestione degli stati è la stessa descritta precedentemente per gli MDS, cioè questi possono assumere due possibili stati: attivo e standby. Il manager attivo è quello che ospiterà la dashboard e quindi quello al quale dovremo connetterci per ottenere la rappresentazione grafica dello stato del cluster, mentre quello in stato standby sarà in una condizione di riposo, in quanto non effettua operazioni, ma sarà sempre pronto a rimpiazzare il manager attivo qualora questo fallisse. Al bootstrap del cluster si è notato che vengono inizializzati due manager, uno attivo ed uno standby; abbiamo provato a far fallire quello attivo per verificare la condizione di cui abbiamo appena parlato e in seguito abbiamo fatto fallire anche il secondo manager per verificare cosa fosse successo in questo caso. Nel caso tutti i manager dovessero fallire, Ceph non ne creerebbe di nuovi lasciando lo storage cluster senza tutte le funzionalità offerte da questo componente. Questo vale per tutti i demoni presenti, siano questi essenziali al funzionamento del cluster che non, come ad esempio grafana, prometheus ma anche nel caso questi demoni fossero i monitor; questa casistica è stata verificata in quanto ci si aspettava che per i servizi indispensabili al funzionamento di Ceph fosse riservato un trattamento differente. Nel caso di fallimento di uno dei servizi indispensabili si era previsto che questi sarebbero stati ricreati, qualora fosse disponibile un host configurato per ospitarli ed una condizione che ne richieda la presenza. Per fare tale verifica siamo partiti da un cluster funzionante e abbiamo configurato tutti i monitor per la loro creazione ma ne abbiamo creati solo 3 sugli host ceph-00, ceph-01 e ceph-03 in modo tale da ottenere il quorum; a questo punto abbiamo spento ceph-00, in questo caso il quorum rimane perchè la maggioranza dei monitor è ancora attiva. Una volta spento anche ceph-01, il quorum non è più preservato e di conseguenza non viene più condivisa la cluster map, questo comporta il fatto che i monitor non riusciranno più ad effettuare il loro compito e quindi non sarà più possibile vedere i cambiamenti nello stato del cluter ma solamente l'ultima immagine di esso nell'istante dell'ultimo quorum effettuato. In questa condizione infatti abbiamo visto che spegnendo un manager rimarrebbe comunque invariato il suo stato sulla dashboard. Creando tale situazione ci saremmo aspettati che al primo fallimento di un monitor questo fosse rimpiazzato creandone uno nuovo sull'host ceph-02 ma questo non è successo, e non è stato fatto nemmeno al fallimento del secondo monitor, quando è venuto a mancare il quorum e di conseguenza è stato compromesso il funzionamento dell'intero cluster. ## 4. Benchmark: Linda Si è pensato di utilizzare questa tecnologia calandola in un caso reale, in particolare per fornire persistenza agli spazi delle tuple utilizzati dal framework Linda. Per far ciò abbiamo deciso di utilizzare la funzionalità RadosGW vista in precedenza, in quanto è quello che si presta meglio a rappresentare il modello utilizzato da Linda, in particolare è possibile raffigurare gli spazi di tuple come bucket S3 e le tuple come gli oggetti al loro interno. Come prima cosa abbiamo completato l'esercizio del laboratorio 7, implementando le funzionalità necessarie per il funzionamento del client Linda, in seguito lo abbiamo modificato per aggiungere la persistenza dello spazio delle tuple tramite l'utilizzo di Ceph. Si è pensato di mantenere il funzionamento del client invariato sfruttando la memoria locale per le operazioni in sola lettura, ed interagire con lo storage cluster solamente per la creazione dello spazio delle tuple e per le operazioni "in" ed "out". Inoltre, è stato necessario modificare le tuple, in quanto ognuna di esse dovrà ora possedere anche un riferimento al nome dell'oggetto con cui sarà memorizzata su Ceph. Dato che lo spazio delle tuple dovrà essere persistente, sarà necessario controllare se questo esiste già all'interno di Ceph, in caso contrario si crea un nuovo bucket, altrimenti si ottiene il riferimento di quello già presente, si leggono tutte le tuple al suo interno e si memorizzano nello spazio delle tuple locale. Le operazioni di "in" ed "out" sono state modificate in modo da rispecchiare le operazioni locali sulla memoria persistente, rimuovendo gli oggetti corrispondenti alle tuple rimosse dalle "in" ed aggiungendoli in caso di "out"; per questa seconda operazione si è pensato inoltre di non scrivere in memoria persistente le tuple al momento della ricezione della richiesta, ma solamente dopo aver completato le richieste pendenti, il cui template viene soddisfatto dalle tuple in questione, ed alla condizione che queste tuple non vengano immediatamente rimosse da tali richieste. In questo modo si possono evitare operazioni di scrittura di tuple dalla memoria persistente, in quanto verrebero subito rimosse dalle richieste pendenti che ne soddifano il match, riducendo così il tempo di esecuzione delle operazioni "out". Per verificare che il comportamento del client sia quello atteso abbiamo aggiunto un test, per verificare la persistenza dei dati, a quelli già presenti che utilizziamo per assicurarci che il comportamento rimanga consistente; questo test compie i seguenti passi: 1. crea uno spazio delle tuple e vi aggiunge 4 tuple; 2. crea un nuovo spazio delle tuple con lo stesso nome, dato che sarà già presente caricherà le tuple create nel passo precedente; 3. richiede il contenuto dello spazio delle tuple creato nel passo 2; 4. perchè il test abbia successo, verificare che il risultato del punto 3 e l'insieme iniziale delle tuple coincidano. | ![](https://i.imgur.com/mPaQasr.png) Figura 11 - Risultato del test | |:-------------------------------------------------------------------:| ## 5. Pros & Cons e scenari di utilizzo Ceph è una tecnolgia ben consolidata per la realizzazione di sistemi di storage distribuiti, in quanto i vantaggi che offre sono rappresentati da feature molto ricercate sia per semplici soluzioni, sia per grandi ambienti di produzione. In particolare Ceph: - offre ottime prestazioni in termini di velocità delle operazioni, e risulta essere una soluzione molto scalabile; - presenta ottime integrazioni con le principali tecnologie di virtualizzazione (come KVM, libvirt, OpenStack, XEN e Proxmox). Questo unito alla possibilità di immagazzinare snapshot all'interno del proprio sistema di storage rende Ceph un'ottima scelta per supportare la virtualizzazione; - offre tecnologie per operare con tutte e tre le tipologie di storage quali blocchi, file e immagini, rendendolo dunque estremamente flessibile ai vari scenari applicativi (come ad esempio NAS e SAN); - è una tecnologia open source, ideale per le aziende che vogliono ridurre il costo dei propri sistemi di storage, senza però sacrificarne l'efficacia; - fa in modo che tutti i dati siano replicati automaticamente da un nodo ad un altro, evitando il disservizio qualora uno dei nodi dovesse fallire, dato che potrebbe essere fornito dal nodo ancora attivo. In questo modo i dati possono essere recuperati in un qualsiasi momento; - immagazzina in modo efficiente i dati, assicurandosi di non occupare spazio in memoria finchè non sono effettivamente stati salvati; - è altamente resiliente, grazie alla sua capacità di rilevare e riprendersi automaticamente da eventuali fallimenti, fintanto che viene mantenuto il numero minimo di nodi attivi. Ad ogni modo Ceph presenta ancora alcune problematiche e svantaggi, riscontrati dai molti utenti che ne hanno fatto uso, in particolare: - la realizzazione di un cluster Ceph completo risulta essere un processo estremamente lungo e complesso. In questo viene in limitato aiuto la documentazione, che in molti casi risulta essere estremamente frammentaria e talvolte obsoleta; - il sistema di bootstrap del cluster risulta minimo nei report degli errori, per cui gli utenti faticano a comprendere se i processi di setup sono andati a buon fine; - errori nella configurazione possono risultare in cali di performance e distribuzione dei dati sbilanciata; - per ambienti di produzione è sconsigliata la realizzazione di un cluster Ceph risiedente su macchine virtuali per motivi di ottimizzazione. Questo può essere un fattore limitante per piccoli casi d'uso che non possono permettersi l'utilizzo di decine di macchine fisiche, ognuna con il proprio OSD. ### Scenari applicativi Ceph può essere utilizzato in molti scenari applicativi, uno dei principali è il suo affiancamento alle principali tecnologie per la realizzazione di database Sql e NoSql. In particolare Ceph è stato adottato da molte aziende per la realizzazione dei propri servizi di Database-as-a-Service (DaaS), sfruttando le proprie risorse hardware invece di ricorrere al public cloud. Gli storage cluster Ceph possono gestire diversi tipi di carichi di lavoro; sebbene quelli ad alto rendimento ed incentrati sul costo/capacità siano comuni, l'utilizzo di Ceph per servire carichi di lavoro MySQL ad alta intensità di operazioni input/output al secondo (IOPS) è sempre più visto negli ambienti di produzione per la sua ottima propensione alla scalabilità. Ceph consente a gruppi di server di mettere in comune le proprie risorse di archiviazione e permette a qualsiasi server del gruppo di accedere all'archiviazione sulla rete. Ciò consente un posizionamento più flessibile ed efficiente dei database nel cluster, senza richiedere strumenti come rsync o la replica di MySQL per spostare i dati. Inoltre offre un'ampia gamma di funzionalità, tra cui: ridimensionamento live dei volumi, mirroring dei volumi, migrazione dei volumi, migrazione live delle macchine virtuali, clonazione copy-on-write e snapshot. Ceph è quindi un'ottima soluzione per la gestione di grandi raccolte di istanze di database MySQL attraverso l'utilizzo dell'interfaccia RBD. Le aziende che hanno deciso di adottare questo modello di cloud privato o ibrido basato su Ceph, sono in grado di fornire dei sistemi di storage ad un prezzo migliore del già popolare cloud pubblico, senza sacrificare caratteristiche di performance essenziali. Un'altro possibile scenario applicativo è l'utilizzo di Ceph per la realizzazione di Network Attached Storage (NAS) clusterizzati. Una web server farm deve avere accesso agli stessi file in modo che i client connessi ricevano lo stesso contenuto a prescindere dal server a cui si connettono. Tradizionalmente per offrire accesso ai file distribuiti viene utilizzato un NAS ad alta disponibilità, ma questo può riscontrare diverse limitazioni quando si tratta di scalare il sistema. In questo contesto si fa strada CephFS, in quanto grazie alla sua capacità di realizzare sistemi di storage basati su file, è in grado di distribuire dati e metadati sui vari nodi del cluster, fornendo così accesso unificato ai file da ciascun nodo a prescindere dall'effettiva locazione dei dati. Questo gli permette di essere adottato per immagazzinare i contenuti su un file system distribuito ed essere montato su ogni nodo della server farm, ponendosi come alternativa ai NAS precedentemente adottati. Ceph inoltre sta diventando un'alternativa molto allettante per la realizzazione di Storage Area Network (SAN), poichè in grado di fornire le tre tipologie principali di storage (file, blocchi e oggetti) sfruttando hardware relativamente economico rispetto alle metodologie stabilite. In questo modo permette alle aziende di sfuggire al vendor lock-in senza compromettere però le performance e senza mancare di feature importanti. Una delle integrazioni di RBD è la possibilità di utilizzare un gateway iSCSI; questo presenta un'entrypoint iSCSI ad alta disponibilità che esporta le immagini RBD (RADOS Block Device) come dischi SCSI. Il protocollo iSCSI consente ai client di inviare comandi SCSI ai dispositivi di archiviazione su una rete TCP/IP, consentendo a quelli senza il supporto client Ceph nativo di accedere allo storage a blocchi Ceph. Con questa funzionalità è possibile fornire un'infrastruttura di storage a blocchi completamente integrata con tutte le caratteristiche ed i vantaggi di una rete SAN convenzionale. Infine Ceph può essere utilizzato da alcuni dei principali hypervisor (VMware, Xen, Proxmox, QEMU, KVM etc..) per gestire lo storage di immagini e snapshot di macchine virtuali, permettendo inoltre la gestione dei dischi virtuali delle singole macchine sfruttando l'interfaccia RBD, la quale effettuerà lo striping dei volumi suddividendoli in blocchi e distribuendoli nel cluster. Dato che le immagini non vengono immagazzinate sullo stesso hardware su cui risiede l'hypervisor, diventa possibile effettuare live migration delle macchine, cioè spostare le macchine virtuali tra macchine guest senza doverle spegnere e senza disconnettere i client, trasferendo automaticamente memoria, storage e connessioni della macchina virtuale. ## Bibliografia - Sage A. Weil, Andrew W. Leung, Scott A. Brandt, Carlos Maltzahn. RADOS: A scalable, reliable storage service for petabyte-scale storage clusters, 2007 - Sage A. Weil, Scott A. Brandt, Ethan L. Miller, Carlos Maltzahn. CRUSH: Controlled, Scalable, Decentralized Placement of Replicated Data, 2006. - Singh Karan, Weil Sage. Learning Ceph. Birmingham, England: Packt Publishing, 2015 - Vikhyat Umrao, Michael Hackett, Karan Singh. Ceph Cookbook - Second Edition: Practical recipes to design, implement, operate, and manage Ceph storage systems. Birmingham, England: Packt Publishing, 2017 - Sage A. Weil. Ceph: reliable, scalable, and high-performance distributed storage, 2007 - Documentazione Ceph di Red Hat, https://access.redhat.com/documentation/en-us/red_hat_ceph_storage/4/html/architecture_guide/the-ceph-architecture_arch (data di consultazione: dicembre 2020) - Documentazione ufficiale di Ceph, https://docs.ceph.com/en/latest/ (data di consultazione: dicembre 2020) - Video di Ross Turk (Inktank). Ceph intro & architectural overview, https://www.youtube.com/watch?v=7I9uxoEhUdY - Video di Sage Wail. Intro to Ceph, https://www.youtube.com/watch?v=PmLPbrf-x9g - Articolo Medium di fajlinuxblog. Ceph: an overview, https://fajlinuxblog.medium.com/ceph-an-overview-e971c00ded93