
Con l'aumentare dell'esperienza nel settore IT, inizi a notare che i sistemi hanno una loro personalità. Possono essere docili, silenziosi, capricciosi, o severi. Possono attrarti o respingerti. In ogni caso, devi "trovare un compromesso" con loro, navigando tra "insidie" e costruendo catene dei loro interazioni.
E così abbiamo avuto l'onore di costruire una piattaforma cloud, e per farlo è stato necessario "convincere" un paio di sottosistemi a lavorare con noi. Fortunatamente, abbiamo un "linguaggio API", mani abili e una grande dose di entusiasmo.
In questo articolo non ci sarà hardcore tecnico, ma una descrizione dei problemi che abbiamo affrontato nel costruire il cloud. Ho deciso di descrivere il nostro percorso come una leggerezza di fantasia tecnica su come abbiamo cercato un linguaggio comune con i sistemi e cosa ne è venuto fuori.
Benvenuti sotto.
Inizio del viaggio
Qualche tempo fa la nostra squadra ha ricevuto l'incarico di avviare una piattaforma cloud per i nostri clienti. Avevamo il supporto della direzione, risorse, un'infrastruttura hardware e libertà nella scelta delle tecnologie per realizzare la parte software del servizio.
C'erano anche alcuni requisiti:
- il servizio ha bisogno di un'interfaccia utente comoda;
- la piattaforma deve essere integrata nel sistema di fatturazione esistente;
- la parte software e hardware: OpenStack + Tungsten Fabric (Open Contrail), di cui i nostri ingegneri hanno acquisito una buona padronanza.
Racconteremo in un'altra occasione come è stata formata la squadra, come è stato sviluppato l'interfaccia dell'account personale e come sono state prese le decisioni di design, se la comunità di Habr sarà interessata.
Gli strumenti che abbiamo deciso di utilizzare:
- Python + Flask + Swagger + SQLAlchemy — un insieme Python abbastanza standard;
- Vue.js per il frontend;
- abbiamo deciso di gestire l'interazione tra i componenti e i servizi utilizzando Celery sopra AMQP.
Anticipando le domande sulla scelta di Python, spiego. Il linguaggio ha trovato la sua nicchia nella nostra azienda e intorno ad esso si è sviluppata una piccola, ma pur sempre una cultura. Pertanto, è stato deciso di iniziare a costruire il servizio proprio su di esso. Inoltre, la velocità di sviluppo in compiti di questo tipo spesso fa la differenza.
Quindi, iniziamo il nostro incontro.
Bill il Silenzioso — fatturazione
Con questo tipo di persona ci conosciamo da tempo. È sempre seduto lì accanto e contava qualcosa in silenzio. A volte ci passava le richieste degli utenti, emetteva fatture ai clienti, gestiva i servizi. Un ragazzo normale e laborioso. Tuttavia, c'erano delle difficoltà. Era riservato, a volte pensieroso e spesso — nel suo mondo.

La fatturazione è il primo sistema con cui abbiamo cercato di familiarizzare. E la prima difficoltà ci si è presentata durante l'elaborazione dei servizi.
Ad esempio, durante la creazione o la cancellazione, il compito finisce in una coda interna della fatturazione. In questo modo è realizzato un sistema di lavoro asincrono con i servizi. Per elaborare i nostri tipi di servizi dovevamo "accumulare" i nostri compiti in questa coda. E qui ci siamo scontrati con un problema: la mancanza di documentazione.

Dalla descrizione dell'API, sembra che sia comunque possibile risolvere questo compito, ma non abbiamo avuto tempo per dedicarci al reverse engineering, quindi abbiamo estratto la logica e organizzato una coda di compiti sopra RabbitMQ. L'operazione sul servizio è innescata dal cliente dal proprio pannello di controllo, avvolta in un 'compito' Celery sul backend e viene eseguita dal sistema di fatturazione e OpenStack. Celery consente di gestire in modo abbastanza comodo i compiti, organizzare i retry e monitorare lo stato. Per saperne di più su 'Celery' si può leggere, ad esempio, .
Inoltre, il sistema di fatturazione non ha stoppato il progetto quando i fondi sono finiti. Parlando con gli sviluppatori, abbiamo scoperto che durante il calcolo delle statistiche (e noi dobbiamo implementare proprio questa logica) esiste una complessa interrelazione delle regole di interruzione. Ma questi modelli non si adattano bene alle nostre realtà. Abbiamo anche implementato questa logica tramite compiti su Celery, portando sul backend la gestione dei servizi.
Entrambe le problematiche sopra citate hanno portato a un certo appesantimento del codice e in futuro dovremo occuparci del refactoring per separare la logica di gestione delle attività in un servizio dedicato. Dobbiamo anche conservare parte delle informazioni sugli utenti e sui loro servizi nelle nostre tabelle per sostenere questa logica.
Un altro problema è il silenzio.
Su alcune richieste all'API, Billi risponde silenziosamente con un «Ok». Ad esempio, è successo quando effettuavamo accrediti dei pagamenti promessi durante la fase di test (di cui parlerò più tardi). Le richieste venivano eseguite correttamente e non vedevamo errori.

Ho dovuto esaminare i log, lavorando con il sistema tramite l'interfaccia utente. Si è scoperto che il billing stesso esegue tali richieste, cambiando lo scope per un utente specifico, ad esempio, admin, passando questo come parametro su.
Nel complesso, nonostante le lacune nella documentazione e piccoli difetti nell'API, tutto è andato abbastanza bene. I log sono leggibili anche con un carico elevato, se si comprende come sono strutturati e cosa cercare. La struttura del database è complicata ma del tutto logica e in alcuni aspetti persino attraente.
Quindi, riassumendo, i principali problemi che abbiamo incontrato durante l'interazione riguardano le peculiarità di implementazione del sistema specifico:
- funzionalità non documentate che ci hanno coinvolto in un modo o nell'altro;
- codice sorgente chiuso (la fatturazione è scritta in C++), di conseguenza — impossibilità di risolvere il problema 1 in alcun modo, se non attraverso il "metodo di prova ed errore".
Fortunatamente, il prodotto ha un API abbastanza ampia e abbiamo integrato nel nostro pannello personale i seguenti sotto-sistemi:
- modulo di assistenza tecnica — le richieste dal pannello personale vengono "proxyizzate" nella fatturazione in modo trasparente per i clienti del servizio;
- modulo finanziario — consente di emettere fatture ai clienti attuali, effettuare addebiti e generare documenti di pagamento;
- modulo di gestione dei servizi — per questo abbiamo dovuto implementare il nostro gestore. L'espandibilità del sistema ha lavorato a nostro favore e abbiamo "istruito" Billy a un nuovo tipo di servizi.
È stato un po' di lavoro, ma in un modo o nell'altro, penso che andremo d'accordo con Billy.
Passeggiate nei campi di tungsteno — Tungsten Fabric
Campi di tungsteno costellati di centinaia di cavi che trasmettono migliaia di bit di informazioni. Le informazioni vengono raccolte in "pacchetti", elaborate, creando percorsi complessi, come per magia.

Questo è il regno del secondo sistema con cui abbiamo dovuto fare amicizia: Tungsten Fabric (TF), precedentemente noto come OpenContrail. Il suo compito è gestire l'hardware di rete, fornendo un'astrazione software a noi utenti. TF è SDN, che incapsula una logica complessa per lavorare con l'hardware di rete. Ci sono articoli interessanti sulla tecnologia, ad esempio, .
Il sistema è integrato con OpenStack (di cui parleremo più avanti) tramite il plugin di Neutron.

Interazione dei servizi OpenStack.
Siamo stati introdotti a questo sistema dai ragazzi del reparto operativo. Utilizziamo l'API del sistema per gestire lo stack di rete dei nostri servizi. Finora non abbiamo avuto problemi seri o disagi (non mi prendo la responsabilità di parlare per i ragazzi dell'OE), tuttavia ci sono stati alcuni eventi curiosi durante l'interazione.
Il primo si è presentato così: i comandi che richiedevano l'output di un gran numero di dati sulla console dell'istanza durante la connessione SSH semplicemente "bloccavano" la connessione, mentre tutto funzionava correttamente su VNC.

Per chi non è familiare con il problema, può sembrare piuttosto divertente: ls /root funziona correttamente, mentre, ad esempio, top «si blocca» completamente. Fortunatamente, abbiamo già affrontato problemi simili. Si è risolto ottimizzando l'MTU sul percorso dalle nodi compute ai router. A proposito, questo non è un problema di TF.
La prossima problematica ci attendeva dietro l'angolo. In un «meraviglioso» momento, la magia del routing è svanita, così, all'improvviso. TF ha smesso di gestire il routing sull'hardware.

Abbiamo lavorato con OpenStack a livello di admin e poi siamo passati al livello dell'utente necessario. SDN, a quanto pare, «intercetta» il dominio dell'utente con cui vengono eseguite le azioni. Il fatto è che questo stesso account admin viene utilizzato per collegare TF e OpenStack. Durante il passaggio all'utente, la «magia» svaniva. Abbiamo deciso di creare un account separato per lavorare con il sistema. Questo ha permesso di operare senza compromettere la funzionalità dell'integrazione.
Forme di vita siliconiche — OpenStack
Una creatura siliconica di forma bizzarra vive vicino ai campi di tungsteno. Ricorda molto un bambino gigante, in grado con un solo colpo di schiacciarci, ma non mostra segni evidenti di aggressività. Non provoca paura, ma le sue dimensioni instillano preoccupazione. Così come la complessità di ciò che accade intorno.

OpenStack è il nucleo della nostra piattaforma.
OpenStack ha diversi sottosistemi, dei quali al momento utilizziamo principalmente Nova, Glance e Cinder. Ognuno di essi ha la propria API. Nova gestisce le risorse di calcolo e la creazione di istanze, Cinder gestisce i volumi e le loro istantanee, mentre Glance è il servizio di immagini che gestisce i template del sistema operativo e le relative informazioni.
Ogni servizio viene eseguito in un contenitore, mentre il broker dei messaggi è il 'coniglio bianco' — RabbitMQ.
Questo sistema ci ha dato più problemi inaspettati.
E il primo problema non ha tardato ad arrivare quando abbiamo cercato di collegare un volume aggiuntivo al server. L'API di Cinder si è categoricamente rifiutata di eseguire questa operazione. Più precisamente, a sentire OpenStack, la connessione viene stabilita, ma all'interno del server virtuale il dispositivo di disco risulta assente.

Abbiamo deciso di "aggirare" il problema e abbiamo richiesto la stessa azione all'API Nova. Il risultato è che il dispositivo si connette correttamente ed è accessibile all'interno del server. Sembra che il problema si verifichi quando lo storage a blocchi non risponde a Cinder.
Un'ulteriore difficoltà ci attendeva durante il lavoro con i dischi. Non siamo riusciti a scollegare il volume di sistema dal server.
Ancora una volta, lo stesso OpenStack "giura" di aver distrutto la connessione e ora è possibile lavorare correttamente con il volume separatamente. Ma l'API si è categoricamente rifiutata di eseguire operazioni sul disco.

Qui abbiamo deciso di non combattere troppo, ma di cambiare approccio sulla logica operativa del servizio. Dato che esiste un'istanza, deve esserci anche un volume di sistema. Pertanto, l'utente non può ancora eliminare o disattivare il "disco" di sistema senza prima eliminare il "server".
OpenStack è un complesso sistema piuttosto complicato con la propria logica di interazione e un'API tortuosa. Ci aiuta una documentazione abbastanza dettagliata e, naturalmente, il metodo di tentativi ed errori (come potremmo fare senza di esso).
Avvio del test
Il test è stato condotto a dicembre dello scorso anno. L'obiettivo principale era verificare il nostro progetto in modalità operativa sia dal punto di vista tecnico che dell'UX. Abbiamo invitato un pubblico selezionato e il test è stato chiuso. Tuttavia, abbiamo anche lasciato la possibilità di richiedere l'accesso al testing sul nostro sito.
Ovviamente, il test non è stato privo di momenti curiosi, poiché le nostre avventure sono appena iniziate.
Innanzitutto, abbiamo sottovalutato l'interesse per il progetto e abbiamo dovuto aggiungere rapidamente nodi di calcolo durante il test. È un caso comune per un cluster, ma c'erano anche delle peculiarità. Nella documentazione per la versione specifica di TF è indicata una versione specifica del kernel, sulla quale è stato testato il funzionamento con vRouter. Abbiamo deciso di avviare nodi con kernel più recenti. Il risultato è stato che TF non ha ricevuto percorsi dai nodi. Abbiamo dovuto ripristinare urgentemente i kernel.

Un altro imprevisto è legato alla funzionalità del pulsante "cambia password" nel pannello di controllo.
Abbiamo deciso di utilizzare JWT per gestire l'accesso al pannello utente, in modo da non dover lavorare con le sessioni. Poiché i sistemi sono molto diversi e ampiamente distribuiti, gestiamo il nostro token, che «incapsula» le sessioni di fatturazione e il token di OpenStack. Ovviamente, al cambiamento della password, il token «scade», poiché i dati dell'utente non sono più validi e devono essere riemessi.

Abbiamo trascurato questo aspetto e purtroppo non avevamo risorse per completare rapidamente questo pezzo. Abbiamo dovuto eliminare funzionalità proprio prima del lancio del test.
Attualmente disconnettiamo l'utente se la password è stata cambiata.
Nonostante queste complessità, i test sono andati bene. In poche settimane, circa 300 persone sono venute a visitarci. Siamo riusciti a vedere il prodotto con gli occhi degli utenti, testarlo in azione e raccogliere un feedback qualitativo.
To be continued
Per molti di noi, questo è il primo progetto di tale portata. Abbiamo appreso una serie di lezioni preziose su come lavorare in squadra, prendere decisioni architettoniche e di design. Come integrare sistemi complessi con risorse limitate e pubblicarli in produzione.
Naturalmente, c'è molto da migliorare sia nel codice che nell'integrazione dei sistemi. Il progetto è ancora giovane, ma siamo pieni di ambizioni per farne un servizio affidabile e user-friendly.
Siamo già riusciti a convincere i sistemi. Bill si occupa diligentemente dei conteggi, delle fatturazioni e delle richieste degli utenti nella sua stanzetta. La «magia» dei campi di tungsteno ci garantisce una connessione stabile. Solo OpenStack a volte fa capricci, lanciando messaggi come «’WSREP has not yet prepared node for application use». Ma questa è un'altra storia…
Poco tempo fa abbiamo lanciato il servizio.
Puoi trovare tutti i dettagli sul nostro .

Team di sviluppo CLO
Link utili
OpenStack
Tungsten Fabric
Fonte: habr.com
