Che cosa penseresti se ti dicessi che ogni piccolo cambiamento può fare una grande differenza? Questo approccio può essere fondamentale nella scelta di una soluzione di Infrastrucuture as a Service ed è esattamente il medesimo approccio attraverso cui abbiamo incrementato le performance del nostro storage Ceph.
Ottimizzare Ceph è sicuramente un sfida difficile, che presuppone elevate competenze di Ceph, RocksDB e kernel Linux e soprattutto tenacia e costanza nei numerosi tentativi. Abbiamo studiato, lavorato e testato e il risultato è stato migliorare sensibilmente le prestazioni dei nostri storage Ceph raggiungendo un livello di performance soddisfacente. Vediamo insieme come.
Che cos'è Ceph e cosa offre?
Per coloro che conoscono già Ceph probabilmente sarà una banalità ma è giusto fare una breve introduzione.
Ceph è un Software Defined Storage interamente Open source nato per grandi scale (es. Cloud providers) focalizzato sulla resilienza dei dati. Tali dati possono essere esposti in differenti modalità: a blocchi, a file e ad oggetti.
Al momento dell’installazione di Ceph, se non modificate, vengono adottate configurazioni e caratteristiche standard, che di default sono adatte a workload generici. Tale base di partenza, comporta performance altrettanto generiche, e quindi non eccellenti o ottimizzate per uno specifico workload.
Per raggiungere performance migliori è necessario apportare delle modifiche. Per farlo, ciò su cui ci siamo focalizzati e su cui abbiamo lavorato è la modalità con cui RADOS salva i suoi oggetti su disco.
Storage Ceph: un salto nel passato e uno nel presente
Nell’ultimo decennio, Ceph si è affidato a due implementazioni diverse di Object Storage. Quando parliamo di object storage a basso livello, non parliamo del famoso protocollo object storage che Ceph espone (S3) ma di come il protocollo Rados gestisce tutti gli input-output con oggetti che vengono letti e scritti fisicamente sui dischi.
La prima implementazione di Object Storage utilizzata, e ora deprecata, è stata FileStore. Questa versione di Ceph utilizzava un filesystem XFS per memorizzare i dati e i metadati degli oggetti sul disco. In particolare, il file store separava l’oggetto in due parti:
- Dato raw - Il dato grezzo e non elaborato;
- Metadato - ovvero le informazioni a corredo del dato utili ad identificare e ricercare il dato stesso.
Tornando a FileStore, mentre la parte raw era scritta direttamente in XFS, il metadato veniva salvato all’interno di un database, in particolare leveldb. Leveldb, database progetto di Google, a sua volta salvava il dato sul disco attraverso il file system XFS che, essendo un journaled filesystem anch'esso, scriveva ulteriori metadati. Tutto questo processo comportava tre scritture: una per il dato raw, una per leveldb e una per XFS, le quali introducevano ognuna una latenza.
Questa tripla scrittura era parecchio sofferta in termini di latenza dagli hard disk: sia quelli più datati sia i più moderni SSD. Per ovviare a questo problema era best practice separare a livello di File Store, le scritture del dato raw su HDD o SSD, dalle scritture del metadato, tipicamente su NVME.
Ceph tuttavia rivoluziona questo processo con una seconda implementazione: BlueStore.
Questo nuovo concetto permette di evitare la tripla scrittura attraverso una nuova metodologia di scrittura del dato e dei metadati.
Il dato raw viene infatti scritto direttamente sul disco, senza passare dal filesystem xfs, già questo questo comporta un generale miglioramento delle latenze e permette di avvicinarti maggiormente al disco.
Il metadato invece cambia database, spostandosi su rocksDB, progetto di Facebook. In particolare RocksDB è un database più adatto all’utilizzo che fa ceph dei metadati. Inoltre, per ottimizzare al massimo la scrittura e la lettura di RocksDB su disco è stato poi sviluppato BlueFS ad hoc.
Grazie BlueStore si riducono in generale le latenze di scrittura e lettura del dato all'interno dello storage.
Come CloudFire ha ottimizzato il Cloud Storage Ceph
In CloudFire siamo passati interamente a BlueStore da qualche anno avendone apprezzato l’incremento di performance. Detto ciò non abbiamo solamente assecondato il cambiamento e adottato la tecnologia proposta da Ceph bensì abbiamo fatto di più. É proprio qui infatti che CloudFire ha deciso di fare la differenza: per raggiungere alle performance sufficienti per workload di livello Enterprise occorre di più.
Analisi storage Ceph iniziale
Analizzando i workload reali ed avviando benchmark su un cluster out-of-the-box abbiamo notato una notevole discrepanza tra le performance raw del disco rispetto al cluster Ceph, in particolare il sovraccarico di archiviazione dei metadati in RocksDB ha un enorme effetto sulle prestazioni. Ciò è particolarmente vero per piccole scritture casuali, in cui la parte raw degli oggetti può essere piccola quasi quanto i metadati.
Tutto ciò comporta quindi un problema, in quanto, se in un oggetto grande la latenza di recupero del metadato è trascurabile, in un’oggetto piccolo quanto il metadato questa latenza diventa considerevole e significativa.
Concretamente, sulle macchine virtuali che ospitano database, che effettuano letture e scritture di blocchi molto piccoli, questa latenza è molto sentita.
Progetto e soluzione
Le analisi dei workload hanno portato alla luce un grosso limite della tecnologia software defined storage. Aumentando la resilienza e l'affidabilità del dato, le performance erogate sono marginali rispetto al limite fisico degli storage nodes. La sfida per i nostri Cloud Engineer è stata quella di mettere in discussione tutte le scelte architetturali sia hardware che software, con l'obiettivo di soddisfare le aspettative dei nostri clienti.
Revisione architettura hardware
Il primo passo è stato rivedere l'architettura hardware (CPU, RAM, Disco e Network) per controllare che nessun componente fosse stato sottodimensionato rispetto alle specifiche di Ceph. Attenersi alle Best Practices dei progetti open source è sempre un must, tuttavia può succedere che la rapida evoluzione dei software possa cambiare qualche carta in tavola.
✅Il design realizzato si è dimostrato più che sufficiente per il workload, infatti ogni release di Ceph porta con se migliori performance mantenendo la medesima architettura hardware.
Revisione setting di Ceph
Considerata l'architettura hardware idonea, il passo successivo è stato lavorare sui settings di Ceph e capire il blocco logico legato alle latenze.
L'approccio "Community First" ci ha portato a condividere la problematica con tutti i membri e abbiamo riscontrato che la medesima richiesta era particolarmente gettonata tra tutti i Ceph Users. Tuttavia, come spesso succede in quasi la totalità delle problematiche, la risposta è sempre la stessa: "Dipende".
Ed è stato davvero così!
La chiave di lettura infine è stata nel lavorare attorno ai settaggi di Ceph.
Cambiando i settaggi di RocksDB infatti, abbiamo subito notato che le performance oscillavano tra scadenti ad eccezionali.
In effetti per come funziona l'algoritmo descritto in precedenza, si può astrarre Ceph come un contenitore di oggetti ed i relativi meta dati scritti in un Database. La scrittura di questi meta-dati è la priorità dell'algoritmo e per questo deve essere fatta nel minor tempo possibile. Un rallentamento di questa operazione fa aumentare in maniera esponenziale la coda con la lista delle operazioni successive e di conseguenza aumenta le latenze.
✅ Dimensionando RocksDB correttamente con l'architettura hardware ( CPU, RAM ed NVME ) ha portato finalmente ad esprimere il massimo delle performance dello storage Ceph , ridurre maggiormente la latenza mantenendo la stessa resilienza di una triplice copia dei dati in 3 datacenter differenti.
Il risultato: Storage Ceph ottimizzato
Per poter analizzare i risultati e fare un paragone è necessario avere un benchmark di riferimento. In generale per misurare le performance di uno storage viene utilizzata la scrittura 4kilobyte, ovvero il dato più piccolo scrivibile, e di conseguenza anche quello più sensibile alle latenze.
Prendendo come riferimento una scrittura di 4kb, si misurano quanti input-output avvengono in un secondo, misurate in IOPS. In altre parole, se il nostro storage è in grado di scrivere su un disco 1000 file di 4 kilobyte ciascuno, in un secondo, allora posso affermare che lo storage raggiunge i 1000 IOPS.
Siamo partiti misurando le performance del singolo disco. Questo dato, moltiplicato per i dischi utilizzati nel nostro storage ci da un’idea delle performance Raw teoriche massime raggiungibili. Ad esempio se ho 100 dischi da 1000 IOPS, il mio massimo teorico sarà di 100 000 IOPS (senza tenere conto delle repliche).
Dopodiché abbiamo misurato le performance dello storage installato ai valori di default. Questo dato era il 30% delle performance teoriche stimate. Ovviamente per noi questo non era soddisfacente e, attraverso le modifiche implementate, siamo riusciti a migliorare le performance del nostro storage Ceph raggiungendo risultati vicini al limite del teorico.
Sicuramente un risultato ottenuto con tanto lavoro sodo e studio che ci da orgoglio su ciò che stiamo implementando per offrire un servizio sempre più performante e di qualità.
Grazie per aver letto l’articolo fino alla fine e condivido l’invito a seguirci costantemente mentre cerchiamo di migliorare le prestazioni del nostro storage Ceph e molto altro.