Alla mia famiglia, a Teresa · Introduzione 1.1 Introduzione al cloud computing e problematiche di...
Transcript of Alla mia famiglia, a Teresa · Introduzione 1.1 Introduzione al cloud computing e problematiche di...
Scuola Politecnica e delle Scienze di Base Corso di Laurea Magistrale in Ingegneria Informatica Tesi di Laurea Magistrale in Impianti di Elaborazione
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Anno Accademico 2017/2018 relatori Ch.mo prof. Domenico Cotroneo Ch.mo prof. Roberto Natella correlatore Ing. Luigi De Simone candidato Alfonso Di Martino matr. M63000654
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Alla mia famiglia, a Teresa ...
ii
Abstract
Con la maturazione delle tecnologie di virtualizzazione, sia nella progettazione software
che nel supporto hardware, il cloud computing sta diventando sempre più una delle più
importanti piattaforme di calcolo. In aggiunta ai servizi offerti dai cloud pubblici, come
Amazon EC2, esiste una domanda sempre più elevata che va verso altri tipi di piatta-
forma cloud, in particolare cloud privati o ibridi. Questa richiesta fa nascere un nuovo
settore industriale, nel quale il consumatore è anche fornitore di servizi, quindi si estende
il dominio dei cloud provider anche ad organizzazioni di dimensioni differenti.
Sull’onda di questa richiesta sempre crescente, è diventato particolarmente importante
avere nella propria infrastruttura uno strato software, chiamato cloud management stack,
che funzioni come un sistema operativo cloud di alto livello, fondamentale per la gestione
delle risorse nelle piattaforme cloud. In tale contesto, OpenStack [16] rappresenta una
delle soluzioni più diffuse per quanto riguarda imprese/soggetti che hanno scelto di af-
fidarsi a progetti open source. OpenStack si compone di numerosi servizi comuni, per
esempio un servizio per le risorse di calcolo, un servizio per la rete, un servizio per la
gestione delle immagini, servizi per l’archiviazione persistente ed altri.
Questa tesi propone un approccio metodologico per la valutazione dell’affidabilità della
piattaforma di cloud computing OpenStack, riportando statistiche dettagliate sui risultati
ottenuti in seguito all’esecuzione di campagne di esperimenti di fault injection. In parti-
colare, gli aspetti che sono stati valutati riguardano la capacità del sistema di manifestare
l’occorrenza di un fallimento, lacune nell’attività di logging e la propagazione tempora-
le e spaziale dei fallimenti tra i diversi servizi che compongono il sistema. Per ognuno
iii
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
di questi aspetti, si è cercato di definire anche possibili strategie di miglioramento che
potrebbero essere implementate.
Nel capitolo 1 viene fornita una panoramica sul cloud computing, presentata l’architettura
di OpenStack e descritti i suoi componenti principali. Inoltre sono forniti anche i concetti
di base riguardanti le tecniche di fault injection e tecniche di affidabilità nel contesto di
sistemi cloud. Infine si definiscono le research questions individuate per la valutazione
dell’affidabilità di OpenStack.
Il capitolo 2 presenta in dettaglio l’approccio metodologico utilizzato per valutare l’affi-
dabilità del sistema target attraverso l’utilizzo di un tool di fault injection. In particolare
si presenta il workflow del tool di fault injection, il workload progettato, i log collezionati
e il processo di analisi.
Nel capitolo 3 sono riportate le informazioni sperimentali, riguardanti la configurazione
del testbed e le prime statistiche sulle campagne di fault injection eseguite.
Nel Capitolo 4, infine, si riportano i risultati sperimentali ottenuti.
iv
Indice
1 Introduzione 1
1.1 Introduzione al cloud computing e problematiche di affidabilità . . . . . . 1
1.2 Fault Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.1 Esperimenti di Fault Injection . . . . . . . . . . . . . . . . . . . 9
1.3 Tecniche per l’affidabilità di sistemi cloud . . . . . . . . . . . . . . . . . 11
1.3.1 Monitoraggio . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.2 Tolleranza ai guasti . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.3 Fault injection nel cloud computing . . . . . . . . . . . . . . . . 16
1.4 Research Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2 Metodologia proposta 23
2.1 Workflow e Tool di Fault Injection . . . . . . . . . . . . . . . . . . . . . 23
2.2 Workload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.3 Log collezionati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.3.1 Log del sistema target . . . . . . . . . . . . . . . . . . . . . . . 31
2.3.2 Log del workload . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.3.3 Log del tool di fault injection . . . . . . . . . . . . . . . . . . . . 33
2.4 Analisi dei log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
v
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
3 Informazioni Sperimentali 40
3.1 Testbed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.2 Punti di iniezione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4 Analisi dei risultati 49
4.1 Sintesi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.1.1 Classificazione in base al fallimento del Round . . . . . . . . . . 50
4.1.2 Classificazione in base al tipo di fallimento . . . . . . . . . . . . 52
4.1.3 Classificazione in base alla presenza di log con severity error . . . 55
4.2 RQ1 (Manifestazione) . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.3 RQ2 (Logging) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4.4 RQ3 (Propagazione) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Conclusioni 75
Ringraziamenti 78
Bibliografia 80
vi
Elenco delle figure
1.1.1 Architettura concettuale di OpenStack . . . . . . . . . . . . . . . . . . . 5
1.2.1 Patologia dei guasti. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.2 Schema concettuale di fault injection. . . . . . . . . . . . . . . . . . . . 10
1.3.1 Circuit breakers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.1.1 Workflow del tool di SFI. . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.1.2 Passi della fase di esecuzione di un esperimento. . . . . . . . . . . . . . . 27
2.3.1 Log collezionati durante l’esecuzione di un esperimento. . . . . . . . . . 31
2.3.2 Estratto output.log e error.log . . . . . . . . . . . . . . . . . . . . . . . . 33
2.4.1 Workflow dell’analisi dei log. . . . . . . . . . . . . . . . . . . . . . . . . 34
3.1.1 Configurazione dell’OpenStack Server. . . . . . . . . . . . . . . . . . . . 41
3.2.1 Piano di esperimenti di fault injection per il servizio OpenStack Nova.
Suddivisione per file di codice sorgente . . . . . . . . . . . . . . . . . . 44
3.2.2 Piano di esperimenti di fault injection per il servizio OpenStack Cinder.
Suddivisione per file di codice sorgente . . . . . . . . . . . . . . . . . . 45
3.2.3 Tipi di fault più comuni per il sottosistema OpenStack Nova. . . . . . . . 46
3.2.4 Tipi di fault più comuni per il sottosistema OpenStack Cinder. . . . . . . 47
4.1.1 Esperimenti di FI eseguiti per OpenStack Nova e OpenStack Cinder. . . . 50
4.1.2 OpenStack Nova - Classificazione in base al fallimento del Round. . . . . 51
vii
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
4.1.3 OpenStack Cinder - Classificazione in base al fallimento del Round. . . . 52
4.1.4 OpenStack Nova - Classificazione in base tipo di fallimento. . . . . . . . 53
4.1.5 OpenStack Cinder - Classificazione in base tipo di fallimento. . . . . . . 54
4.1.6 OpenStack Nova - Classificazione in base alla presenza di log ad alta
severità. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.1.7 OpenStack Cinder - Classificazione in base alla presenza di log ad alta
severità. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.2.1 OpenStack Nova - Tipi di Assertion Failure. . . . . . . . . . . . . . . . . 59
4.2.2 OpenStack Cinder - Tipi di Assertion Failure. . . . . . . . . . . . . . . . 60
4.2.3 OpenStack Nova - Tipi di API ERROR. . . . . . . . . . . . . . . . . . . 61
4.2.4 OpenStack Cinder - Tipi di API ERROR. . . . . . . . . . . . . . . . . . 62
4.2.5 OpenStack Nova/Cinder - Fallimenti totali registrarti. . . . . . . . . . . . 63
4.3.1 Esperimento 1 - Codice mutato. . . . . . . . . . . . . . . . . . . . . . . 65
4.3.2 Esperimento 2 - Codice mutato. . . . . . . . . . . . . . . . . . . . . . . 66
4.3.3 Esperimento 2 - Estratto Log. . . . . . . . . . . . . . . . . . . . . . . . . 67
4.3.4 Esperimento 2 - Estratto trigger.log. . . . . . . . . . . . . . . . . . . . . 67
4.4.1 OpenStack Nova - Propagazione temporale. . . . . . . . . . . . . . . . . 68
4.4.2 OpenStack Cinder - Propagazione temporale. . . . . . . . . . . . . . . . 69
4.4.3 OpenStack Nova - Propagazione spaziale dei fallimenti. . . . . . . . . . . 71
4.4.4 OpenStack Nova - Fallimenti persistenti. . . . . . . . . . . . . . . . . . . 73
viii
Elenco delle tabelle
2.1 Tipi di guasti supportati dal tool di Software Fault Injection . . . . . . . . 24
2.2 Classificazione degli esperimenti. . . . . . . . . . . . . . . . . . . . . . 39
3.1 File di codice sorgente con più punti di iniezione - OpenStack Nova. . . . 43
3.2 File di codice sorgente con più punti di iniezione - OpenStack Cinder. . . 46
3.3 Tipi di fault più comuni per il sottosistema OpenStack Nova. . . . . . . . 47
3.4 Tipi di fault più comuni per il sottosistema OpenStack Cinder. . . . . . . 47
3.5 Esperimenti di fault injection eseguiti. . . . . . . . . . . . . . . . . . . . 48
4.1 OpenStack Nova - Classificazione in base al fallimento del Round. . . . . 51
4.2 OpenStack Cinder - Classificazione in base al fallimento del Round. . . . 52
4.3 OpenStack Nova - Classificazione in base tipo di fallimento. . . . . . . . 53
4.4 OpenStack Cinder - Classificazione in base tipo di fallimento. . . . . . . 54
4.5 OpenStack Nova - Classificazione in base alla presenza di log ad alta
severità. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.6 OpenStack Cinder - Classificazione in base alla presenza di log ad alta
severità. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.7 OpenStack Nova - Tipi di Assertion Failure. . . . . . . . . . . . . . . . . 59
4.8 OpenStack Cinder - Tipi di Assertion Failure. . . . . . . . . . . . . . . . 60
4.9 OpenStack Nova - Tipi di API ERROR. . . . . . . . . . . . . . . . . . . 61
ix
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
4.10 OpenStack Cinder - Tipi di API ERROR. . . . . . . . . . . . . . . . . . 62
4.11 OpenStack Nova/Cinder - Fallimenti totali registrarti. . . . . . . . . . . . 63
4.12 Informazioni del FIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.13 Informazioni del FIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.14 OpenStack Nova - Propagazione temporale per tipi di fallimento. . . . . . 69
4.15 OpenStack Cinder - Propagazione temporale per tipi di fallimento. . . . . 70
4.16 OpenStack Nova - Propagazione spaziale dei fallimenti. . . . . . . . . . . 71
4.17 OpenStack Nova - Fallimenti persistenti. . . . . . . . . . . . . . . . . . . 72
x
Capitolo 1
Introduzione
1.1 Introduzione al cloud computing e problematiche di
affidabilità
Con i significativi progressi nel campo dell’Information and Communications Technology
(ICT) dell’ultimo mezzo secolo, vi è una visione sempre più percepita che il computing
sarà un giorno la quinta utility, dopo acqua, elettricità, gas e telefonia, ritenute essenziali
per le esigenze quotidiane della comunità generale. Per realizzare questa visione, sono
stati proposti numerosi paradigmi informatici, tra cui il cloud computing, definito come un
modello che abilita l’accesso via rete, in modo ubiquitario, conveniente e su richiesta ad
un insieme di condiviso di risorse configurabili (reti, server, sistemi di memorizzazione,
applicazioni e servizi) che possono essere rapidamente acquisite e rilasciate con minimo
sforzo o minima interazione con il fornitore del servizio [11].
Questo paradigma basato su un modello di business pay-per-use, ha portato alla proli-
ferazione di nuove Infrastrutture come Servizio (IaaS), come Google Compute Engine,
Microsoft Windows Azure e Amazon EC2, con conseguente passaggio al cloud di nume-
rose aziende che in questo modo evitano di dover costruire, gestire e manutenere propri
data center, abbattendo così l’investimento di capitale iniziale e costi di manutenzione nel
1
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
tempo. In tale contesto, è importante avere strumenti che permettano di creare e gesti-
re agevolmente la piattaforma cloud (e.g., aggiungere rapidamente nuove istanze, nuovi
volumi o ridimensionare le capacità delle risorse già allocate): parliamo di cloud manage-
ment stack (CMS), ossia uno stack di gestione del cloud che, come un sistema operativo di
alto livello, gestisce le risorse nelle piattaforme cloud tramite la collaborazione di servizi
distribuiti. Questi CMS sono sistemi distribuiti complessi e su larga scala che consento-
no l’orchestrazione di attività, tra cui spawn, cessazione, migrazione, ecc. di macchine
virtuali (VM).
Un esempio di cloud management stack è OpenStack [16], definito come un sistema ope-
rativo cloud che controlla vasti pool di risorse di elaborazione, di storage e di rete, il
tutto gestito tramite una dashboard che fornisce agli amministratori il controllo, e con-
sente agli utenti di fornire risorse attraverso un’interfaccia web. OpenStack è un software
open source, scritto in Python, quindi chiunque può accedere al codice e apportare mo-
difiche a seconda delle proprie esigenze, aggiungendo magari nuovi componenti/servizi.
Per questo motivo, la comunità OpenStack ha identificato dei componenti chiave che fan-
no parte del core di OpenStack e che vengono distribuiti come parte di qualsiasi sistema
OpenStack.
I principali servizi di OpenStack sono:
• Compute (Nova): è il componente principale di OpenStack, utilizzato per la di-
stribuzione e la gestione di un gran numero di macchine virtuali e altre istanze per
gestire attività di elaborazione. Le risorse di calcolo sono accessibili tramite API
dagli sviluppatori di applicazioni cloud e tramite interfaccia web dagli ammini-
stratori e utenti. Nova supporta varie tecnologie di virtualizzazione e permette di
scegliere tar diversi hypervisor, come KVM, Xen, etc.
• Block Storage (Cinder): fornisce uno storage persistente a livello di dispositivi a
blocchi per il loro utilizzo da parte delle istanze di Nova. Il sistema di storage a
blocchi gestisce la creazione, il collegamento e lo scollegamento dei dispositivi a
2
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
blocchi ai server. I volumi del block storage sono pienamente integrati con Nova e
con la Dashboard, permettendo agli utenti di gestire i loro dispositivi di storage.
• Networking (Neutron): sistema per la gestione delle reti e degli indirizzi IP. Neu-
tron assicura che la rete non sarà il collo di bottiglia o fattore limitante in un cloud
e offre agli utenti una reale gestione self-service anche delle loro configurazioni
di rete. Neutron gestisce gli indirizzi IP, consentendo l’assegnazione di indirizzi
IP statici dedicati oppure tramite DHCP. Fornisce differenti modelli di rete, tra cui
quelli standard come flat networks o VLAN per la separazione del traffico.
• Identity (Keystone): fornisce servizi di autenticazione e autorizzazione ad alto
livello per OpenStack. Supporta autenticazione basata su token e autorizzazione
utente-servizio (per esempio, elenco di utenti e permessi di utilizzo dei servizi for-
niti dal cloud). Ad esempio, una chiamata di autenticazione convalida le credenziali
dell’utente e del progetto con il servizio di identità. In caso di successo, creerà e
restituirà un token, che potrà essere utilizzato per l’accesso autorizzato agli altri
servizi di OpenStack fino alla sua scadenza.
• Object Storage (Swift): è un sistema di storage scalabile e ridondante. Gli oggetti
e i file sono memorizzati su diversi dischi, distribuiti su diversi server nel centro
di calcolo. OpenStack si fa carico di assicurare la replicazione e l’integrità dei
dati all’interno del cluster. Dato che OpenStack effettua le operazioni di replica e
distribuzione dei dati sulle differenti unità via software, si può utilizzare hardware
commerciale senza dover ricorrere a costose soluzioni proprietarie.
• Image Service (Glance): fornisce servizi di immagine a OpenStack. In questo
caso, "immagini" si riferisce a immagini (o copie virtuali) di dischi rigidi. Glance
consente di utilizzare queste immagini come modelli durante la distribuzione di
nuove istanze di macchine virtuali.
3
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
• Dashboard (Horizon): fornisce una interfaccia grafica, sia per gli amministratori
che per gli utenti, per l’accesso e la gestione delle risorse fornite dal cloud. Ho-
rizon può integrarsi con prodotti e servizi di terze parti utili per la fatturazione, il
monitoraggio e altri strumenti di gestione. Horizon è solo uno dei vari metodi con
cui si può interagire con le risorse fornite da OpenStack. Gli sviluppatori possono
automatizzare l’accesso o realizzare strumenti per la gestione delle risorse usando
la API native di OpenStack o la API per la compatibilità con EC2.
In figura 1.1.1 è riportata una vista concettuale dell’architettura di OpenStack, dalla quale
possiamo notare che:
1. ogni servizio del sistema (e.g., Nova, Glance, Neutron) è visto come un modulo
isolato, costituito da più componenti; per esempio, in Nova si possono notare nova-
api, nova-scheduler, nova-console, etc. In particolare, ogni servizio del sistema può
essere replicato e distribuito su nodi differenti con indirizzi IP differenti, mentre i
componenti di ogni servizio vengono eseguiti in processi indipendenti.
2. la comunicazione può avvenire attraverso chiamate REST tra i diversi servizi, men-
tre tra i processi interni del servizio la comunicazione avviene per mezzo di mes-
saggi RPC e data la possibilità di distribuzione su più nodi, un broker RabbitMQ si
occupa di instradare questi messaggi.
4
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figura 1.1.1: Architettura concettuale di OpenStack
L’infrastruttura di cloud computing si presenta come un complesso ecosistema, dove mol-
teplici attori ricoprono un ruolo fondamentale. Questo ecosistema è altamente distribuito,
costituito da componenti hardware e software eterogenei il più delle volte forniti da terze
parti, e ci si aspetta che fornisca servizi high-available richiesti parallelamente da milioni
di utenti [19].
In un contesto di sistemi così complessi i fallimenti sono inevitabili e dal punto di vista
dei fornitori di servizi (per esempio, operatori di telefonia che per ridurre i costi, time-to-
market, aumentare la gestibilità e fornire servizi innovativi, hanno abbracciato un nuovo
paradigma chiamato Network Function Virtualization (NFV) basato su virtualizzazione
e cloud computing), è fondamentale la disponibilità dei prodotti e l’affidabilità percepita
dagli utenti, in quanto (i) servizi percepiti inaffidabili vengono scartati dagli utenti e (ii)
i costi dei guasti di sistema possono essere enormi. Possibili cause di fallimenti possono
essere:
• Hardware Faults: l’utilizzo di componenti hardware definiti come Commercial Off-
The-Shelf (COTS) è una potenziale causa di fallimenti, in quanto non sono specifi-
catamente progettati per l’applicazione, che potrebbero richiedere specifici requisiti
di affidabilità; da questo punto di vista questi guasti potrebbero essere mascherati
5
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
utilizzando componenti hardware replicati o sfruttando la replicazione fornita dal
livello di virtualizzazione (per esempio replicare i dati su più dischi fisici ed esporre
un unico disco virtuale sempre affidabile).
• Software Faults: anche dal punto di vista dei componenti software vi è un (ri)utilizzo
di COTS a vari livelli dello stack di virtualizzazione (hypervisor, guest OSes, soft-
ware di gestione e orchestrazione, ecc...); questi componenti di terze parti, spes-
so non sono testati rigorosamente e vengono rilasciati ed utilizzati insieme ai loro
software bugs residui;
• Operator Faults: la complessità e l’elevata scala dell’infrastruttura di virtualizza-
zione (spesso si ha a che fare con migliaia di nodi e con stack hardware/software
abbastanza complessi), può portare gli operatori umani a commettere degli errori
durante la configurazione ed utilizzo del sistema. Questo espone l’infrastruttura ad
errori che si possono osservare all’atto della distribuzione e messa in esercizio.
Il problema di testare e validare l’infrastruttura di cloud computing diventa quindi una
grande sfida, in quanto l’infrastruttura di cloud computing è costituita da molti elementi
e come sopra menzionato le cause di fallimento possono essere di natura molto differen-
te, quindi diventa difficile comprendere come i vari elementi influiscano sull’affidabilità
dell’infrastruttura stessa o del servizio e comprendere come prevenire questi fallimenti.
1.2 Fault Injection
Nel contesto di scenari business o mission-critical, avere un’intensa attività di testing è
fondamentale per garantire che i nuovi sistemi e i meccanismi di fault-tolerance che essi
incorporano, si comportino come ci si aspetta. In tali contesti, garantire che il sistema si
comporti correttamente in presenza di guasti è un problema che richiede qualcosa in più
rispetto al tradizionale testing. Il processo di introduzione volontaria di guasti all’interno
del sistema con l’obiettivo di valutare il suo comportamento e misurare l’efficienza (in
6
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
termini di copertura e latenza) di meccanismi di fault-tolerant incorporati, è chiamato
fault injection.
Definiamo un guasto (fault) come la causa accertata o ipotizzata di un errore. I guasti
possono essere interni o esterni al sistema: la precedente presenza di una vulnerabilità,
per esempio un guasto interno che permette a un guasto esterno di danneggiare il sistema,
è necessaria affinché un guasto esterno possa causare un errore e conseguentemente il
manifestarsi di un fallimento. Un guasto è attivo quando causa un errore, altrimenti è
definito dormiente. Nella maggior parte dei casi, un guasto causa prima un errore nello
stato di servizio del componente, che è parte dello stato interno del sistema, mentre lo
stato esterno non è immediatamente influenzato.
Per questo motivo definiamo errore (error) la parte dello stato totale del sistema che può
portare al successivo fallimento del servizio. Se l’errore è opportunamente rilevato si
definisce detected, viceversa se l’errore esiste ma non è rilevato si parla di latent error.
Infine definiamo un fallimento (failure o service failure) un evento che si verifica quando
il servizio fornito devia dal servizio corretto. Un servizio fallisce perché non rispetta le
specifiche funzionali o perché questa specifica non descrive adeguatamente la funzione
del sistema. Un fallimento di servizio è una transizione dal servizio corretto a un servi-
zio errato. La deviazione dal servizio corretto può assumere forme diverse che vengono
chiamate modalità di fallimento del servizio (service failure mode) e sono classificate
in base alla severità del fallimento [2].
Fault, error e failure sono legati da una precisa relazione definita in letteratura come
patologia del guasto [2] e schematizzata in 1.2.1:
7
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figura 1.2.1: Patologia dei guasti.
Nel tempo si è avuta un’evoluzione degli approcci di fault injection che ha seguito l’evolu-
zione dei sistemi digitali. Infatti inizialmente la tecnica prevedeva di iniettare fisicamente
guasti nel sistema hardware target, per esempio usando radiazioni e disturbi di alimenta-
zione, assumendo un semplice modello di guasto hardware come bit-flip o bit stuck-at.
Con l’aumento di complessità dell’hardware, tale approccio è risultato essere sempre più
difficile da applicare e si sono sviluppati nuovi approcci basati su emulazione a runtime
di guasti hardware attraverso software. Nascono così nuovi strumenti di fault injection
chiamati Software-Implemented Fault Injection - SWIFI, utilizzati per iniettare errori di-
rettamente nello stato del programma, per esempio alterando il contenuto di data register
e address register, stack o memoria heap, oppure agendo a livello di codice del program-
ma, per esempio nell’area di memoria dove è memorizzato il codice, prima o durante
l’esecuzione.
Con l’incremento sempre più massiccio della componete software nei sistemi moderni,
un fault model puramente hardware non basta ed è necessario avere degli strumenti che
permettano di emulare l’effetto di un guasto software reale, per esempio bugs. Nasce
l’approccio di Software Fault Injection - SFI, che consiste nell’introduzione di piccoli
cambiamenti nel codice del sistema target, creando più versioni dello stesso programma
(per esempio si inietta un guasto per volta). L’utilizzo di SFI è raccomandato da mol-
ti standard di sicurezza, come lo standard ISO 26262 per l’automotive safety [8], che
specifica i requisiti per lo sviluppo del prodotto a livello software per applicazioni auto-
mobilistiche, prescrivendo la corruzione dei componenti software per la valutazione dei
8
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
meccanismi di rilevamento e gestione degli errori e lo standard NASA 8719.13B per la
software safety [12], che raccomanda l’iniezione di guasti per valutare il comportamento
del sistema in presenza di software off-the-shelf difettoso.
1.2.1 Esperimenti di Fault Injection
Gli esperimenti di fault injection seguono lo schema comune presentato in [7] e mostrato
in figura 1.2.2. Tipicamente l’ambiente di fault injection consiste di un sistema target più
un fault injector, fault library, workload generator, workload library, controller, monitor,
data collector, and data analyzer.
In particolare, l’injector si occupa di iniettare i guasti nel sistema target (faultload) mentre
il load generator esercita il sistema inviando gli input (workload) che saranno elaborati
durante l’esperimento di fault injection (per esempio applicazioni, benchmarks o wor-
kload sintetici). In genere faultload e workload sono specificati dal tester attraverso la
definizione di una libreria, workload library o faultload library, oppure tramite la defini-
zione di regole per generare input e guasti. Il monitor tiene traccia dell’esecuzione dei
comandi e avvia la raccolta dei dati grezzi quando è necessario (letture o misurazioni),
necessari per valutare l’effetto dei guasti iniettati. I dati sono raccolti online dal data
collector mentre il data analyzer si occuperà di elaborare e analizzare i dati anche offline.
La scelta delle letture dipende dal sistema sotto analisi e dalle proprietà che vogliono
essere valutate, per esempio messaggi inviati agli utenti o ad altri sistemi nel caso in cui
voglio valutare l’output del sistema, oppure contenuto di aree specifiche di memoria se
voglio valutare lo stato interno del sistema. E’ importante scegliere le letture, in quanto
queste portano l’informazione che aiuterà il tester a capire se il sistema ha tollerato il
guasto oppure è fallito. In genere le letture di un esperimento con iniezione vengono
confrontate con quelle registrate da un esperimento senza guasto (fault-free experiments
o golden runs).
Infine il controller coordina tutte le entità sopra descritte ed è responsabile di iterare gli
9
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
esperimenti, che compongono la campagna di fault injection e di archiviare i risultati che
saranno poi utilizzati nelle analisi successive.
Figura 1.2.2: Schema concettuale di fault injection.
Inizialmente si presume che il sistema sia in uno stato corretto, viene iniettato il guasto e
avviato il workload. Si possono verificare due casi :
1. il guasto non viene attivato e rimane latente, quindi non si osservano fallimenti e
dopo lo scadere di un timeout l’esperimento è terminato;
2. il guasto viene attivato e diventa un errore, che può:
• propagarsi, corrompendo altre parti dello stato del sistema fino a quando il
sistema non esibisce un fallimento;
• rimanere latente nel sistema;
• essere mascherato da meccanismi di fault-tolerance;
Poiché in genere solo in una minima parte degli esperimenti di fault injection si osserva
l’attivazione di un guasto, per accelerare il processo di testing e renderlo più efficiente
si usa l’approccio SWIFI, con il quale si emula l’effetto di guasti hardware (per esempio
guasti di memoria, CPU, disco) andando a corrompere lo stato del software.
10
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
1.3 Tecniche per l’affidabilità di sistemi cloud
In questa sezione viene fornita una panoramica sulle tecniche e tecnologie legate all’affi-
dabilità nel contesto dei sistemi cloud. In 1.3.1, si discute dell’utilità e della necessità di
meccanismi di monitoraggio (e.g., per capire come si sta comportando il sistema, utiliz-
zo delle risorse, qualità del servizio fornito e occorrenza di fallimenti), riportando anche
esempi di tecnologie implementate in OpenStack (e.g., Ceilometer, servizio di misura-
zione e raccolta di dati) e affermate nell’ambito del monitoraggio dei sistemi distribuiti
complessi (e.g., Zipkin). In 1.3.2 si presentano alcuni esempi di pattern architetturali
per l’affidabilità in ambito di applicazioni cloud-native, riportando anche delle soluzioni
implementate in OpenStack (e.g., meccanismi di retry e timeout, architettura modulare
organizzata in servizi e scambio di messaggi). Infine, in 1.3.3 si effettua una panorami-
ca sugli approcci di fault injection e tool/framework di fault injection implementati nel
contesto del cloud computing (e.g., a livello di VMs, Hypervisor e Cloud Management).
1.3.1 Monitoraggio
Una delle caratteristiche essenziali del cloud computing è il Servizio Misurato, in quanto
i sistemi cloud controllano e ottimizzano automaticamente l’utilizzo delle risorse sfrut-
tando una capacità di misurazione ad un livello di astrazione appropriato per il tipo di
servizio, per esempio archiviazione, elaborazione e larghezza di banda. L’utilizzo delle
risorse può essere monitorato, controllato e segnalato, garantendo trasparenza sia per il
fornitore che per il consumatore del servizio utilizzato [11].
I meccanismi di monitoraggio del servizio sono responsabili della raccolta e segnalazione
delle misurazioni di Key Quality Indicators (KQIs) e Key Performance Indicators (KPIs),
che forniscono le basi per il servizio misurato e servono come input per le politiche uti-
lizzate per aiutare a gestire la capacità e misurare l’affidabilità del servizio. Sebbene il
monitoraggio del servizio non influisca direttamente sulla sua affidabilità e disponibilità,
esso è un componente importante per la misurazione e la segnalazione sull’affidabilità del
11
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
sistema per garantire la conformità agli SLAs (Service Level Agreements - strumenti con-
trattuali attraverso i quali si definiscono le metriche di servizio che devono essere rispet-
tate da un fornitore di servizi). Il monitoraggio del servizio può essere abbinato a soglie
per innescare l’aumento di istanze o risorse applicative che impatteranno positivamen-
te sulla disponibilità (soddisfacendo esigenze di capacità più elevate) e sull’affidabilità
(assicurando che ci siano sufficienti risorse per gestire le richieste) del sistema [4].
Sono necessarie attività di monitoraggio precise e dettagliate, ma allo stesso tempo poco
intrusive, per gestire in modo efficiente la piattaforma e gestirne la crescente complessità
[1], e considerati i requisiti di SLA ci sono molti KPI che indicano come il servizio sta
operando secondo determinati parametri [5].
Al fine di valutare il grado di affidabilità del sistema non basta considerare solo le metriche
dettagliate raccolte già dai servizi di rete (come round trip time, tempo di risposta, tasso
di perdita dei pacchetti), servizi di storage (come throughput, spazio libero su disco) e
servizi di calcolo (come utilizzo CPU, consumo di memoria), ma sono necessarie misure
a un livello più fine, per monitorare il comportamento di ogni singolo componente, al
fine di individuare gli effetti dei guasti durante gli esperimenti e le metriche relative alla
propagazione dell’errore. Inoltre, è importante prendere in considerazione misure relative
alla tolleranza ai guasti, come la copertura e la latenza del rilevamento degli errori, i
tempi di migrazione e checkpoint, ecc. In tale scenario possiamo considerare due tipi
di misure: misure a livello di sistema, importanti nella prospettiva della validazione e per
soddisfare i requisiti specifici degli SLA e misure interne, relative ai componenti del cloud
stack, necessarie per analizzare e testare in profondità il sistema al fine di migliorarne la
progettazione e configurazione [19].
OpenStack fornisce un servizio per il monitoraggio, al pari dei servizi di calcolo come
Nova e persistenza come Cinder, chiamato Ceilometer [15], il cui scopo è raccogliere,
normalizzare e trasformare efficientemente i dati prodotti dai servizi OpenStack. Ceilo-
meter è uno dei moduli più interessanti per i service provider, in quanto rende disponi-
bili tutti i contatori utilizzabili per misurare il costo delle singole applicazioni/progetti
12
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
e alimentare dei sistemi di fatturazione a consumo. Il modulo può essere impostato per
effettuare azioni automatiche (e.g., scale-out) sulla base delle misurazioni rilevate.
Un esempio di strumento di monitoraggio in ambito di sistemi distribuiti è Zipkin [21],
che rappresenta un sistema di tracciamento distribuito che può essere utilizzato per racco-
gliere i dati temporali per tutti i servizi coinvolti nella gestione di una chiamata API. Que-
sti dati possono essere utilizzati per la risoluzione di problemi all’interno del sistema (e.g.,
per ridurre la latenza di alcune operazioni). Zipkin prevede di strumentare l’applicazione
target utilizzando delle librerie (esistono librerie già sviluppate per molte piattaforme),
in questo modo i componenti dell’applicazione strumentata (chiamati Reporter), possono
inviare i dati di tracciamento ai Collector di Zipkin, che li memorizza e successivamente
li può fornire attraverso un’interfaccia grafica.
1.3.2 Tolleranza ai guasti
In architetture applicative cloud-native o in genere nei sistemi distribuiti, si possono avere
potenzialmente più modi di fallimento rispetto a sistemi monolitici. Poiché ogni richiesta
in entrata potenzialmente può riferirsi a decine o centinaia di servizi diversi, qualche
fallimento in una o più di queste dipendenze è praticamente garantito. In questi scenari è
fondamentale garantire punti di accesso isolati ai servizi, bloccando i guasti in cascata su
di essi, migliorando la resilienza complessiva del sistema [13].
In [20] sono presentati due esempi di pattern architetturali per l’affidabilità:
1. Interruttori automatici (Circuit Breakers): isolano un servizio dalle sue dipen-
denze impedendo chiamate remote quando si determina che una dipendenza è mal-
sana (e.g., le risposte sono in timeout a causa di un’elevata latenza o producono
un’eccezione in seguito al tentativo di esecuzione della richiesta), così da evitare
l’accumulo di richieste che porterebbero a un rapido esaurimento del pool di thread
per le richieste (per esempio se consideriamo App Container come Tomcat, Jetty,
etc.). Questi interruttori sono implementati come macchine a stati e si comportano
13
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
come in figura 1.3.1. Quando il circuito è nello stato chiuso, le chiamate vengono
semplicemente passate alla dipendenza. Se una di queste fallisce, viene conteggia-
to un fallimento e quando tale conteggio raggiunge una soglia specificata entro un
certo periodo di tempo, il circuito scatta nello stato aperto e le chiamate fallisco-
no immediatamente. Dopo un periodo predeterminato, il circuito passa in un stato
semiaperto, le chiamate vengono effettuate e a seconda dell’esito della chiamata si
passa allo stato aperto (se fallisce) o chiuso (se riesce).
Figura 1.3.1: Circuit breakers.
2. Paratie stagne (Bulkheads): suddividono un servizio in modo da confinare gli erro-
ri e prevenire che l’intero servizio non funzioni a causa di un fallimento in un’area.
I sistemi software possono usare le paratie in molti modi, per esempio la suddivi-
sione in microservizi, esecuzione in parallelo del lavoro su diversi pool di thread o
il partizionamento dei processi applicativi in contenitori Linux.
Queste soluzioni architetturali, insieme a molte altre, sono state sviluppate da Netflix e
fornite in Hystrix [13], una libreria dedicata per la tolleranza ai guasti nel contesto di
applicazione cloud.
OpenStack prevede dei meccanismi concettualmente simili a questi sopra descritti, per
esempio:
• RetryFilter è implementato in Compute, insieme ad altri filtri di calcolo, e filtra gli
host per i quali lo scheduler ha già tentato una volta la pianificazione di un’azio-
ne da compiere (e.g., lo scheduler seleziona un host per rispondere a una richiesta
14
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
di servizio come la creazione di un’istanza e l’host non risponde alla richiesta).
Impostando un valore di soglia max_attempts=3, sarà generata un’eccezione Ma-
xRetriesExceeded nel caso in cui la pianificazione fallisce ripetutamente per l’host
selezionato, il quale non sarà più coinvolto in tentativi di pianificazione (RetryFilter
escluderà questo host);
• l’architettura stessa di OpenStack consiste di diversi moduli indipendenti chiamati
servizi (come mostrato in figura 1.1.1), che vengono distribuiti su nodi differenti
con indirizzi IP distinti, a formare così un complesso sistema distribuito con com-
ponenti disaccoppiati. Le comunicazioni inter-servizio avvengono tramite chiamate
REST e per ogni servizio è implementato un client HTTP per l’accesso alle sue API
REST. Inoltre, ogni servizio è costituito da diversi processi (e.g., OpenStack Nova
ha Conductor, Scheduler, Api, etc.), distribuiti e replicati anche su server differenti.
Le comunicazioni intra-servizio avvengono esclusivamente tramite messaggi RPC,
instradati su più nodi attraverso un broker RabbitMQ (quindi meccanismo a code
di messaggi). Questo favorisce sicuramente il disaccoppiamento (e.g., il client non
deve sapere dove si trova il riferimento del servente), possibilità di bilanciamento
delle chiamate remote (e.g., se sono presenti più serventi, la chiamata arriva al pri-
mo disponibile) e la comunicazione è asincrona (e.g., il client non ha bisogno che
il servente venga eseguito contemporaneamente alla chiamata remota).
Questi riportati sono solo un piccolissimo esempio dei possibili meccanismi e pattern per
l’affidabilità (per esempio, potremmo aggiungere ancora algoritmi tolleranti ai guasti di
consenso o di elezione, sempre nell’ottica di sistemi distribuiti, scambio di messaggi e
replicazione). Nel corso del lavoro, con l’iniezione di guasti nel software di OpenStack,
si proverà a dare una valutazione su questi ed altri meccanismi di tolleranza ai guasti
(e.g., utilizzo di timeout per valutare il fallimento di azioni generiche, come build, reboot
o delete di un’istanza), ovviamente nel contesto di OpenStack.
15
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
1.3.3 Fault injection nel cloud computing
Il concetto di cloud computing è strettamente legato a quello di virtualizzazione: infatti
questa la tecnologia è un “abilitatore” del cloud computing, in quanto “de facto” quasi
tutte le infrastrutture di cloud sono costruite utilizzando tecnologie di virtualizzazione.
La virtualizzazione consente l’astrazione delle risorse fisiche, come CPU, dispositivi di
rete o di memorizzazione, al fine di condividerle e fornirle come risorse. Il software di
virtualizzazione conosciuto come Hypervisor, è utilizzato per eseguire una o più macchi-
ne virtuali (che rappresentano l’astrazione software di una macchina fisica) su un’unica
macchina fisica, gestendo e sincronizzando l’accesso alle risorse della macchina fisica
quali CPU, memoria e dispositivi di I/O.
Per valutare l’affidabilità di sistemi cloud è necessario valutare l’affidabilità dell’inte-
ro ambiente di virtualizzazione, in particolare a livello di VMs, Hypervisor e Cloud
Management Stack che orchestra il tutto.
Fault Injection Testing di Macchine Virtuali si focalizza sul software utente e sistema
operativo in esecuzione sulle macchine virtuali. Lo scopo è quello di evidenziare proble-
matiche di affidabilità attraverso guasti hardware, per esempio modificando device virtuali
come hard disk e network controller o manomettendo lo stato della CPU o memoria. Sono
previste anche iniezioni di bug software a livello di sistema operativo mediante corruzione
del codice sorgente in memoria. D-Cloud [3] e DS-Bench Toolset [6] sono due esempi di
strumenti che adottano virtualizzazione per l’esecuzione di fault injection testing. Il pri-
mo effettua fault injection simulando la corruzione di dati nei device emulati (per esempio
corruzione di un settore del disco) oppure simulando condizioni di non risposta o lentezza
per hard disk o dispositivi di rete. Il secondo calcola metriche di affidabilità generali del
sistema sotto test attraverso l’iniezione di carichi anomali.
Fault Injection Testing di Hypervisor si focalizza sul testing dello strato software respon-
sabile dell’astrazione e distribuzione delle risorse di calcolo tra più VMs. Lo scopo è va-
lutare l’affidabilità attraverso l’iniezione di soft faults, performance faults o maintenance
16
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
faults. CloudVal [17] è un framework che supporta questo tipo di fault injection in KVM
e Xen hypervisor al fine di valutare l’isolamento guest/host delle VMs, il comportamento
dell’hypervisor e il livello di manutenibilità.
Fault Injection Testing di Cloud Management Stack si focalizza sul testing dei servizi
distribuiti responsabili della creazione e gestione di una piattaforma cloud. In particolare
questi servizi si occupano di istanziare VMs su hypervisor, migrare VMs, creare e can-
cellare VMs, comunicazione di rete e gestione volumi. Inoltre, a causa di piattaforme
hardware inaffidabili, il cloud management stack è anche responsabile di fornire proto-
colli per il recupero da vari fallimenti hardware quali arresti anomali, errori del disco e
di rete. In [10] è presentato uno studio sistematico sulla resilienza di OpenStack, uno dei
più importanti software di cloud computing open source. Il framework proposto inietta
guasti di rete mirando alle comunicazioni tra i servizi di calcolo, immagine, identità, da-
tabase, hypervisor e messaggistica. Gli autori valutano il framework su due versioni di
OpenStack, identificando bug come timeout nella comunicazione tra servizio o mancanze
nel controllo periodico della vitalità del servizio. PreFail [9] segue una tendenza recente
nella ricerca su fault injection basata su iniezioni multiple di guasti durante lo stesso espe-
rimento. Le iniezioni multiple sono motivate dall’osservazione che, sebbene l’occorrenza
di più guasti è rara, trascurare questa eventualità durante lo sviluppo e il testing rendereb-
be il sistema meno tollerante se non addirittura incapace di tollerare l’occorrenza di guasti
multipli.
In un’infrastruttura cloud possono occorrere fallimenti di diversi tipi, sia dovuti a soft-
ware bug che a fallimenti hardware, in quanto anche avendo a disposizione l’hardware
più costoso, questo prima o poi fallirà. I dischi possono fallire, la rete può andare giù o
un’improvvisa ondata di traffico può sovraccaricare un componente funzionante, provo-
cando interruzioni o altri comportamenti indesiderati. Non è possibile prevenire tutte le
possibili modalità di fallimento ma si possono identificare molti dei punti deboli del siste-
ma e in questo caso sistemarli. Chaos Engineering è la disciplina della sperimentazione
su un sistema distribuito al fine di aumentare la fiducia nella capacità del sistema di resi-
17
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
stere a condizioni turbolente quando è in esercizio [18]. Uno dei principi dell’ingegneria
del caos è sperimentare direttamente sul sistema in produzione, in quanto questo ci da
un’idea del traffico reale e del sistema reale. Netflix ha sviluppato The Simian Army [14],
costituito da una serie di strumenti chiamati scimmie, che inducono vari tipi di fallimenti
o rilevano anomalie all’interno dell’infrastruttura. Tra queste, quelle ad oggi sviluppate
sono:
• Chaos Monkey, servizio che disabilita casualmente delle istanze (per esempio mac-
chine virtuali), con lo scopo di valutare e nel caso costruire meccanismi di ripristino
automatici;
• Janitor Monkey, servizio che rileva e ripulisce risorse inutilizzate;
• Conformity Monkey, servizio che rileva istanze non conformi alle migliori pratiche,
per esempio non appartengono a un gruppo con ridimensionamento automatico e
questo potrebbe essere un problema in attesa di verificarsi;
Altre scimmie in progettazione sono: Chaos Gorilla e Chaos Kong, che sullo stesso prin-
cipio di Chaos Monkey terminano istanze, però nel primo caso la terminazione è estesa
a un’intera zona di disponibilità (AZ) o intera regione nel secondo caso. Latency Mon-
key che consente di iniettare errori che simulano istanze parzialmente sane, per esempio
introducendo un ritardo artificiale a livello di comunicazione RESTful client-server per
simulare il degrado del servizio, il tempo di inattività del nodo o anche i tempi di inattività
del servizio.
1.4 Research Questions
Come discusso in precedenza, la fault injection prevede l’introduzione deliberata di guasti
in un sistema al fine di valutare l’impatto di questi guasti sul comportamento del sistema e
le sue proprietà di tolleranza. La Software Fault Injection (SFI) è una forma innovativa di
fault injection che si focalizza sull’iniezione di guasti nei componenti software (software
18
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
faults o software bugs), per esempio bugs di programmazione che si verificano durante il
rilascio, l’aggiornamento o la configurazione del software, al fine di emulare guasti che il
componente potrebbe sperimentare durante il funzionamento.
Nell’ottica di sistemi distribuiti di grandi dimensioni, costituiti da un elevato numero di
componenti, l’idea generale della SFI è simulare software faults in uno di questi com-
ponenti (chiamato componente target) e valutare la fault-tolerance del sistema nel suo
insieme.
In questa tesi si presenta una metodologia di Software Fault Injection basata su intro-
duzione di software bugs tramite mutazione del codice sorgente del componente target,
ponendo particolare enfasi sull’analisi dei risultati ottenuti a valle di varie campagne di
esperimenti effettuate su OpenStack. E’ importante notare che il focus non è posto sul fal-
limento del componente iniettato (il che potrebbe essere ovvio date che il guasto è stato
iniettato lì), ma su come l’iniezione del guasto impatta sul resto del sistema.
In quest’ottica si cerca di dare risposta a una serie di research questions che sono di
seguito descritte:
1. In presenza di un fallimento di uno o più componenti, il sistema è capace di di-
chiararsi fallito nel caso in cui non riesce a portare a termine con successo una
richiesta? Per esempio, consideriamo una richiesta da parte dell’utente della crea-
zione di una VM o di un volume. In condizioni di normale funzionamento ci si
aspetta che la richiesta sia accolta dal sistema, elaborata (tramite la collaborazione
di più componenti/servizi che compongono il sistema) e si concluda con l’effettiva
creazione della risorsa oggetto della richiesta o, in caso di fallimento (e.g., esem-
pio esaurimento delle risorse o condizioni di errore dei componenti interni), questo
sia esplicitamente notificato all’utente, per esempio con un messaggio di errore o
un codice di ritorno rappresentativo del problema. Ci possono essere casi in cui
il sistema non si dichiara fallito (e.g., la creazione della VM viene avviata ma il
suo stato resta inconsistente, impedendole di diventare disponibile oppure il servi-
zio responsabile è in stallo) e questo può essere dannoso per la progettazione di
19
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
infrastrutture affidabili. Nel corso di questa tesi, verrà analizzato questo aspetto per
valutare l’affidabilità di OpenStack, al fine di evidenziare lacune nei meccanismi
di failure detection o reporting in generale, come per esempio mancanza di check
periodici sulla vitalità dei servizi o su stalli del client durante la chiamata all’API
OpenStack.
2. In presenza di un fallimento di uno o più componenti, i meccanismi di logging im-
plementati riescono a rilevarne l’occorrenza mediante messaggi ad alta severità?
I log sono una risorsa molto preziosa per gli sviluppatori e amministratori del siste-
ma, in quanto dalla loro analisi si possono identificare i componenti maggiormente
sottoposti a stress, quelli più soggetti a malfunzionamenti e in generale il compor-
tamento e lo stato corrente del sistema. Ci possono essere casi in cui l’utente (o il
workload in esecuzione) riscontra un fallimento API (e.g., durante la creazione e
configurazione di nuove istanze su OpenStack si ha uno stallo), ma lato OpenStack
il fallimento percepito dall’utente non viene rilevato, in quanto il sottosistema in-
teressato (e.g., OpenStack Nova) non registra alcun log ad alta severità. Questo
è un problema per gli amministratori di sistema ed eventuali strumenti automatici
di recupero, in quanto l’assenza di segnalazioni rende difficile individuare la cau-
sa principale del problema e avviare opportune e tempestive azioni di ripristino
dal fallimento. Al fine di migliorare l’affidabilità di OpenStack, in questo lavoro
analizzeremo i casi in cui si riscontrano lacune nell’attività di logging, così da in-
dirizzare gli sviluppatori nelle azioni migliorative (e.g., migliorare la gestione delle
eccezioni) e gli amministratori nelle azioni di configurazione (e.g., meccanismi di
base forniti ma che devono essere abilitati o regolati).
3. In presenza di un fallimento di uno o più componenti, i meccanismi di fault-tolerance
implementati riescono ad arginare l’effetto dei guasti nel sistema, sia in termini di
propagazione temporale che di propagazione spaziale? Valutare il modo in cui
l’attivazione di un guasto impatta sul comportamento del sistema target è impor-
20
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
tante per indirizzare l’analisi e il miglioramento dei meccanismi di fault-tolerance.
In particolare, è importante identificare i casi in cui una condizione di errore nello
stato del sistema si protrae per un lungo periodo di tempo, in quanto questo po-
trebbe amplificarne gli effetti sulle altre parti del sistema e sugli utenti. Analizzare
questi casi di propagazione temporale è utile per fornire agli sviluppatori le moti-
vazioni e le informazioni necessarie per intervenire, magari introducendo ulteriori
verifiche degli errori all’interno del proprio sistema e ottenere un comportamento
fail-stop (ovvero, il sistema si arresta non appena si verifica un errore, al fine di
evitare conseguenze peggiori). In alcuni casi, però, a un comportamento fail fast,
quindi generazione di un errore immediato e blocco dell’applicazione nel caso in
cui una richiesta non venga soddisfatta (e.g., la VM o il volume non vengono creati
o vengono etichettati in uno stato di errore), è preferibile una risposta in una moda-
lità di fallback per ridurre l’impatto degli errori sugli utenti. In tal senso, approcci
possibili fanno uso di cache (per recuperare i dati da cache locali o remote, anche
se obsoleti), eventuale coerenza (e.g., le scritture in coda diventano persistenti non
appena il componente ritorna disponibile), dati di stub (e.g., ripristino a valori pre-
definiti quando non è possibile recuperare le opzioni personalizzate), risposta file
silent (e.g., ritorna una lista nulla o vuota che le interfacce utente possono ignorare).
Un altro aspetto importante da valutare riguarda la propagazione spaziale, ossia la
possibilità che l’errore si propaghi attraverso diverse parti del sistema target, gene-
rando fallimenti a cascata dei componenti del sistema. Avere un tasso di propaga-
zione basso è una proprietà chiave da assicurare, in quanto permette di confinare gli
effetti dell’errore ai soli componenti difettosi e limitare il rischio di ulteriori danni
al resto del sistema, che porterebbero ad azioni di recupero più complesse e costose
(e.g., riavvio di molti servizi/componenti o ripristino totale dello stato del sistema).
Analizzare questi casi è importante, perché identificare l’eventuale catena di falli-
menti significa identificare i punti deboli dove intervenire, magari con l’aggiunta
di meccanismi di gestione degli errori per impedire la propagazione dei fallimenti
21
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
tra i componenti (e.g., aggiunta di gestori di eccezioni per gestire le eccezioni da
un sottosistema difettoso). In questa tesi si effettueranno degli esperimenti di fault
injection su OpenStack, al fine di portare alla luce eventuali fenomeni di propaga-
zione temporale (e.g., lunga latenza dall’istante di iniezione/attivazione del guasto
all’istante di rilevamento con log ad alta severità o fallimento lato utente) e feno-
meni di propagazione spaziale (e.g., il guasto iniettato nel sottosistema nova-api
causa un fallimento a cascata nel sottosistema nova-compute), così da indirizza-
re gli sviluppatori in azioni migliorative con lo scopo di rendere OpenStack più
robusto.
22
Capitolo 2
Metodologia proposta
In questo capitolo si presenta l’approccio metodologico utilizzato per la valutazione del-
la dependability della piattaforma OpenStack. Lo scopo dello studio è quello di fornire
delle risposte alle research questions definite in 1.4, attraverso l’utilizzo di un tool di fault
injection su un’installazione OpenStack all’interno di una macchina virtuale (chiamata
OpenStack Server), raccogliendo informazioni (log) sul comportamento del sistema du-
rante gli esperimenti di fault injection. Le risposte alle research questions saranno date a
valle dell’analisi dei log prodotti dal tool e da OpenStack.
In particolare, si presenta in dettaglio il tool di fault injection utilizzato e il suo workflow
2.1, mentre in 2.2 si discute del workload progettato. In 2.3 è fornita una panoramica sui
log prodotti dal tool e da OpenStack. Infine in 2.4 viene presentato il workflow di analisi
progettato.
2.1 Workflow e Tool di Fault Injection
La metodologia proposta prevede di eseguire una campagna di esperimenti sul sottosi-
stema di interesse (e.g., OpenStack Nova, OpenStack Cinder, etc.) e successivamente
analizzare i log raccolti per ogni esperimento, al fine di trarre delle statistiche globali
(e.g., numero di faults iniettati, esperimenti con attivazione del fault iniettato, esperimenti
23
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
che hanno esibito o meno un fallimento, etc.) e informazioni che saranno utili per l’analisi
delle research questions.
Per l’esecuzione della campagna di esperimenti, si utilizza un tool di Software Fault Injec-
tion sviluppato dal gruppo di ricerca DESSERT presso l’Università degli Studi di Napoli
Federico II.
Il tool è pensato per iniettare guasti software che tipicamente riguardano errori comuni di
programmazione, per esempio nell’utilizzo di API, gestione delle risorse, flusso di con-
trollo o gestione delle eccezioni. Infatti, uno dei criteri utilizzati per definire parte dei tipi
di guasti supportati dal tool, è stato analizzare i bug più frequenti e con alta severità ripor-
tati sul Launchpad1 (https://launchpad.net/openstack) del progetto OpenStack.
A questi sono stati anche aggiunti tipi di guasti generici per software Python, ad esempio
OS (e.g., fork, system, etc.), DISK (e.g., open, seek, next, etc.), e NET (e.g., socket, close,
bind, etc.). La tabella 2.1 riassume le principali classi di guasti supportate dal tool e una
breve descrizione per ognuna di esse:
Fault Type DescrizioneWRONG_PARAMETERS Corruzione del parametro passato alla funzione (strin, int, dict).
WRONG_RETURN_VALUE Corruzione il valore di ritorno dalla funzione (string, int, dict).MISSING_FUNCTION_CALL Omissione della chiamata a funzione.
MISSING_PARAMETERS Omissione del parametro (string, int, dict) nella funzione chiamata.THROW EXCEPTION Sostituisce la chiamata a funzione sollevando un’eccezione.
Tabella 2.1: Tipi di guasti supportati dal tool di Software Fault Injection
Il tool inietta questi tipi di fault in diverse aree del software, per esempio nelle API che
gestiscono le istanze o per i volumi, nelle chiamate RPC, a livello di database, di siste-
ma e di rete. I tipi di fault definiti sono generici e si specializzano a seconda del punto
di iniezione, infatti possono essere relativi al codice di OpenStack (e.g., OPENSTACK
MISSING PARAMETERS IMAGE), chiamate a metodi di archiviazione (e.g., DISKIO
MISSING FUNCTION CALL OPEN), chiamate a metodi di rete (e.g., NETIO-WRONG
PARAMETERS CONNECT) e chiamate a sistema operativo (e.g., OS MISSING FUNC-
1Launchpad è una piattaforma software di collaborazione che fornisce molteplici servizi, tra cuitracciamento di bug per molti software open source.
24
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
TION CALL OS). Statistiche sul tipo di guasti iniettati, sul dove i guasti sono iniettati e
sul numero di guasti iniettati saranno date più avanti, quando si discuterà delle campagne
di esperimenti effettuate sui componenti target.
Il workflow del tool consiste di tre fasi come mostrato in figura 2.1.1:
Figura 2.1.1: Workflow del tool di SFI.
1. Fase di SCAN: in questa fase il tool interagisce con l’utente per la definizione del
piano di esperimenti di fault injection; in particolare, l’utente può specificare uno o
più componenti per cui effettuare gli esperimenti e su questi il tool avvia la scan-
sione al fine di identificare tutti i punti di iniezione di guasti (Fault Injection Point
- FIP). Un FIP è un’istruzione nel codice sorgente in cui il tool può iniettare un
bug software (appartenente a una delle classi mostrate in tabella 2.1), per esempio:
chiamate di metodi e funzioni, inizializzazione di variabili, espressioni aritmeti-
che o booleane. Terminata la fase di scansione, l’utente può selezionare i FIP da
un elenco, e dalle scelte effettuate il tool genera il piano di esperimenti in modo
automatico (definendo quella che sarà la campagna di esperimenti).
2. Fase di ESECUZIONE: in questa fase il tool esegue gli esperimenti così come
definiti nel piano di esperimenti generato a valle della fase di SCAN. Ad ogni itera-
zione, il tool esegue un esperimento iniettando un solo guasto nel codice sorgente.
In particolare, il codice sorgente Python originario viene mutato secondo il fault
25
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
da iniettare nell’esperimento corrente. Ad esempio, quando si inserisce un bug in
una chiamata al metodo, il tool la sostituisce con un’altra chiamata allo stesso me-
todo ma con parametri di input diversi (per emulare un’omissione di un parametro
o il passaggio di un parametro di tipo differente da quello che il metodo si aspetta
o con valore corrotto), oppure la chiamata al metodo viene cancellata (per emula-
re un’omissione dal programmatore). Il codice sorgente mutato viene ricompilato
ed eseguito nell’ambiente di test. Durante l’esecuzione di ogni esperimento viene
eseguito un workload (vedi 3.1), necessario per esercitare il sistema target e poten-
zialmente attivare il fault iniettato. Al termine dell’esecuzione dell’esperimento il
tool raccoglie i log generati dal sistema e dal workload stesso.
3. Fase di ANALISI DEI DATI: in questa fase il tool calcola delle statistiche sulla
campagna analizzando i file di log raccolti durante gli esperimenti. Le statistiche
riportate riguardano:
(a) failure logging: esperimenti nei quali i fallimenti sono rilevati e loggati dal
sistema;
(b) failure propagation: esperimenti nei quali si osservano fallimenti di compo-
nenti del sistema non oggetto dell’iniezione;
(c) service availability: esperimenti nei quali, dopo la disattivazione del guasto,
si osservano ancora fallimenti dei servizi.
In aggiunta, il tool permette di indagare sui singoli esperimenti o organizzare i dati
rispetto al target dell’iniezione o il tipo di guasto iniettato. La fase di ANALISI DEI
DATI sarà ampiamente esplorata nella tesi, descrivendo con attenzione il processo
di estrazione di informazioni di interesse dai log collezionati durante l’esecuzione
delle campagne di esperimenti.
L’esecuzione di un esperimento si compone di numerosi passi, come mostrato in figura
2.1.2:
26
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figura 2.1.2: Passi della fase di esecuzione di un esperimento.
1. Mutazione del codice sorgente: in base al punto di iniezione , viene inserito il co-
dice mutato che consiste sia del codice sorgente corretto che del codice con bug.
Questi sono inclusi in un blocco if-else che determina due possibili percorsi di ese-
cuzione (buggy path e path corretto), a seconda del valore di una variabile (true o
false) che fa da trigger per attivazione del guasto; per esempio, se il FIP prevede
l’omissione della chiamata a una funzione, nel caso di esecuzione buggy questa
risulta assente, nel caso di esecuzione corretta questa è normalmente presente;
2. Clean-up dell’ambiente: ripristinare lo stato del sistema è fondamentale per avere
indipendenza tra gli esperimenti. L’azione di clean-up prevede il riavvio di tut-
ti i servizi (questo rende effettive le modifiche effettuate al codice sorgente, poi
ricompilato), la rimozione di eventuali risorse obsolete e terminazione di even-
tuali processi dell’esecuzione precedente. Da sottolineare che il clean-up è effet-
tuato mantenendo attivo il path corretto (trigger a false). A questo passo possia-
mo anche aggiungere l’azione di backup di strutture critiche per il funzionamento
del sistema, necessaria in quanto l’esecuzione con guasto potrebbe corromperle
27
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
irrimediabilmente impedendo l’esecuzione dei successivi esperimenti.
3. Attivazione del guasto: viene abilitato il path buggy settando il trigger a true.
4. Esecuzione round_1: viene avviato per la prima volta il workload, la cui esecuzione
porterà all’attivazione del bug iniettato. Il workload è quindi eseguito in presenza di
un guasto permanente, in quanto il percorso buggy è abilitato per tutta l’esecuzione
del workload.
5. Salvataggio log round_1: terminata la prima esecuzione si effettua il salvataggio dei
log prodotti dai vari componenti (e.g., per Nova, Cinder, Glance, etc.), dal workload
(output.log per lo stdout2 e error.log per lo stderr3) e trigger.log nel quale vengono
registrati gli istanti temporali in cui il workload induce l’esecuzione della linea di
istruzione mutata.
6. Disattivazione guasto: viene abilitato il path corretto settando il trigger a false.
7. Esecuzione round_2: viene avviato il workload per la seconda volta, questa volta
con path corretto abilitato. Lo scopo è quello di valutare la capacità del sistema
di riprendersi dai fallimenti eventualmente provocati dall’esecuzione con bug. Os-
servare fallimenti durate l’esecuzione del round_2 (con guasto disabilitato), accerta
che il guasto iniettato ha causato effetti permanenti sul sistema.
8. Salvataggio log round_2: come per il passo 5, vengono salvati i log prodotti da
OpenStack e dal workload (trigger.log non esiste poiché è abilitato il path corretto).
9. Salvataggio log del tool di SFI: prima di passare all’esperimento successivo viene
salvato il log contenete le info sui passi appena descritti.2stdout è il flusso standard per l’output di un programma.3stderr è il flusso a cui vengono inviati i messaggi di errore.
28
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
2.2 Workload
Il workload con cui si esercita il sistema durante gli esperimenti di fault injection è co-
stituito da un insieme di input abbastanza completo e variegato, con lo scopo di coprire
quanti più percorsi di codice possibile, incluso quello dove è stato inserito il codice mu-
tato. Nel caso di OpenStack, questi input sono una serie di chiamate alle API dei suoi
servizi (e.g., Nova, Cinder, Neutron, etc.).
Il workload progettato procede in questo modo:
1. Creazione dell’immagine;
2. Creazione coppia di chiavi;
3. Creazione di un gruppo di sicurezza al quale sarà aggiunta l’istanza;
4. Creazione di una rete privata alla quale sarà connessa l’istanza;
5. Creazione di un router per testare successivamente la connettività alla rete;
6. Avvio dell’istanza con l’immagine, rete, gruppo di sicurezza e coppia di chiavi
create, e GET della lista di istanze;
7. Aggiunta dell’indirizzo IP all’istanza;
8. Creazione di un volume e GET della lista dei volumi;
9. Attach del volume creato all’istanza e GET della lista dei volumi;
10. Tentativo di connessione in SSH all’istanza creata;
11. Riavvio dell’istanza;
12. Tentativo di connessione in SSH all’istanza dopo il riavvio;
Dagli step riportati, si può apprezzare la varietà delle chiamate che verranno fatte durante
l’esecuzione del workload.
29
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Sono previsti anche dei controlli per verificare eventuali fallimenti dei servizi a segui-
to delle chiamate API effettuate dal workload. In particolare, il workload è capace di
registrare due tipi di fallimenti:
1. Fallimenti per Asserzione: questi fallimenti sono rilevati dai controlli di integri-
tà e consistenza effettuati per verificare i risultati delle chiamate precedenti (e.g.,
dopo la creazione di un volume, ci si aspetta che questi diventi disponibile). Ta-
le meccanismo è definito come “check & retry”, e verifica lo stato delle risorse
oggetto dell’ultima chiamata, registrando un fallimento nel caso in cui il controllo
non viene superato (è definito un numero massimo di tentativi pari a 5). In questi
casi, il workload continua la sua esecuzione perché il servizio non ha manifesta-
to esplicitamente un fallimento, ma questo è stato accertato dai controlli presen-
ti nel workload. Esempi di controlli implementati sono: check_image_creation(),
check_volume_creation(), check_volume_attaching().
2. Fallimenti per API ERROR: questi fallimenti sono rilevati quando, a seguito una
chiamata API, il servizio risponde con un messaggio di errore (eg., codice HTTP
40x, 50x, etc.). In questi casi, il workload termina la sua esecuzione in quanto il
servizio ha manifestato esplicitamente un fallimento, e data l’incapacità di portare
a termine la richiesta non ha più senso continuare l’esecuzione.
2.3 Log collezionati
Come anticipato, durante l’esecuzione di ogni esperimento si effettua il salvataggio dei
log prodotti dal sistema target, dal workload e dal tool di SFI. Per ogni esperimento effet-
tuato, il tool produce in output un file contenente le informazioni sul FIP, che comprendo-
no: il tipo di fault, il componente, la classe e la funzione target, più il punto di iniezione.
Queste informazioni sono importanti in fase di analisi per mantenere una corrispondenza
tra il fault iniettato e la funzione in cui è stato iniettato, soprattutto in ottica di valutazione
della propagazione spaziale del fallimento.
30
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figura 2.3.1: Log collezionati durante l’esecuzione di un esperimento.
In figura 2.3.1, si riportano i tipi di log collezionati durante l’esecuzione di un esperimen-
to.
Di seguito è fornita una breve panoramica sulle informazioni contenute nei log prodotti
durante gli esperimenti.
2.3.1 Log del sistema target
Ogni componente del sistema (ed i suoi sottocomponenti), memorizza eventi di natura
differente nei propri log (e.g., Nova, Cinder, Neutron, etc.), a cui assegna severità diffe-
rente. Durante l’esecuzione dell’esperimento, una volta per round, si effettua il clean-up
dei log di ogni componente e il loro salvataggio alla fine dell’esecuzione del workload.
In questo modo, per la fase di analisi, si hanno a disposizione i soli log generati durante
l’esecuzione dello specifico round.
Per l’analisi, l’interesse è posto sia sulla presenza che sull’assenza di eventi loggati con
alta severità (e.g., ERROR, CRITICAL o FATAL), in quanto a questi sono in genere asso-
ciati fallimenti di servizio o errori interni dei componenti; in particolare, l’assenza di log
31
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
ad alta severità nel caso di esecuzione del round_1 (buggy path abilitato), è un campanello
d’allarme che si trasforma in un fallimento del logging nel caso in cui è confermato un
fallimento nell’esecuzione del workload. Allo stesso modo, la presenza di log ad alta se-
verità nel caso di esecuzione del round_2 (buggy path disabilitato), denota l’incapacità del
sistema/componente di riprendersi da un fallimento, attuando magari azioni di ripristino
o recovery.
2.3.2 Log del workload
I log prodotti dall’esecuzione del workload (vedi 2.2) sono divisi in due file (un estratto è
fornito in figura 2.3.2):
• output.log: mantiene le informazioni sulle chiamate API effettuate dal workload e
sul risultato dei check & retry, in particolare:
– istante di inizio della chiamata - [data] INFO [workload]: [START] [chiamata completa];
– risposta ricevuta (e.g., l’output fornito da una chiamata nova list);
– istante di terminazione della chiamata - [data] INFO [workload]: [END] [chiamata
completa];
– nel caso di check & retry - [data] INFO [workload]: [risorsa o tipo di check] [risultato
check] [#tentativo]
– nel caso di esaurimento dei tentativi di retry - [data] INFO [workload]: Failure!!!
;
• error.log: mantiene le informazioni sui fallimenti di servizio accertati durante l’e-
secuzione del workload, loggando due tipi di informazioni:
– Assertion results: informazione registrata dopo l’esaurimento dei tentativi di
check & retry - [data] INFO [workload]: Assertion results: [tipo di asserzione];
– API ERROR: informazione registrata quando una chiamata API ritorna con un
errore - [data] INFO [workload]: API ERROR: [chiamata completa] [errore ritornato];
32
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figura 2.3.2: Estratto output.log e error.log
Queste informazioni saranno usate nell’analisi successiva in quanto ci danno i tempi delle
chiamate, l’output fornito e fallimenti percepiti lato utente (workload in questo caso).
2.3.3 Log del tool di fault injection
Durante l’esecuzione di un esperimento, il tool produce due log importanti per la fase di
analisi:
• trigger.log: registra tutti gli istanti temporali in cui viene eseguita l’istruzione mu-
tata, quindi mantiene le informazioni sugli istanti e il numero di attivazioni del
bug iniettato; dato che il buggy path è attivo solo durante la prima esecuzione del
workload, esiste solo per il round_1;
• tool.log: registra tutti i passi dell’esecuzione dell’esperimento (e.g., clean-up del-
l’ambiente, abilitazione dell’iniezione, avvio e completamento round_1, etc.);
Le informazioni mantenute nel trigger.log sono importanti in quanto ci permettono di va-
lutare la propagazione temporale, intesa come differenza di tempo tra l’istante di iniezione
e l’istante di rilevazione (e.g., assertion failure, api error o log ad alta severità).
2.4 Analisi dei log
Una volta terminata la campagna di esperimenti e raccolti i dati di interesse, si passa
all’analisi dei dati, il cui scopo è l’estrazione di informazioni che ci saranno utili per
rispondere alle research questions e per selezionare esperimenti di interesse che saranno
successivamente approfonditi.
33
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Il primo dato di interesse riguarda il numero di FIP prodotti a valle della fase di SCAN,
che dipende dal sottosistema target (e.g., Nova, Cinder, Neutron, etc.) e dalla fault library
definita. Il numero di FIP definisce un ipotetico numero di esperimenti che dovranno
essere effettuati. Ovviamente, per esercitare tutti i possibili punti di iniezione, si dovrebbe
definire un workload capace di coprire tutto il codice analizzato. Per questo motivo, prima
di avviare la campagna di esperimenti, viene eseguita un’analisi di copertura capace di
identificare quelli che sono i FIP che effettivamente saranno coperti dal workload, e solo
per questi il tool effettuerà le iniezioni e quindi gli esperimenti, distinguendo alla fine tra
esperimenti Skipped ed esperimenti Completed.
L’analisi prosegue sugli esperimenti Completed, seguendo i passi mostrati in figura 2.4.1
e descritti di seguito.
Figura 2.4.1: Workflow dell’analisi dei log.
1. Classificazione in base al fallimento del round: questa classificazione è fatta analiz-
zando l’error.log prodotto dal workload (vedi 2.3.2). In particolare, gli esperimenti
vengono classificati in base alla presenza nell’error.log, di ogni round, delle parole
chiave “Assertion” e “API ERROR”. Avendo eseguito due round per esperimento,
le possibili classi di appartenenza sono 4:
(a) Failure Round_1 & Round_2: in questi casi il fallimento del workload è stato
rilevato in entrambi i round e probabilmente il guasto iniettato ha prodotto ef-
fetti permanenti sul componente target o sull’intero sistema. Questi casi devo-
no essere analizzati con cautela, in quanto evidenziano situazioni abbastanza
34
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
critiche nelle quali il sistema non riesce a recuperare dallo stato di errore nel
quale si è portato;
(b) Failure Round_1 Only: questi casi sono abbastanza normali, in quanto l’ese-
cuzione del workload è avvenuta con buggy path abilitato e molto probabil-
mente il fallimento è dovuto proprio al guasto iniettato. Un’altra osservazione
importante che si può fare è relativa al fatto che nel round_2 (buggy path disa-
bilitato), non è stata registrato alcun fallimento del workload, quindi gli effetti
dell’attivazione del guasto non hanno provocato effetti permanenti: questo
può essere dovuto al tipo di guasto iniettato oppure alla capacita del sistema
di recuperare dal fallimento del round precedente;
(c) Failure Round_2 Only: questi casi sono abbastanza anomali e vanno analiz-
zati con attenzione. In particolare, un fallimento nel solo round_2 può essere
dovuto a guasti latenti dell’esecuzione precedente oppure semplicemente il
fallimento non dipende dal guasto iniettato, ma da qualche condizione parti-
colare del sistema (e.g., esaurimento delle risorse o problemi momentanei).
E’ necessaria un’analisi più approfondita;
(d) No Failure: questi casi potrebbero essere quasi considerati normali, nel senso
che l’esecuzione del workload nel round_1 (con buggy path abilitato) non
necessariamente deve produrre dei fallimenti (la stessa considerazione sul
round_1 può essere estesa alla la classe precedenti), e quindi il workload può
completare la sua esecuzione e terminare correttamente. Per questi casi è
comunque utile indagare al fine di identificare log ad alta severità tra quelli re-
gistrati dal sistema: infatti è possibile che il sistema abbia mascherato l’errore
oppure, semplicemente, questi non ha influito sull’esecuzione del workload.
Applicando questo tipo di classificazione, si possono già riscontrare dei casi uti-
li per rispondere alle research questions che abbiamo definito, per esempio: nelle
classi Failure abbiamo esperimenti che possono essere analizzati per confermare
35
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
fenomeni di propagazione temporale e spaziale (e.g., si possono analizzare i log
del sistema per valutare la propagazione tra i diversi componenti del servizio, op-
pure valutare la latenza dall’istante di iniezione all’istante di manifestazione, etc.),
quindi RQ3. Allo stesso tempo, possono essere utili per valutare se il sistema ha
manifestato il fallimento del servizio, quindi RQ1, e se il sistema di logging ha
manifestato delle lacune, quindi RQ2. Detto questo, il secondo livello di analisi ci
permette di essere più precisi nella classificazione e individuazione di esperimenti
utili per le research questions.
2. Classificazione in base al tipo di fallimento: questa classificazione è fatta analiz-
zando l’error.log prodotto dal workload (vedi 2.3.2). In particolare, gli esperimenti
vengono classificati in base alla presenza nell’error.log di ogni round della sola pa-
rola chiave “Assertion” o della sola parola chiave “API ERROR” o di entrambe,
distinguendo i tre casi. L’assenza di entrambe le parole corrisponde al caso di NO
Failure già classificato nella fase 1. La classificazione per tipo di fallimento è fatta
per ogni classe definita nella fase 1 (escuso la classe No Failure), per un totale di 9
possibili combinazioni. Di seguito si riportano solo le tre classi principali:
(a) Assertion Failure & API ERROR: in questi casi il workload ha registrato sia
l’asserzione per esaurimento dei tentativi di check & retry, sia il fallimento
della chiamata API a causa di risposta con codice di errore. Gli esperimen-
ti appartenenti a questa classe, a causa dell’occorrenza di API ERROR, non
hanno portato a termine l’esecuzione del workload e sono importanti da ana-
lizzare per valutare fenomeni di propagazione e qualità dei log prodotti (intesa
come presenza di log effettivamente rappresentativi dello stato di errore del
servizio).
(b) Assertion Failure Only: in questi casi il workload ha terminato la sua esecu-
zione, anche se in uno o più casi il meccanismo di check & retry ha registrato
l’occorrenza di un fallimento del servizio, in quanto il controllo di integri-
36
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
tà delle risorse non è stato superato. Questi casi sono interessanti, in quanto
possono evidenziare l’incapacità del sistema di dichiararsi fallito e per que-
sto l’analisi va approfondita anche sui log del sistema target, con lo scopo di
verificare la presenza di log ad alta severità e nel caso valutare la loro qualità.
(c) API ERROR Only: in questi casi il workload non ha terminato la sua esecu-
zione e non ha mai registrato un’asserzione relativa al fallimento dei controlli
di integrità delle risorse. Questi casi sono interessanti, perché possono evi-
denziare l’effettiva capacità del sistema di dichiararsi fallito non appena una
condizione di errore viene rilevata. E’ comunque richiesta un’analisi suc-
cessiva dei log del sistema, perché potrebbe portare alla luce casi critici nei
quali i meccanismi di fault-tolerance (e.g., risposta in modalità di fallback)
sono riusciti ad ingannare i controlli di integrità favorendo una propagazione
dell’errore.
Applicando questo tipo di classificazione, si possono individuare casi utili per va-
lutare la propagazione e la capacità del sistema/servizio di dichiararsi fallito.
3. Classificazione in base alla presenza di log ad alta severità nei log di sistema: que-
sta classificazione è fatta analizzando i log prodotti dal sistema target (vedi 2.3.1).
In particolare, gli esperimenti vengono classificati in base alla presenza nei log di
sistema di messaggi con severity error (ricerca effettuata tenendo conto del tem-
plate utilizzato dal sistema per generare i log). Distinguiamo due possibili classi
(essendo questo il terzo livello di classificazione, avremo queste informazioni per
tutte le classi e combinazioni delle stesse, definite nei due punti precedenti):
(a) OpenStack Log: in questi casi è accertata la presenza di messaggi con severity
error nei log di sistema, quindi un’ulteriore analisi potrebbe essere effettuata
su di essi per valutarne la qualità. Ovviamente, la presenza di log ad alta
severità per gli esperimenti appartenenti alla classe No Failure, per i quali
non è stato registrato un fallimento lato workload, è abbastanza anomalo e
37
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
l’analisi va approfondita, con lo scopo di valutare l’effettiva natura del log ad
alta severità registrato.
(b) NO OpenStack Log: in questi casi non si riscontra la presenza di messaggi
con severity error nei log di sistema. Questa condizione è accettabile per gli
esperimenti appartenenti alla classe No Failure, ma sicuramente è anomala
negli altri casi (Failure Round_1 & Round_2, Failure Round_1 Only e Failure
Round_2 Only), in quanto evince delle lacune nell’attività di logging. Questi
casi sono particolarmente interessanti, in quanto ci permettono di rispondere
alla RQ2 relativa all’attività di logging.
Dall’analisi effettuata, si possono ricavare informazioni dettagliate sugli esperimenti del-
la campagna di fault injection, così da focalizzare l’attenzione su quegli esperimenti che
risultano anomali o critici (e.g., No Failure + OpenStack Log, Failure Round_2 Only, Fai-
lure Round_1 & Round_2, Failure Round_1 Only + NO OpenStack Log, etc.). In tabella
2.2 si riporta il quadro generale della classificazione degli esperimenti a valle dell’ana-
lisi. Ad ogni classe è stato associato un livello di severità espresso su 3 livelli, così da
quantificare il grado di attenzione che deve essere posto sull’ulteriore analisi di questi
esperimenti:
1. A - ALTO: associato alle classi in cui si è riscontrato un comportamento critico (e.g
Failure Round_1 & Round_2, perché in questo caso potrebbero esserci stati effetti
permanenti dovuti all’iniezione, oppure Failure Round_1 Only + NO OpenStack
Log, perché in questo caso potrebbero esserci lacune nell’attività di logging). In
questi casi è necessaria un’analisi più approfondita.
2. B - MEDIO: associato alle classi in cui si è riscontrato un comportamento am-
biguo/anomalo (e.g., NO Failure + OpenStack Log, perché in questo caso non si
riscontrano fallimenti lato workload, ma allo stesso tempo vengono registrati log
ad alta severità, oppure Failure Round_2 Only). In questi casi è consigliata un’ana-
38
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
lisi più approfondita, così da risolvere l’ambiguità e capire se i log registrati sono
dovuti all’iniezione o meno.
3. C - BASSO: associato alle classi in cui si è riscontrato un comportamento adeguato
(e.g., Failure Round_1 Only + OpenStack Log, perché si sta considerando l’esecu-
zione con buggy path attivo, e ci si aspetta che in caso di fallimento questi venga
rilevato e registrato con log ad alta severità) per il tipo di analisi che vogliamo
effettuare. In questi casi, un’analisi più approfondita potrebbe anche non essere
necessaria.
1 - Fallimenti per Round 2 - Fallimenti per tipo 3 - Presenza error log SeveritàR1+R2 R1 R2 No As. + API As. API log No log
! ! ! A! ! ! A! ! ! A! ! ! A! ! ! A! ! ! A
! ! ! C! ! ! A! ! ! C! ! ! A! ! ! C! ! ! A
! ! ! B! ! ! A! ! ! B! ! ! A! ! ! B! ! ! A
! – – – ! B! – – – ! C
Tabella 2.2: Classificazione degli esperimenti.
39
Capitolo 3
Informazioni Sperimentali
In questo capitolo si presenta l’ambiente di sperimentazione utilizzato per effettuare le
campagne di fault injection e si forniscono i dettagli sul piano di esperimenti per i sotto-
sistemi target OpenStack Nova e OpenStack Cinder.
In 3.1 viene descritto il testbed, in termini di requisiti hardware e setup dell’architettura
di test, chiamata OpenStack Server. Infine in 3.2 viene descritto il piano di esperimenti e
riportate le prime statistiche sulle campagne di esperimenti eseguite.
3.1 Testbed
In questa sezione si presenta l’ambiente di test sul quale sono state effettuate le campagne
di fault injection. In particolare, si forniscono i requisiti hardware della macchina sulla
quale è stato effettuato il deploy di OpenStack, e una descrizione dell’architettura target
(chiamata OpenStack Server), costituita dall’installazione OpenStack e distribuzione dei
componenti del tool di fault injection.
Il deploy della piattaforma OpenStack è stato fatto su una macchina virtuale con i seguenti
requisiti:
• CPU: 8 CPU(s) virtuali;
40
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figura 3.1.1: Configurazione dell’OpenStack Server.
• MEM: 16 GB;
• DISK: 150 GB;
• Guest OS: CentOS v7.0;
Sulla macchina virtuale è stato effettuato il deploy di OpenStack (versione Pike - 3.12.1),
utilizzando l’utility Packstack, in una configurazione che potremmo definire vanilla, in
quanto è prevista l’installazione dei soli servizi che fanno parte del “core” di OpenStack
(e.g., Nova, Cinder, Neutron, Glance, etc.) e single-node, in quanto tutti i servizi sono
distribuiti sulla singola macchina virtuale.
In figura 3.1.1 è mostrata l’architettura del testbed, indicata come OpenStack Server, dove
vengono anche riportati i moduli del tool di fault injection utilizzato.
L’architettura del testbed prevede i seguenti componenti:
1. piattaforma OpenStack: l’insieme dei servizi (e.g., Nova, Neutron, Cinder, etc.) e
dei componenti che li compongono (e.g., nova-api, nova-compute, neutron-server,
41
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
etc.), insieme ai moduli per la comunicazione intra-servizio (RabbitMQ Server)
e ai moduli per la gestione e memorizzazione dei dati che vengono processati su
OpenStack (MySQL Server);
2. Tool Agent: rappresenta il cuore del tool di fault injection, in quanto è responsabile
di tutti i passi della fase di esecuzione di un esperimento, come definito in 2.1. In
particolare, l’agent espone un’API REST e chiamate all’API possono essere fatte
dalla dashboard o da altri tool esterni, per esempio per richiedere la lista dei FIP a
valle della fase di SCAN. Per ogni FIP selezionato dall’utente, questi viene passato
al Tool Agent tramite l’API, l’agent esegue l’esperimento e salva i risultati (Test
logs);
3. Tool dashboard: fornisce un’interfaccia all’utente tramite la quale questi può confi-
gurare la campagna di esperimenti (selezionando il componente o sotto-componente
e la lista dei FIPs, e caricando il workload). Al termine della campagna di esperi-
menti, fornisce anche delle statistiche (eg. vedi 2.1.1) sugli esperimenti effettuati;
4. Tool user: rappresenta il terminale con il quale l’utente accede alla dashboard, per
interagire con l’architettura del testbed;
5. Test logs: insieme dei log memorizzati durante l’esecuzione della campagna di
esperimenti (vedi 2.3);
6. Foreground workload: rappresenta il workload con il quale si vuole esercitare il
sistema target durante un esperimento di fault injection (vedi 2.2).
3.2 Punti di iniezione
In questa sezione è fornita una prima panoramica sulle campagne di fault injection ef-
fettuate su OpenStack. In particolare, sono stati valutati due sottosistemi di OpenStack:
Nova (servizio di calcolo) e Cinder (servizio di block storage), e in entrambi i casi sono
42
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
stati selezionati tutti i componenti dei sottosistemi (e.g., nova-api, nova-scheduler, cinder-
api, cinder-volume, etc.) e tutti i tipi di fault supportati dal tool. Le informazioni riportate
sono utili per quantificare la dimensione del piano di esperimenti, per identificare i com-
ponenti maggiormente testati e i tipi di fault maggiormente applicati, e per valutare la
bontà dell’analisi in relazione a quello che è il workload progettato (infatti, dopo aver
identificato i possibili punti di iniezione, il tool eseguirà l’analisi di copertura per identifi-
care i fault che saranno attivati durante l’esecuzione del workload definito, eseguendo di
fatto solo gli esperimenti relativi a questi fault).
Le figure 3.2.1 e 3.2.2, riportano il piano di esperimenti per i due servizi target (Nova e
Cinder), suddiviso per file di codice sorgente.
Il piano di esperimenti generato automaticamente dal tool, prevede 5588 punti di iniezione
per Nova e 6633 punti di iniezione per Cinder, e copre tutti i file di codice sorgente che
costituiscono i due sottosistemi.
Le tabelle 3.1 - Nova e 3.2 - Cinder, riportano un estratto con i 10 file sorgente per i
quali la scansione ha riportato il numero maggiore di possibili FIP. In entrambi i casi, si
può notare che il maggior numero di FIP è stato riscontrato per i file manager.py, che
rappresentano i gestori di tutti i processi e chiamate RPC, relative rispettivamente alle
istanze e ai volumi. Per OpenStack Nova, altri file iniettati riguardano le API di Nova,
driver di virtualizzazione e le API SQL Alchemy, mentre per OpenStack Cinder abbiamo
driver per la gestione dei volumi e API SQL Alchemy.
Sottosistema FIP TOT ID Nome File # FIP %
5588
1 /nova/compute/manager.py 1416 25,342 /nova/compute/api.py 370 6,623 /nova/virt/libvirt/driver.py 361 6,464 /nova/db/sqlalchemy/api.py 195 3,49
OpenStack 5 /nova/virt/vmwareapi/vmops.py 160 2,86Nova 6 /nova/virt/xenapi/vmops.py 140 2,50
7 /nova/cells/messaging.py 138 2,478 /nova/virt/libvirt/imagebackend.py 116 2,079 /nova/cells/manager.py 107 1,91
10 /nova/db/api.py 101 1,80
Tabella 3.1: File di codice sorgente con più punti di iniezione - OpenStack Nova.
43
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figu
ra3.
2.1:
Pian
odi
espe
rim
enti
difa
ulti
njec
tion
peri
lser
vizi
oO
penS
tack
Nov
a.Su
ddiv
isio
nepe
rfile
dico
dice
sorg
ente
44
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figu
ra3.
2.2:
Pian
odi
espe
rim
enti
difa
ulti
njec
tion
peri
lser
vizi
oO
penS
tack
Cin
der.
Sudd
ivis
ione
perfi
ledi
codi
ceso
rgen
te
45
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Sottosistema FIP TOT ID Nome File # FIP %
6633
1 /cinder/volume/manager.py 474 7,152 /cinder/volume/drivers/.../storwize_svc_common.py 212 3,203 /cinder/db/sqlalchemy/api.py 178 2,684 /cinder/volume/drivers/dell_emc/vmax/common.py 138 2,08
OpenStack 5 /cinder/volume/flows/manager/create_volume.py 135 2,03Cinder 6 /cinder/volume/drivers/ibm/gpfs.py 106 1,60
7 /cinder/volume/drivers/lvm.py 103 1,558 /cinder/volume/drivers/netapp/dataontap/nfs_base.py 99 1,499 /cinder/volume/drivers/solidfire.py 97 1,46
10 /cinder/volume/drivers/hpe/hpe_3par_common.py 93 1,40
Tabella 3.2: File di codice sorgente con più punti di iniezione - OpenStack Cinder.
Un’altra informazione di interesse riguarda i tipi di fault più frequenti per i sottosistemi
target. Le figure 3.2.3 e 3.2.4, mostrano la lista dei tipi di fault e il numero di occorrenze
per ognuno di essi. Le tabelle 3.3 - Nova e 3.4 - Cinder, riportano un estratto con i
primi 5 tipi di fault più comuni. Per entrambi i sottosistemi, si può notare che i tipi di
fault più comuni sono gli stessi (si differenziano solo per la presenza di INSTANCE e
VOLUME, come specializzazione del tipo di fault rispettivamente per istanze e volumi),
anche se presenti in ordine differente. Per OpenStack Nova, i cinque tipi di fault sono
distribuiti abbastanza equamente, intorno al 12%, mentre per OpenStack Cinder il tipo
THROW_EXCEPTION raggiunge il 20% e i restanti quattro sono introno al 12%.
Figura 3.2.3: Tipi di fault più comuni per il sottosistema OpenStack Nova.
46
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Sottosistema FIP TOT ID Nome File # FIP %
5588
1 OPENSTACK_THROW_EXCEPTION-INSTANCE 683 12,222 OPENSTACK_MISSING_FUNCTION_CALL-INSTANCE 683 12,22
OpenStack 3 OPENSTACK_WRONG_PARAMETERS-INSTANCE 673 12,04Nova 4 OPENSTACK_MISSING_PARAMETERS-INSTANCE 673 12,04
5 OPENSTACK_WRONG_RETURN_VALUE-INSTANCE 656 11,74
Tabella 3.3: Tipi di fault più comuni per il sottosistema OpenStack Nova.
Figura 3.2.4: Tipi di fault più comuni per il sottosistema OpenStack Cinder.
Sottosistema FIP TOT ID Nome File # FIP %
5588
1 OPENSTACK_WRONG_RETURN_VALUE-VOLUME 1375 20,732 OPENSTACK_THROW_EXCEPTION-VOLUME 971 14,64
OpenStack 3 OPENSTACK_MISSING_FUNCTION_CALL-VOLUME 971 14,64Cinder 4 OPENSTACK_WRONG_PARAMETERS-VOLUME 894 13,48
5 OPENSTACK_MISSING_PARAMETERS-VOLUME 894 13,48
Tabella 3.4: Tipi di fault più comuni per il sottosistema OpenStack Cinder.
Come anticipato più volte, il tool esegue solo gli esperimenti per i quali l’esecuzione
del workload attiverà il guasto iniettato (precisamente nell’esecuzione del round_1 con
buggy path abilitato), distinguendo alla fine tra quelli che saranno Skipped e Completed.
La tabella 3.5 riporta la percentuale di esperimenti Completed, sul totale dei punti di
iniezione selezionati a valle della fase di SCAN. I risultati mostrano una percentuale di
copertura dei FIP del 14,64 % nel caso di Nova, mentre nel caso di Cinder si attesta sul
5,6%. Sebbene la percentuale di copertura non sembri elevata, il risultato è molto positivo,
47
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
in quanto ci fornisce un dataset totale di 1189 esperimenti su cui poter eseguire l’analisi
vista nel capitolo 2.
Sottosistema FIP TOT Completed % di Copertura
OpenStack Nova 5588 818 14,64 %OpenStack Cinder 6633 371 5,59 %
Tabella 3.5: Esperimenti di fault injection eseguiti.
48
Capitolo 4
Analisi dei risultati
In questo capitolo si presentano i risultati sperimentali ottenuti eseguendo le campagne di
fault injection sui sottosistemi OpenStack Nova e OpenStack Cinder. Le prime statistiche,
come il numero di FIP identificati dal tool nella scansione, la localizzazione per file di
codice sorgente dei punti di iniezione e i tipi di fault che possono essere applicati, sono
stati presentati già nella sezione 3.2, così da fornire un quadro generale sul dataset di
interesse.
Nelle sezioni successive, si prosegue l’analisi applicando i vari criteri di classificazione
(vedi 2.4). In particolare, in 4.1 sono riportate tutte le statistiche relative alla classifi-
cazione dei log (e.g., esperimenti che hanno riportato un fallimento in entrambi i round
oppure in uno solo dei due round, il tipo di fallimento registrato e presenza o meno di log
ad alta severità). Nelle restanti sezioni, 4.2, 4.3 e 4.4, si utilizzeranno queste statistiche
per fare delle considerazioni generali in merito alle research questions, che saranno poi
approfondite così da completare il processo di analisi che si vuole presentare in questa
tesi.
49
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
4.1 Sintesi
Applicando i criteri di classificazione, come definito in 2.4, si possono ricavare infor-
mazioni abbastanza dettagliate sul comportamento del sistema durante gli esperimenti di
fault injection. Di seguito, per ogni passo del processo di classificazione, si riportano
i risultati per i due sottosistemi target (OpenStack Nova e OpenStack Cinder), facendo
di volta in volta delle considerazioni sui risultati ottenuti, e come questi possono essere
utilizzati per rispondere alle research questions definite.
Prima di passare alla classificazione, si riportano in forma grafica (in figura 3.5) i numeri
relativi agli esperimenti Skipped e Completed riportati già in tabella 3.5.
Figura 4.1.1: Esperimenti di FI eseguiti per OpenStack Nova e OpenStack Cinder.
La percentuale di copertura dipende strettamente dal workload progettato e dalle sue chia-
mate alle API di OpenStack. Sicuramente la maggior parte delle richieste passa per Nova
(e.g., creazione di istanze e tutte le azioni che la riguardano, come attach/detach di un
volume, aggiunta/rimozione di un indirizzo IP, che arrivano a Nova attraverso chiamate
REST fatte a nova-api e gestite poi da nova-compute con chiamate agli altri servizi).
4.1.1 Classificazione in base al fallimento del Round
Il primo passo prevede di classificare gli esperimenti in base al fallimento del round di
esecuzione, definendo così quattro possibili classi di appartenenza: Failure Round_1 &
Round_2, Failure Round_1 Only, Failure Round_2 Only, No Failure.
50
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Per OpenStack Nova, la classificazione in base al fallimento del round è riportata in
tabella 4.1. Gli stessi dati sono riportati in forma grafica in figura 4.1.2.
Classe di appartenenza Occorrenze %Failure Round_1 and Round_2 30 3,68%
Failure Round_1 Only 575 70,46%Failure Round_2 Only 0 0%
NO Failure 211 25,86%816 100%
Tabella 4.1: OpenStack Nova - Classificazione in base al fallimento del Round.
Figura 4.1.2: OpenStack Nova - Classificazione in base al fallimento del Round.
Dalla figura 4.1.2, si può notare che circa il 70% degli esperimenti (575 su 816 Com-
pleted), mostra un fallimento del servizio durante l’esecuzione del Round_1, anche se a
questo livello non si sa ancora se il fallimento è dovuto al controllo di consistenza delle
risorse (fallimento per Assertion Failure), o al servizio che risponde alla richiesta con un
codice di errore (fallimento per API ERROR). Si riscontrano casi di fallimenti in entrambi
i round, nel 3,68 % degli esperimenti (30 su 816 Completed), e in questi casi si presume
che l’attivazione del guasto abbia portato una condizione di errore permanente nel servi-
zio/sistema. Non si riscontrano invece casi di fallimento nel solo Round_2. Infine, nel
25,86% degli esperimenti (211 su 816 Completed), non si riscontrano fallimenti in nessu-
no dei due round, indice del fatto che il guasto iniettato non ha causato effetti durante il
tempo di osservazione dell’esperimento (errori latenti).
51
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Per OpenStack Cinder, la classificazione in base al fallimento del round è riportata in
tabella 4.2. Gli stessi dati sono riportati in forma grafica in figura 4.1.3.
Classe di appartenenza Occorrenze %Failure Round_1 and Round_2 6 1,62%
Failure Round_1 Only 341 91,91%Failure Round_2 Only 0 0%
NO Failure 24 6,47%371 100%
Tabella 4.2: OpenStack Cinder - Classificazione in base al fallimento del Round.
Figura 4.1.3: OpenStack Cinder - Classificazione in base al fallimento del Round.
Dalla figura 4.1.3, si può notare che in più del 90% degli esperimenti (341 su 371 Comple-
ted), il guasto iniettato ha provocato un fallimento del servizio durante l’esecuzione del
Round_1, da attribuire a fallimenti per Assertion Failure o API ERROR. Si riscontrano
casi di fallimenti in entrambi i round, nel 1,6 % degli esperimenti (6 su 371 Completed), e
in questi casi si presume che l’attivazione del guasto abbia portato una condizione di erro-
re permanente nel servizio/sistema. Non si riscontrano invece casi di fallimento nel solo
Round_2. Infine, nel 6,4% degli esperimenti (24 su 371 Completed), non si riscontrano
fallimenti in nessuno dei due round.
4.1.2 Classificazione in base al tipo di fallimento
Il secondo passo prevede di classificare gli esperimenti (già divisi in base al fallimento per
round, vedi 4.1.1 per i risultati) in base al tipo di fallimento, distinguendo tra: Assertion
52
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Failure & API ERROR, Assertion Failure Only, API ERROR Only.
Per OpenStack Nova, la classificazione in base al tipo di fallimento è riportata nella
tabella 4.3. Gli stessi dati sono riportati in forma grafica in figura 4.1.4. Non si riporta
la stessa classificazione per Failure Round_2 Only, in quanto non sono state riscontrate
occorrenze per questa classe.
Classe di appartenenzaFailure
%Failure
%Round_1 & Round_2 Round_1 Only
Assertion Failure & API ERROR 9 30% 451 78,44%API ERROR Only 21 70% 72 12,52%
Assertion Failure Only 0 0% 52 9,04%30 100% 575 100%
Tabella 4.3: OpenStack Nova - Classificazione in base tipo di fallimento.
Figura 4.1.4: OpenStack Nova - Classificazione in base tipo di fallimento.
Dalla figura 4.1.4, si può notare che:
• nel caso di Failure Round_1 & Round_2, nel 30% degli esperimenti (9 su 30 Failure
Round_1 & Round_2), risulta essere stato registrato sia il fallimento per asserzione
che per API ERROR, mentre nel 70% degli esperimenti (21 su 30 Failure Round_1
& Round_2) si registra un fallimento per solo API ERROR;
• nel caso di Failure Round_1 Only, nel 78,44% degli esperimenti (451 su 575 Fai-
lure Round_1 Only), si è avuto sia il fallimento per asserzione, sia quello per API
ERROR; nel 12,52% degli esperimenti (72 su 575 Failure Round_1 Only) sono stati
53
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
registrati solo fallimenti per API ERROR, mentre nel 9,04% degli esperimenti (52
su 575 Failure Round_1 Only) è stato registrato il fallimento per asserzione;
Per OpenStack Cinder, la classificazione in base al tipo di fallimento è riportata nella
tabella 4.4. Gli stessi dati sono riportati in forma grafica in figura 4.1.5. Non si riporta
la stessa classificazione per Failure Round_2 Only, in quanto non sono state riscontrate
occorrenze per questa classe.
Classe di appartenenzaFailure
%Failure y
%Round_1 & Round_2 Round_1 Onl
Assertion Failure & API ERROR 6 100% 337 98,83%API ERROR Only 0 0% 3 0,88%
Assertion Failure Only 0 0% 1 0,29%6 100% 341 100%
Tabella 4.4: OpenStack Cinder - Classificazione in base tipo di fallimento.
Figura 4.1.5: OpenStack Cinder - Classificazione in base tipo di fallimento.
Dalla figura 4.1.5, si può notare che:
• nel caso di Failure Round_1 & Round_2, per tutti gli esperimenti risulta essere stato
registrato sia il fallimento per asserzione, sia quello per API ERROR;
• nel caso di Failure Round_1 Only, in quasi il 99% degli esperimenti (337 su 341
Failure round_1 Only), si avuto sia il fallimento per asserzione, sia quello per API
ERROR; in 3 esperimenti sono stati registrati solo fallimenti per API ERROR e in
1 solo esperimento è stato registrato il fallimento per asserzione;
54
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Questi risultati ci forniscono un’importante spunto per l’analisi, in quanto:
1. per entrambi i sottosistemi il maggior numero di fallimenti è di tipo Assertion Fai-
lure & API ERROR, indicando delle carenze nei meccanismi di rilevamento de-
gli errori che possono favorire la propagazione dei guasti e l’incapacità del ser-
vizio/sistema di mostrare un comportamento fail-stop. Solo nel caso di Failure
Round_1 & Round_2 per Nova si registra un comportamento differente, con una
maggioranza di fallimenti per API ERROR, dovuti forse al numero limitato di
esperimenti appartenenti a questa classe.
2. nel caso di Nova, si possono analizzare gli esperimenti che hanno riportato solo
API ERROR (83 in totale), per valutare l’efficacia dei meccanismi di rilevamento e
valutare se la propagazione è stata limitata. Lo stesso discorso si estende a Cinder
e i 3 esperimenti con solo API ERROR nel round_1.
3. nel caso di Nova, si possono analizzare gli esperimenti appartenenti alla classe As-
sertion Failure Only (52 del solo round_1), in quanto il servizio/sistema non è stato
capace di dichiararsi fallito all’utente, e l’analisi di questi esperimenti è utile per
capire come migliorare i meccanismi di fault-tolerance del sistema e valutare la
propagazione temporale e spaziale.
4.1.3 Classificazione in base alla presenza di log con severity error
L’ultimo passo prevede di classificare gli esperimenti in base alla presenza o meno di log
ad alta severità, tra i log registrati dai diversi componenti di OpenStack. Questa classifica-
zione è utile per valutare l’efficacia del sistema di logging e dei meccanismi di rilevamento
degli errori implementati.
Per OpenStack Nova, si riportano i risultati in tabella 4.5, aggregati in base al round di
fallimento. Gli stessi dati sono riportati in forma grafica in figura 4.1.6. Non si riporta
la stessa classificazione per Failure Round_2 Only, in quanto non sono state riscontrate
occorrenze per questa classe.
55
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Classe di appartenenzaFailure
%Failure
% NO Failure %Round_1 and Round_2 Round_1 Only
OpenStack Log 30 100% 548 95,3% 54 25,59%NO OpenStack Log 0 0% 27 4,7% 157 74,41%
30 100% 575 100% 211 100%
Tabella 4.5: OpenStack Nova - Classificazione in base alla presenza di log ad alta severità.
Figura 4.1.6: OpenStack Nova - Classificazione in base alla presenza di log ad altaseverità.
Dalla figura 4.1.6, si può notare che:
• nel caso di Failure Round_1 & Round_2, OpenStack ha sempre riportato messaggi
con severity error, quindi è utile valutare la qualità di questi messaggi di log;
• nel caso di Failure Round_1 Only, nel 4,7% degli esperimenti (27 su 575 Failu-
re Round_1 Only), non sono stati registrati log ad alta severità, indicando lacune
nel sistema di logging e rilevamento degli errori; l’analisi può essere approfondita
per valutare un eventuale corrispondenza tra i fallimenti per sola asserzione e la
mancanza di log.
56
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
• nel caso di NO Failure, nel 25,59% degli esperimenti (54 su 211 NO Failure), sono
stati registrati log ad alta severità da OpenStack e questo è un comportamento ano-
malo. Un’analisi approfondita è utile per verificare la presenza di fallimenti, dovuti
alla propagazione, che i controlli del workload non hanno rilevato (e.g., nella fase
di clean-up non è presente né il meccanismo di check & retry, né quello di rileva-
mento di API ERROR), oppure si tratta di falsi positivi (quindi log che non hanno a
che fare con l’esecuzione del workload).
Per OpenStack Cinder, si riportano i risultati in tabella 4.6, aggregati in base al round
di fallimento. Gli stessi dati sono riportati in forma grafica in figura 4.1.7. Non si riporta
la stessa classificazione per Failure Round_2 Only, in quanto non sono state riscontrate
occorrenze per questa classe.
Classe di appartenenzaFailure
%Failure
% NO Failure %Round_1 and Round_2 Round_1 Only
OpenStack Log 6 100% 341 100% 5 20,83%NO OpenStack Log 0 0% 0 0% 19 79,17%
6 100% 341 100% 24 100%
Tabella 4.6: OpenStack Cinder - Classificazione in base alla presenza di log ad altaseverità.
In riferimento alla figura 4.1.7, si possono fare considerazioni simili a quelle fatte per il
caso di Nova. In particolare, il sistema non riporta messaggi con severity error nel caso
di fallimenti di entrambi i round e del solo round_1, mentre nel caso NO Failure riporta
dei log ad alta severità, fornendo degli esperimenti che possono essere approfonditi (per
le stesse considerazioni fatte prima).
4.2 RQ1 (Manifestazione)
In questa sezione si discutono i risultati ponendo l’enfasi sulla capacità del sistema di
dichiararsi fallito, così da rispondere alla domanda “In presenza di un fallimento di uno
57
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figura 4.1.7: OpenStack Cinder - Classificazione in base alla presenza di log ad altaseverità.
o più componenti, il sistema è capace di dichiararsi fallito nel caso in cui non riesce a
portare a termine con successo una richiesta?”.
Per l’analisi l’attenzione è posta sugli esperimenti appartenenti alle classi Failure, per i
quali il workload ha registrato un fallimento per sola asserzione, per sola API ERROR
o entrambi. In particolare, la presenza di un fallimento per asserzione, denota l’inca-
pacità del sistema di comunicare all’utente che la richiesta non è stata soddisfatta, ed è
importante analizzare questi casi al fine di suggerire dei miglioramenti ai meccanismi di
fault-tolerance, rendendo così OpenStack più affidabile.
Nella sezione 4.1 sono state riportate le statistiche sui fallimenti per i due sottosistemi
target (Nova e Cinder), classificando gli esperimenti in base al fallimento per round (ri-
spettivamente, tabella 4.1 e figura 4.1.2 per Nova, tabella 4.2 e figura 4.1.3 per Cinder),
e successivamente è stata applicata una classificazione per tipo di fallimento (rispettiva-
mente, tabella 4.3 e figura 4.1.4 per Nova, tabella 4.4 e figura 4.1.5 per Cinder). Queste
statistiche forniscono una panoramica sui tipi di fallimenti registrati.
58
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Gli stessi dati possono essere analizzati in maniera differente riportando il tipo di as-
serzione registrata per ogni esperimento. Questo tipo di informazione, infatti, potrebbe
essere utile per individuare le cause di fallimento più frequenti, indirizzando su queste
l’attenzione degli sviluppatori (e.g., se il tipo di asserzione più frequente riguarda la crea-
zione di un volume, significa che si devono apportare miglioramenti a Cinder, per esempio
aggiungendo o riprogettando meccanismi di rilevamento degli errori).
Per OpenStack Nova, i risultai dell’analisi dei tipi di asserzione sono riportati in tabella
4.7. Gli stessi dati sono riportati in forma grafica in figura 4.2.1.
Tipo di Asserzione Occorrenze %
FAILURE INSTANCE ACTIVE 502 89,01%FAILURE SSH 45 7,98%
FAILURE VOLUME ATTACHED 17 3,01%564 100%
Tabella 4.7: OpenStack Nova - Tipi di Assertion Failure.
Figura 4.2.1: OpenStack Nova - Tipi di Assertion Failure.
Per quanto riguarda i dati riportati, sono state considerate anche le asserzioni multiple
che è possibile trovare in alcuni esperimenti, e le possibili asserzioni registrate durante
l’esecuzione del round_2 (e.g., nel caso di esperimenti falliti nel round_1 e round_2),
così da riportare tutti i fallimenti per asserzione registrati.
Per OpenStack Cinder, si riportano gli stessi risultati in tabella 4.8 e figura 4.2.2. Valgo-
no le stesse considerazioni fatte per Nova, per quanto riguarda le asserzioni considerate.
59
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Tipo di Asserzione Occorrenze %
FAILURE INSTANCE ACTIVE 333 73,03%FAILURE VOLUME CREATED 113 24,77%
FAILURE_SSH 7 1,54%FAILURE VOLUME ATTACHED 3 0,66%
456 100%
Tabella 4.8: OpenStack Cinder - Tipi di Assertion Failure.
Figura 4.2.2: OpenStack Cinder - Tipi di Assertion Failure.
Per entrambi i sottosistemi, si riscontra che l’asserzione con maggior numero di occorren-
ze è FAILURE INSTANCE ACTIVE, rispettivamente 89,01% (502 su 564 asserzioni regi-
strate) per Nova, e 73,03% (333 su 456 asserzioni registrate) per Cinder. Inoltre, per Nova
sono state registrate asserzioni per FAILURE SSH e FAILURE VOLUME ATTACHED,
rispettivamente a 7,98% e 3,01%. Per Cinder, si riscontra una percentuale alta anche per
l’asserzione FAILURE VOLUME CREATED, al 24,77% (113 su 456 asserzioni registra-
te), mentre FAILURE SSH e FAILURE VOLUME ATTACHED sono rispettivamente al
1,54% e 0,66%.
Una possibile strategia, in questo caso, potrebbe essere quella di aggiungere un mecca-
nismo simile a quello utilizzato per rilevare l’asserzione, per esempio un controllo sullo
stato attivo dell’istanza a valle della sua creazione (nel caso di FAILURE INSTANCE AC-
TIVE), o sull’esistenza e stato disponibile del volume a valle della richiesta di creazione
(nel caso di FAILURE VOLUME CREATED). Nel caso di fallimento del controllo di
60
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
consistenza, si potrebbe lanciare un’eccezione che sarebbe gestita altrove, prevedendo
una notifica agli altri componenti del sistema, all’utente e registrazione di log ad alta
severità.
Di seguito, si riportano i fallimenti delle chiamate API che hanno portato all’interruzione
dell’esecuzione del workload nei vari esperimenti. Questi rappresentano i casi in cui il
servizio/sistema ha manifestato l’occorrenza di un fallimento in risposta a una chiamata
all’API del servizio, ritornando un codice di errore HTTP (e.g., codici 40x per errori
causati dalla richiesta, o 50x per indicare che il servizio non è in grado di soddisfare la
richiesta, in quanto ha riscontrato un errore interno) e una descrizione, rappresentativi del
problema rilevato (e.g., Impossibile ’attach_volume’ l’istanza xxx-x-x-x-xxx mentre si
trova in vm_state error (HTTP 409)).
Per OpenStack Nova, in tabella 4.9 si riporta la distribuzione dei fallimenti per API
ERROR . Gli stessi dati sono riportati in forma grafica in figura 4.2.3.
Tipo di API ERROR Occorrenze %
openstack server add volume 468 81,96%openstack server create 75 13,13%
nova list 23 4,03%openstack keypair create 3 0,53%openstack server reboot 2 0,35%
571 100%
Tabella 4.9: OpenStack Nova - Tipi di API ERROR.
Figura 4.2.3: OpenStack Nova - Tipi di API ERROR.
61
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Dai dati riportati per Nova, si nota subito che il maggior numero di richieste fallite ri-
guarda l’attach del volume all’istanza precedentemente creata (fallimento della richiesta
openstack server add volume), con una percentuale dell’ 81,96% (468 su 571 fallimenti
api totali). Il dato è confermato dal fatto che, per lo stesso sottosistema, sono state rilevate
502 asserzioni di tipo FAILURE INSTANCE ACTIVE, e di conseguenza tutte le richie-
ste di attach del volume per queste istanze falliscono, poiché l’istanza non è in uno stato
attivo.
Si riscontrano anche fallimenti per richieste di creazione dell’istanza (openstack server
create), con una percentuale del 13,13% (75 su 571 fallimenti api), e fallimenti delle
richieste di visualizzazione delle istanze create (nova list), con una percentuale del 4,03%
(23 su 571 fallimenti api).
Per OpenStack Cinder, in tabella 4.10 si riporta la distribuzione dei fallimenti per API
ERROR . Gli stessi dati sono riportati in forma grafica in figura 4.2.4.
Tipo di API ERROR Occorrenze %
openstack server add volume 289 83,28%openstack volume create 34 9,80%
openstack volume list 23 6,63%cinder list 1 0,29%
347 100%
Tabella 4.10: OpenStack Cinder - Tipi di API ERROR.
Figura 4.2.4: OpenStack Cinder - Tipi di API ERROR.
62
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Anche per Cinder, possono essere fatte considerazioni molto simili a quelle fatte per il
sottosistema Nova. In particolare, nell’ 83,28% dei fallimenti api registrati (289 su 347
totali), fallisce la richiesta di attach del volume all’istanza precedentemente creata (in
333 casi su 456 fallimenti per asserzione, lo stato dell’istanza non risulta attivo, vedi
4.8). Si riscontrano anche fallimenti per richieste di creazione del volume (openstack
volume create), con percentuale 9,8% (34 su 347 totali), e fallimenti delle richieste di
visualizzazione dei volumi creati (cinder list), con una percentuale del 6,63% (23 su 347
fallimenti api).
Prima di concludere, si riportano in forma aggregata i dati precedentemente discussi,
così da valutare il numero di fallimenti rilevati sul totale di quelli registrati dal workload
(riportati in tabella 4.11, e graficamente in figura 4.2.5).
Tipo di Fallimento Occorrenze %
Assertion Failure 1020 52,63%API ERROR 918 47,37%
1938 100%
Tabella 4.11: OpenStack Nova/Cinder - Fallimenti totali registrarti.
Figura 4.2.5: OpenStack Nova/Cinder - Fallimenti totali registrarti.
63
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
4.3 RQ2 (Logging)
In questa sezione si discutono i risultati ottenuti ponendo l’enfasi sull’efficacia dei mecca-
nismi di logging e rilevamento degli errori, così da rispondere alla domanda “In presenza
di un fallimento di uno o più componenti, i meccanismi di logging implementati riescono
a rilevarne l’occorrenza mediante messaggi ad alta severità?”.
Per l’analisi innanzitutto si possono considerare gli esperimenti appartenenti alle classi
Failure per i quali non è stato registrato alcun log ad alta severità (NO OpenStack Log).
Potrebbe essere utile approfondire anche gli esperimenti che hanno esibito un fallimento
per Assertion Failure & API ERROR e durante i quali il sistema ha loggato messaggi ad
alta severità. Infatti, in questi casi, è possibile che sia stato registrato un fallimento per
asserzione, ma che il servizio non si sia accorto del fallimento e di conseguenza i log ad
alta severità sono relativi al solo fallimento per API ERROR.
Valutando solo il caso in cui si considera una combinazione Failure + NO OpenStack Log,
si può affermare che:
1. per OpenStack Nova, l’analisi ha riscontrato un fallimento dei meccanismi di log-
ging nel 4,46% degli esperimenti (27 esperimenti su 605 falliti), e per questi espe-
rimenti un’analisi più approfondita può essere utile per suggerire miglioramenti ai
meccanismi di rilevamento e segnalazione;
2. per OpenStack Cinder, l’analisi non ha riportato occorrenze per questa classe di
esperimenti.
Di seguito, si discutono due esperimenti relativi a OpenStack Nova, classificati rispettiva-
mente come:
• Esperimento1: Failure Round_1 Only -> Assertion Failure Only -> NO OpenStack
Log.
• Esperimento2: Failure Round_1 Only -> Assertion Failure & API ERROR -> NO
OpenStack Log.
64
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Esperimento1 In questo esperimento, durante l’esecuzione del workload è stato registra-
to un fallimento per asserzione, dovuto all’impossibilità di completare l’operazione
di attach di un volume precedentemente creato. Il fallimento è percepito solo lato
utente, infatti la chiamata API relativa è effettuata con successo e non viene regi-
strato alcun messaggio con alta severità da OpenStack, anche se effettivamente la
richiesta non è stata sodisfatta.
In tabella 4.12, si riportano le informazioni del FIP (contenute in fip_info.data).
TIPO DI FAULT OPENSTACK_MISSING_FUNCTION_CALL-VOLUMECOMPONENTE TARGET /nova/virt/libvirt/driver.py
CLASSE TARGET LibvirtDriverFUNZIONE TARGET _connect_volumePUNTO INIEZIONE vol_driver.connect_volume(connection_info, disk_info, instance)
Tabella 4.12: Informazioni del FIP
In figura 4.3.1 è riportato il codice sorgente mutato.
Figura 4.3.1: Esperimento 1 - Codice mutato.
Essendo il fault di tipo MISSING FUNCTION CALL, la chiamata viene sostituita con
l’istruzione pass1 e non verrà eseguita, impedendo di completare la richiesta di attach del
volume.
Questo comportamento è tipico degli esperimenti con questo tipo di fault (omissione di
chiamata), e in molti casi il servizio non rileva il fallimento della richiesta. In questi casi,
una strategia di miglioramento potrebbe essere quella di aggiungere dei meccanismi di
check sui valori ritornati dalle funzioni, o in generale verificare il risultato di una richie-
sta (e.g., se è richiesto l’attach del volume, verificare che questi sia associato all’istanza
specificata al ritorno dalla chiamata).1pass è un’operazione nulla -- quando viene eseguita, non succede niente.
65
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Esperimento2 In questo esperimento, il workload ha registrato un fallimento per asser-
zione e un fallimento della chiamata API, ritornata con un codice di errore HTTP
409. Analizzando l’error.log, si può notare che l’asserzione registrata è relativa al
controllo sullo stato dell’istanza precedentemente creata (il meccanismo di check
& retry verifica che l’istanza sia in uno stato attivo), mentre il fallimento per API
ERROR è relativo alla richiesta di attach del volume alla stessa istanza, bloccata in
uno stato inconsistente. In questo caso, il servizio notifica all’utente l’impossibilità
di completare la richiesta, ma non registra alcun log ad alta severità.
In tabella 4.13, si riportano le informazioni del FIP (contenute in fip_info.data).
TIPO DI FAULT OPENSTACK_WRONG_RETURN_VALUE-INSTANCECOMPONENTE TARGET /nova/db/api.py
CLASSE TARGET NoneFUNZIONE TARGET instance_update_and_get_originalPUNTO INIEZIONE return rv
Tabella 4.13: Informazioni del FIP
In figura 4.3.2è riportato il codice sorgente mutato.
Figura 4.3.2: Esperimento 2 - Codice mutato.
In questo esperimento, il fault è iniettato in una delle funzioni che definiscono le interfacce
di accesso al DB, ed essendo il fault di tipo WRONG RETURN VALUE, il valore di
ritorno della funzione viene corrotto dalla funzione pycc_corrupt() in base al suo tipo
(e.g., int, str, dict, etc.). Una volta iniettato il guasto, l’attivazione avviene a seguito della
creazione dell’istanza, in particolare quando il sistema tenta di aggiornare le informazioni
sull’istanza.
Analizzando in modo approfondito i log di Nova, si nota un messaggio con severità
WARNING che riporta un errore generato dall’interprete Python, il quale potrebbe da-
66
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
re maggior informazioni su quanto successo durante l’esecuzione del workload (figura
4.3.3).
Figura 4.3.3: Esperimento 2 - Estratto Log.
Il timestamp del log generato è molto vicino (dal punto di vista temporale) ai timestamp
relativi all’attivazione del fault, riportati nel trigger.log (figura 4.3.4).
Figura 4.3.4: Esperimento 2 - Estratto trigger.log.
In questo caso, per migliorare il sistema di logging, sarebbe utile assegnare una severità
maggiore a questo tipo di messaggi, così da essere rilevati come log ad alta severità.
4.4 RQ3 (Propagazione)
In questa sezione si discutono i risultati ottenuti al fine di valutare il modo in cui l’attiva-
zione di un guasto impatta sul resto del sistema, così da rispondere alla domanda “In pre-
senza di un fallimento di uno o più componenti, i meccanismi di fault-tolerance implemen-
tati riescono ad arginare l’effetto dei guasti nel sistema, sia in termini di propagazione
temporale che di propagazione spaziale?”
Per l’analisi, l’attenzione è posta sugli esperimenti appartenenti alle classi Failure, per i
quali il workload ha registrato un fallimento per sola asserzione, per sola API ERROR o
entrambi.
Dal punto di vista della propagazione temporale, è importate identificare i casi in cui si
registra un elevata latenza, intesa come l’intervallo di tempo che intercorre tra l’istante di
attivazione del guasto (informazione che viene registrata nel trigger.log durante l’esecu-
zione del round_1 di ogni esperimento), e l’istante in cui viene registrata l’API ERROR,
67
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
che determina l’interruzione dell’esecuzione del workload. Nei casi in cui questa si ve-
rifica questa condizione, il sistema non ha esibito un comportamento fail-stop in quanto
non è riuscito a rilevare prontamente una probabile condizione di errore, che protraendosi
nel tempo, potrebbe amplificare i suoi effetti sugli altri componenti del sistema.
Per gli esperimenti in cui sono stati registrati solo fallimenti per asserzione, non si possono
fare considerazioni per quanto riguarda la propagazione temporale, in quanto il sistema
non manifesta esplicitamente il fallimento del servizio.
Per OpenStack Nova, si riportano il grafico delle latenze in figura 4.4.1, con valori
riportati in secondi e ordinati in modo decrescente.
Figura 4.4.1: OpenStack Nova - Propagazione temporale.
Si possono notare casi in cui la latenza calcolata è veramente elevata, in quanto dall’i-
stante di attivazione all’istante di rilevamento con api error sono trascorsi anche diversi
minuti, e casi in cui invece il sistema ha rilevato quasi immediatamente l’occorrenza di
un fallimento, con latenze inferiori del secondo. Effettuando un’analisi più approfondita,
nella quale si sono distinti gli esperimenti falliti per Assertion Failure & API ERROR da
quelli falliti per API ERROR Only, si è riscontrato che nel secondo caso le latenze si abbat-
tono notevolmente nella maggior parte dei casi. Infatti, nel grafico sono state evidenziate
due regioni differenti, corrispondenti ai due tipi di fallimenti:
• nel caso di fallimenti per API ERROR Only, il sistema ha mostrato un comporta-
mento fail-stop, mostrando un ottima tolleranza ai guasti e rilevando subito l’errore;
68
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
• nel caso di fallimenti per Assertion Failure & API ERROR, la presenza di fallimenti
per asserzione indica che il sistema non è stato in grado di rilevare prontamente il
fallimento, favorendo la propagazione temporale.
In tabella 4.14, si riportano media e mediana delle latenze calcolate distinguendo i due
tipi di fallimento.
Tipo di fallimento Latenza Media Mediana della LatenzaAssertion Failure & API ERROR 195,57 175,29
API ERROR Only 4,75 0,21
Tabella 4.14: OpenStack Nova - Propagazione temporale per tipi di fallimento.
I risultati mostrano che per Assertion Failure & API ERROR la latenza media è 195,57
secondi, mentre per API ERROR Only scende notevolmente a 4,75 secondi. Allo stesso
modo, per Assertion Failure & API ERROR la mediana della latenza è apri a 175,29
secondi, mentre per API ERROR Only risulta 0,21 secondi. In questo caso, la mediana si
discosta molto dalle media, il che può essere giustificato dalla presenza di latenze molto
elevate che influenzano la media. Quindi si può considerare più attendibile la mediana in
questi casi.
Per OpenStack Cinder si riportano il grafico delle latenze in figura 4.4.2, con valori
riportati in secondi e ordinati in modo decrescente.
Figura 4.4.2: OpenStack Cinder - Propagazione temporale.
Anche in questo caso, si hanno casi in cui la latenza calcolata è molto elevata (e.g., più
di 450 secondi), e casi in cui il sistema ha rilevato quasi immediatamente l’occorrenza di
69
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
un fallimento (e.g., meno di 0,2 secondi). In questo caso, a differenza di quanto fatto per
Nova, non ha senso riportare sul grafico i casi in cui sono si hanno fallimenti di tipo API
ERROR Only, in quanto le occorrenze per questa classe sono appena 3.
In tabella 4.15, si riportano media e mediana delle latenze calcolate distinguendo i due
tipi di fallimento.
Tipo di fallimento Latenza Media Mediana della LatenzaAssertion Failure & API ERROR 82,00 82,61
API ERROR Only 0,26 0,21
Tabella 4.15: OpenStack Cinder - Propagazione temporale per tipi di fallimento.
I risultati mostrano che per Assertion Failure & API ERROR la latenza media è 82 secondi,
mentre per API ERROR Only scende notevolmente a 0,26 secondi. Allo stesso modo, per
Assertion Failure & API ERROR la mediana della latenza è apri a 82,61 secondi, mentre
per API ERROR Only risulta 0,21 secondi. In questo caso, i valori di media e media sono
abbastanza vicini, quindi la media è un buon indicatore.
Dal punto di vista della propagazione spaziale, è importante identificare i casi in cui si
ha una propagazione dell’errore tra diverse parti del sistema, in quanto questo porterebbe
portare al fallimento in cascata dei componenti del sistema.
Per quanto riguarda OpenStack Nova, al fine di analizzare la propagazione dei fallimenti
tra i diversi servizi del sistema, si sono valutati gli esperimenti in cui si è riscontrato un
fallimento del servizio in Nova (e.g., FAILURE INSTANCE ACTIVE), che successiva-
mente si è propagato fino a Cinder (e.g., FAILURE_VOLUME_ATTACH o fallimento
della chiamata API relativa). Inoltre, sono stati considerati anche i casi in cui il fallimento
è relativo solo al sottosistema Cinder, perché anche in questo caso l’errore si è propagato
da Nova a Cinder, provocandone il disservizio.
In tabella 4.16 si riportano i risultati relativi all’analisi della propagazione spaziale, con-
siderando il totale delle esecuzioni in cui si è riscontrato un fallimento, pari a 635. Gli
stessi dati, sono riportati graficamente in figura 4.4.3.
Dai dati riportati, si può notare:
70
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Tipi di fallimenti Occorrenze %Assertion Failure on Nova & API ERROR on Cinder 461 72,60%
Assertion Failure on Cinder 17 2,68%API ERROR on Cinder 7 1,10%
Esecuzioni senza propagazione 150 23,62%TOTALE ESECUZIONI CON FALLIMENTO 635 100%
Tabella 4.16: OpenStack Nova - Propagazione spaziale dei fallimenti.
Figura 4.4.3: OpenStack Nova - Propagazione spaziale dei fallimenti.
• nel 72,60% dei casi (461 su 635 esecuzioni con fallimento), l’esecuzione ha ripor-
tato un fallimento per asserzione su una richiesta indirizzata a Nova (in tutti i casi
l’asserzione registrata è FAILURE INSTANCE ACTIVE), e successivamente si è
registrato il fallimento per API ERROR di una chiamata all’API di Cinder (in tutti
i casi l’API ERROR registrata è openstack server add volume);
• nel 2,68% dei casi (17 su 635 esecuzioni con fallimento), si è riscontrato solo
un fallimento per asserzione su una richiesta indirizzata a Cinder, in particolare
FAILURE VOLUME ATTACHED;
• nel 1,10% dei casi (7 su 635 esecuzioni con fallimento), è stato registrato il solo fal-
limento per API ERROR di una chiamata a Cinder, in particolare openstack server
add volume;
• nei restanti casi, che rappresentano il 23,62% (150 su 635 esecuzioni con falli-
mento), il fallimento registrato è relativo a richieste indirizzate a Nova stesso (in
particolare: FAILURE INSTANCE ACTIVE, FAILURE SSH come asserzioni e
71
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
openstack server create, nova list, openstack keypair create, openstack server re-
boot come API ERROR), quindi in questi casi non si è avuta propagazione tra i due
sottosistemi.
I risultati ottenuti dimostrano la necessità di migliorare i meccanismi di fault-tolerance
implementati, così da arginare i fenomeni di propagazione dei fallimenti tra i diversi ser-
vizi. A tal proposito, una possibile strategia potrebbe essere quella effettuare un check
ridondante sul risultato di un’operazione (e.g., verificare che l’istanza sia in uno stato
attivo dopo la sua creazione), e nel caso propagare una notifica del problema agli altri
componenti del sistema, in modo da evitare situazioni inconsistenti.
E’ utile fare anche un’analisi approfondita dei fallimenti avvenuti in entrambi i round.
Questi casi sono relativi a situazioni in cui il sistema non è riuscito a limitare l’effetto del
guasto iniettato, anzi, anche dopo la rimozione del guasto nel round_2, il sistema continua
a fallire. Come discusso in 4.1.1, questi rappresentano il 3,68% (30 su 816 Completed)
per Nova e il 1,62% (6 su 371 Completed) per Cinder.
Per OpenStack Nova, in tabella 4.17si riportano le statistiche per il tipo di fallimento
(Assertion Failure e/o API ERROR) per entrambi i round. Gli stessi dati sono dati in
forma semplificata in figura 4.4.4.
Tipi di fallimenti per RoundOccorrenze %
Round_1 Round_2
openstack server createFAILURE INSTANCE ACTIVE
20 66,67%openstack server add volume
FAILURE_INSTANCE_ACTIVE FAILURE_INSTANCE_ACTIVE7 23,33%
openstack server add volume openstack server add volumeopenstack server create nova list 1 3,33%
FAILURE_INSTANCE_ACTIVEFAILURE_SSH 1 3,33%
openstack server add volumeFAILURE_INSTANCE_ACTIVE
nova list 1 3,33%nova list
30 100%
Tabella 4.17: OpenStack Nova - Fallimenti persistenti.
Dai risultati ottenuti, i tipi di fallimenti registrati per entrambi i round risultano così
distribuiti:
72
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Figura 4.4.4: OpenStack Nova - Fallimenti persistenti.
• nel 66,67% dei casi (20 su 30 fallimenti persistenti), la richiesta di creazione dell’i-
stanza ha generato un API ERROR nel Round_1, mentre nel Round_2 si è registra-
to un fallimento per FAILURE INSTANCE ACTIVE e successivamente è fallita la
richiesta di attach del volume;
• nel 23,33% dei casi (7 su 30 fallimenti persistenti), si è avuto lo stesso comporta-
mento nei due round, con un fallimento per asserzione e successivamente fallimento
della richiesta di attach del volume;
• in 1 caso, la creazione dell’istanza nel Round_1 ha provocato il fallimento della
richiesta nova list nel Round_2;
• in 1 caso, si è avuto un fallimento per FAILURE INSTANCE ACTIVE e succes-
sivamente richiesta di attach del volume nel Round_1, mentre nel Round_2 è stata
registrata un’asserzione per l’impossibilità di valutare la connettività dell’istanza;
• in 1 caso, si è avuto un fallimento per FAILURE INSTANCE ACTIVE e API ER-
ROR sulla richiesta nova list nel Round_1, e lo stesso fallimento per API ERROR
sulla chiamata nova list si è registrato anche nel Round_2.
Analizzare a fondo questi casi è importante, in quanto evidenziano l’incapacità del siste-
ma di recuperare dallo stato di errore in cui si è portato, o quantomeno il recupero non
risulta repentino. Durante l’esecuzione degli esperimenti, per ovviare a problemi di que-
73
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
sto tipo, si è cercato di ripristinare lo stato del sistema alla fine di ogni esperimento (e.g.,
riavviando i servizi, ripulendo i log, ripristinando lo stato del database di ogni servizio),
così da avere indipendenza tra gli esperimenti e uno stato consistente del sistema.
74
Conclusioni
In questa tesi si è effettuata una valutazione dell’affidabilità di OpenStack, una delle più
popolari piattaforme di cloud computing open source. Gli obbiettivi dello studio so-
no stati fissati definendo delle research questions, e successivamente è stata descritta la
metodologia utilizzata per rispondere alle domande prefissate.
Di seguito si riassumono le research questions definite e per ognuna di esse si riportano i
risultati ottenuti:
1. RQ1 - OpenStack è capace di dichiararsi fallito nel caso in cui non riesce a por-
tare a termine con successo una richiesta? In questo caso si vuole valutare la
capacita del sistema di manifestare esplicitamente l’occorrenza di un fallimento, e
quest’aspetto è importante da valutare. E’ importante sottolineare il fatto che, per
registrare il fallimento del servizio, all’interno del workload sono state inserite del-
le sonde che permettessero di rilevare Assertion Failure e API ERROR. I risultati
ottenuti mostrano che:
(a) nel 52,63% (1020 su 1938 totali) i fallimenti registrati sono per asserzione,
quindi il servizio non manifesta esplicitamente il fallimento della richiesta;
un’analisi più approfondita ha permesso di evidenziare che il tipo di asser-
zione più comune è per FAILURE INSTANCE ACTIVE, quindi il fallimento
registrato è relativo allo stato dell’istanza che resta inconsistente. L’utilizzo
dei meccanismi di check & retry si è dimostrato molto utile, in quanto ha per-
75
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
messo di rilevare fallimenti che altrimenti sarebbero passati inosservati, e solo
uno studio approfondito dei log forse avrebbe potuto portare alla luce.
(b) nei restanti casi, i fallimenti registrati sono per fallimento della chiamata API,
e un’analisi approfondita ha rilevato che la richiesta con più alto numero di
fallimenti è per l’attach del volume a un’istanza in uno stato non attivo.
2. RQ2 - In OpenStack i meccanismi di logging implementati riescono a rilevarne
l’occorrenza mediante messaggi ad alta severità? In questo caso di vuole valutare
l’efficacia del sistema di logging. L’analisi effettuata ha permesso di evidenziare
in modo puntuale gli esperimenti che hanno esibito un fallimento e per i quali il
logging ha mostrato delle lacune. Per il sottosistema Cinder non sono stati registrati
casi di assenza di messaggi ad alta severità, mentre per Nova è stata evidenziata una
piccola percentuale, pari al 4,46% degli esperimenti (27 esperimenti su 605 falliti).
Questi casi possono essere approfonditi per migliorare il sistema di logging.
3. RQ3 - In OpenStack i meccanismi di fault-tolerance implementati riescono ad ar-
ginare l’effetto dei guasti nel sistema, sia in termini di propagazione temporale che
di propagazione spaziale? In questo caso si vogliono analizzare i fenomeni di pro-
pagazione temporale e spaziale. Per la prima, l’analisi ha evidenziato che nei casi
in cui si è registrato un fallimento per sola API ERROR, la mediana della latenza
calcolata è pari a 0,21 secondi e il servizio ha esibito un comportamento fail-stop.
In presenza di asserzione, invece, la mediana calcolata è pari a 175,29 secondi. In
questi casi, meccanismi di check ridondati e notifica agli altri componenti del si-
stema, potrebbero limitare la propagazione temporale e favorire un comportamento
fail-stop. Per quanto riguarda la propagazione spaziale, l’analisi ha evidenziato casi
in cui il fallimento si propaga da Nova a Cinder. In particolare si è notato che la
mancanza di rilevamento di fallimenti per asserzione, ha propagato il fallimento tra
i due servizi.
76
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Infine, sono stati registrati anche casi in cui l’iniezione del guasto ha provocato effetti per-
manenti nel sistema (fallimenti Round_1 e Round_2), e questi casi sono utili da analizzare
per suggerire dei miglioramenti ai meccanismi di recovery.
77
Ringraziamenti
Giunti alla fine di questo percorso universitario, non posso fare altro che rivolgere un
pensiero alle persone che hanno contribuito al raggiungimento di questo traguardo.
Ringrazio il mio relatore, Prof. Domenico Controneo, perché mi ha permesso di lavorare
con alcune delle persone più preparate che ho incontrato durante il mio percorso di studi.
Ringrazio il Prof. Roberto Natella per il grande aiuto ricevuto durante questi mesi e per
aver avuto sempre pazienza nei miei confronti. Ricordo ancora il giorno in cui, nello
studio del Prof., hai esclamato “Benvenuti nel team!”, riferendoti a me e Pietro. Da quel
giorno non ho potuto fare altro che imparare.
Un sincero grazie va all’Ing. Luigi De Simone, mio correlatore, per l’enorme disponibilità
e attenzione dedicatami in questi mesi di tirocinio.
Desidero ringraziare mio padre per tutto quello che ha fatto per me, per non avermi mai
fatto pesare le scelte fatte, anzi, mi ha sempre invogliato a seguire i miei sogni. Ringrazio
mia madre per il sostegno dato, per le parole giuste, per la forza che mi ha saputo tra-
smettere in questi anni. Ringrazio le mie sorelle per aver sempre visto in me qualcosa di
speciale. Grazie di cuore!
Voglio ringraziare Pietro e Salvatore, vi considero come due fratelli. Mi avete aiutato
innumerevoli volte durante questo percorso, e molto di quello che sono oggi lo devo a
voi. Con voi ho condiviso la maggior parte di questi anni, giorni e notti passati insieme.
Spero di continuare a coltivare questa nostra amicizia per molti anni. Grazie ancora Pietro
perché senza di te avrei sicuramente perso la fiducia in me stesso.
78
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
Ringrazio i miei amici. Ammetto di avervi trascurato in questi ultimi mesi, ma sappiate
che un pensiero per voi l’ho sempre avuto.
Dedico questo mio ultimo pensiero alla mia fidanzata. Sei stata sempre al mio fianco
durante questi anni e non hai mai smesso di credere in me. Mi hai sempre ripetuto di
essere fiera di me, di essere orgogliosa di me. Dedico a te tutti gli sforzi di questi anni,
fatti per costruire un futuro, insieme. Chiudo questa pagina allo stesso modo in cui ho
chiuso quella della tesi triennale.
“A Te, che mi hai cambiato la vita”
79
Bibliografia
[1] G. Aceto, A. Botta, W. de Donato, and A. PescapÚ. Cloud monitoring: A survey.
Computer Networks, 57(9):2093 – 2115, 2013.
[2] A. Avizienis, J. C. Laprie, B. Randell, and C. Landwehr. Basic concepts and taxo-
nomy of dependable and secure computing. IEEE Transactions on Dependable and
Secure Computing, 1(1):11–33, Jan 2004.
[3] T. Banzai, H. Koizumi, R. Kanbayashi, T. Imada, T. Hanawa, and M. Sato. D-cloud:
Design of a software testing environment for reliable distributed systems using
cloud computing technology. In 2010 10th IEEE/ACM International Conference
on Cluster, Cloud and Grid Computing, pages 631–636, May 2010.
[4] E. Bauer and R. Adams. Reliability and availability of cloud computing. John Wiley
& Sons, 2012.
[5] S. Frey. Key performance indicators for cloud computing slas.
[6] H. Fujita, Y. Matsuno, T. Hanawa, M. Sato, S. Kato, and Y. Ishikawa. Ds-bench
toolset: Tools for dependability benchmarking with simulation and assurance. In
IEEE/IFIP International Conference on Dependable Systems and Networks (DSN
2012), pages 1–8, June 2012.
[7] M.-C. Hsueh, T. K. Tsai, and R. K. Iyer. Fault injection techniques and tools.
Computer, 30(4):75–82, Apr 1997.
80
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
[8] ISO. Product development: software level. ISO 26262: Road vehicles - Functional
safety, 2011.
[9] P. Joshi, H. S. Gunawi, and K. Sen. Prefail: A programmable tool for multiple-
failure injection. In Proceedings of the 2011 ACM International Conference on
Object Oriented Programming Systems Languages and Applications, OOPSLA ’11,
pages 171–188, New York, NY, USA, 2011. ACM.
[10] X. Ju, L. Soares, K. G. Shin, K. D. Ryu, and D. Da Silva. On fault resilience
of openstack. In Proceedings of the 4th Annual Symposium on Cloud Computing,
SOCC ’13, pages 2:1–2:16, New York, NY, USA, 2013. ACM.
[11] P. M. Mell and T. Grance. SP 800-145. The NIST Defi-
nition of Cloud Computing. Tech. Rep., [Online]. Availa-
ble: http://csrc.nist.gov/publications/nistpubs/800-145/
SP800-145.pdf National Institute of Standards and Technology, Gaithersburg,
MD, United States, 2011.
[12] NASA. NASA Software Safety Guidebook. NASA-GB-8719.13, 2004.
[13] Netflix. Hystrix. [Online]. Available:
https://github.com/Netflix/Hystrix/wiki.
[14] Netflix. The Simian Army. [Online]. Available:
https://github.com/Netflix/SimianArmy/wiki.
[15] OpenStack. Ceilometer. [Online]. Available:
https://www.openstack.org/software/releases/queens/components/ceilometer.
[16] OpenStack. OpenStack. [Online]. Available: https://www.openstack.org.
[17] C. Pham, D. Chen, Z. Kalbarczyk, and R. K. Iyer. Cloudval: A framework for
validation of virtualization environment in cloud infrastructure. In 2011 IEEE/IFIP
81
Dependability Assessment della Piattaforma di Cloud Computing OpenStack
41st International Conference on Dependable Systems Networks (DSN), pages 189–
196, June 2011.
[18] C. Rosenthal, L. Hochstein, A. Blohowiak, N. Jones, and A. Basiri. Chaos
engineering building confidence in system behavior through experiments, 2017.
[19] L. D. Simone. Towards fault propagation analysis in cloud computing ecosy-
stems. In 2014 IEEE International Symposium on Software Reliability Engineering
Workshops, pages 156–161, Nov 2014.
[20] M. Stine. Migrating to cloud-native application architectures, 2015.
[21] Zipkin. Zipkin. [Online]. Available: https://zipkin.io.
82