{"id":52389,"date":"2019-11-07T00:00:00","date_gmt":"2019-11-06T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions"},"modified":"2020-02-18T14:00:05","modified_gmt":"2020-02-18T11:00:05","slug":"kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","title":{"rendered":"Come viene implementata un'architettura web resiliente nella piattaforma Mail.ru Cloud Solutions","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Come viene implementata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/fe7af07f3ac5ca4e75009993b742293e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCiao, Habr! Sono Artem Karamyshev, il responsabile del team di amministrazione di sistema. <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/\">Mail.Ru Cloud Solutions (MCS)<\/a><\/noindex>. Negli ultimi anno abbiamo lanciato molti nuovi prodotti. Volevamo assicurarci che i servizi API potessero scalare facilmente, fossero fault-tolerant e pronti a una rapida crescita del carico degli utenti. La nostra piattaforma \u00e8 basata su OpenStack e voglio raccontare quali problemi di tolleranza ai guasti dei componenti abbiamo dovuto affrontare per ottenere un sistema resistente. Penso che questo possa interessare chi sta sviluppando prodotti su OpenStack.<\/p>\n<p>La tolleranza ai guasti della piattaforma deriva dalla robustezza dei suoi componenti. Quindi passeremo gradualmente attraverso tutti i livelli in cui abbiamo identificato rischi e li abbiamo affrontati.<\/p>\n<p>Puoi guardare la versione video di questa storia, che ha avuto origine da una presentazione alla conferenza Uptime Day 4, organizzata da <noindex><a rel=\"nofollow\" href=\"http:\/\/www.itsumma.ru\">ITSumma<\/a><\/noindex>, su <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=3b06MVou-vg&amp;list=PLmXjIrLllpkjwuIGkzBkLbI7oHtUadmvZ&amp;index=5\">canale YouTube della Uptime Community<\/a><\/noindex>. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Tolleranza ai guasti dell'architettura fisica<\/h2>\n<p>\nLa parte pubblica della nuvola MCS \u00e8 attualmente basata in due data center di livello Tier III, tra i quali \u00e8 presente una fibra ottica scura dedicata, riservata a livello fisico attraverso diverse rotte, con una capacit\u00e0 di 200 Gbit\/s. Il livello Tier III garantisce il necessario livello di tolleranza ai guasti per l'infrastruttura fisica. <\/p>\n<p>La fibra ottica scura \u00e8 riservata sia a livello fisico che logico. Il processo di riservazione dei canali \u00e8 stato iterativo, ci sono stati problemi e stiamo continuamente migliorando la connessione tra i data center. <\/p>\n<blockquote><p>Ad esempio, recentemente durante i lavori in una fossa vicino a uno dei data center, un escavatore ha colpito un tubo che conteneva sia il cavo ottico principale sia quello di riserva. Il nostro canale di comunicazione a prova di guasto con il data center si \u00e8 rivelato vulnerabile in un solo punto, nella fossa. Di conseguenza, abbiamo perso parte dell'infrastruttura. Abbiamo tratto delle conclusioni e abbiamo intrapreso diverse azioni, tra cui l'installazione di ulteriore fibra ottica attraverso una fossa vicina.<\/p><\/blockquote>\n<p>\nNei data center ci sono punti di presenza dei provider di telecomunicazioni, a cui trasmettiamo i nostri prefissi tramite BGP. Per ogni direzione di rete viene scelta la migliore metrica, che consente di garantire ai vari clienti la migliore qualit\u00e0 di connessione. Se la connessione tramite un provider si interrompe, ristrutturiamo il nostro instradamento attraverso i provider disponibili.<\/p>\n<p>In caso di guasto di un provider, passiamo automaticamente al successivo. In caso di guasto di uno dei data center, abbiamo una copia speculare dei nostri servizi nel secondo data center, che prende in carico tutto il carico.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene implementata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/295ca212f48dd074d834154666e5b0c3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Affidabilit\u00e0 dell'infrastruttura fisica<\/i><\/p>\n<h2>Cosa utilizziamo per l'affidabilit\u00e0 a livello di applicazioni<\/h2>\n<p>\nIl nostro servizio \u00e8 costruito su una serie di componenti open source. <\/p>\n<p><b>ExaBGP<\/b> \u2014 un servizio che implementa diverse funzionalit\u00e0 utilizzando il protocollo di instradamento dinamico basato su BGP. Lo utilizziamo attivamente per annunciare i nostri indirizzi IP pubblici, attraverso i quali gli utenti accedono all'API.<\/p>\n<p><b>HAProxy<\/b> \u2014 un bilanciatore di carico ad alta intensit\u00e0, che consente di configurare regole di bilanciamento del traffico molto flessibili su diversi livelli del modello OSI. Lo utilizziamo per il bilanciamento davanti a tutti i servizi: database, broker di messaggi, servizi API, servizi web, i nostri progetti interni \u2014 tutto \u00e8 gestito da HAProxy.<\/p>\n<p><b>API application<\/b> \u2014 un'applicazione web scritta in Python, tramite la quale l'utente gestisce la propria infrastruttura, il proprio servizio.<\/p>\n<p><b>Worker application <\/b>(d'ora in poi semplicemente worker) \u2014 nei servizi OpenStack \u00e8 un demone di infrastruttura che consente di trasmettere comandi API all'infrastruttura. Ad esempio, la creazione di un disco avviene proprio nel worker, mentre la richiesta di creazione avviene nell'API application. <\/p>\n<h2>Architettura standard dell'OpenStack Application<\/h2>\n<p>\nLa maggior parte dei servizi sviluppati per OpenStack cerca di seguire un'unica concezione. Un servizio di solito \u00e8 composto da 2 parti: API e worker (esecutori di backend). In genere, l'API \u00e8 un'applicazione WSGI in Python, che pu\u00f2 essere eseguita come processo autonomo (daemon), oppure utilizzando un server web gi\u00e0 configurato come Nginx o Apache. L'API gestisce la richiesta dell'utente e trasmette successivamente le istruzioni all'applicazione worker. La trasmissione avviene tramite un broker di messaggi, generalmente RabbitMQ, mentre le altre opzioni sono poco supportate. Quando i messaggi raggiungono il broker, vengono elaborati dai worker e, in caso di necessit\u00e0, restituiscono una risposta. <\/p>\n<p>Questa concezione implica isolati punti di guasto comuni: RabbitMQ e il database. Tuttavia, RabbitMQ \u00e8 isolato all'interno di un singolo servizio e, in teoria, pu\u00f2 essere dedicato a ciascun servizio. Per questo motivo, in MCS cerchiamo di separare al massimo questi servizi, creando per ogni progetto un database e un RabbitMQ distinti. Questo approccio \u00e8 vantaggioso poich\u00e9 in caso di guasti in alcuni punti vulnerabili, non si interrompe l'intero servizio, ma solo una sua parte.<\/p>\n<p>Il numero di worker application non \u00e8 limitato, quindi l'API pu\u00f2 scalare facilmente orizzontalmente dietro ai bilanciatori, al fine di aumentare le prestazioni e la resilienza.<\/p>\n<blockquote><p>In alcuni servizi \u00e8 necessaria una coordinazione all'interno del servizio, quando si verificano operazioni sequenziali complesse tra API e worker. In questo caso, viene utilizzato un centro di coordinazione unico, un sistema di clustering come Redis, Memcache, etcd, che consente a un worker di comunicare a un altro che questo compito \u00e8 assegnato a lui (\u00abtu, per favore, non prenderlo\u00bb). Noi utilizziamo etcd. Di solito, i worker comunicano attivamente con il database, scrivendo e leggendo informazioni. Come database utilizziamo MariaDB, che \u00e8 mantenuto in un cluster multimaster.\n<\/p><\/blockquote>\n<p>\nUn servizio classico singolo \u00e8 organizzato in modo consolidato per OpenStack. Pu\u00f2 essere visto come un sistema chiuso, per il quale sono abbastanza evidenti i metodi di scaling e resilienza. Ad esempio, per la resilienza dell'API \u00e8 sufficiente posizionare un bilanciatore davanti ad essa. Lo scaling dei worker si ottiene aumentando il loro numero. <\/p>\n<p>Il punto debole dell'intero sistema sono RabbitMQ e MariaDB. La loro architettura merita un articolo dedicato. In questo articolo voglio concentrarmi sull'affidabilit\u00e0 dell'API.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene implementata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/f39e5a8ae350864e311bf4db3b9c34b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Architettura Openstack Application. Bilanciamento e affidabilit\u00e0 della piattaforma cloud.<\/i><\/p>\n<h2>Rendiamo il bilanciatore HAProxy affidabile con ExaBGP.<\/h2>\n<p>\nPer garantire che le nostre API siano scalabili, veloci e affidabili, abbiamo inserito un bilanciatore. Abbiamo scelto HAProxy. A mio avviso, possiede tutte le caratteristiche necessarie per il nostro compito: bilanciamento su pi\u00f9 livelli OSI, interfaccia di gestione, flessibilit\u00e0 e scalabilit\u00e0, un grande numero di metodi di bilanciamento, supporto per le tabelle di sessione.<\/p>\n<p>Il primo problema da risolvere \u00e8 stata l'affidabilit\u00e0 del bilanciatore stesso. L'installazione di un bilanciatore crea comunque un punto di guasto: se il bilanciatore si blocca, il servizio va gi\u00f9. Per evitare questo problema, abbiamo utilizzato HAProxy insieme a ExaBGP.<\/p>\n<p>ExaBGP consente di implementare un meccanismo di verifica dello stato del servizio. Abbiamo utilizzato questo meccanismo per controllare il funzionamento di HAProxy e, in caso di problemi, disattivare il servizio HAProxy dal BGP. <\/p>\n<p><b>Schema ExaBGP+HAProxy.<\/b><\/p>\n<ol>\n<li>Installiamo il software necessario, ExaBGP e HAProxy, su tre server. <\/li>\n<li>Su ciascun server creiamo un'interfaccia loopback.<\/li>\n<li>Su tutti e tre i server impostiamo lo stesso indirizzo IP pubblico su questa interfaccia.<\/li>\n<li>L'indirizzo IP pubblico viene annunciato su Internet tramite ExaBGP. <\/li>\n<\/ol>\n<p>\nL'affidabilit\u00e0 si ottiene annunciando lo stesso indirizzo IP da tutti e tre i server. Dal punto di vista della rete, lo stesso indirizzo \u00e8 accessibile da tre diversi next hop. Il router vede tre percorsi identici e seleziona quello pi\u00f9 priorizzato secondo la sua metrica (che di solito \u00e8 lo stesso percorso), e il traffico viene instradato solo su uno dei server. <\/p>\n<p>In caso di problemi con il funzionamento di HAProxy o di guasto del server, ExaBGP smette di annunciare il percorso, e il traffico viene immediatamente reindirizzato a un altro server. <\/p>\n<p>In questo modo abbiamo raggiunto l'affidabilit\u00e0 del bilanciatore.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene implementata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/9fba0718176dc1266f25a2c01ec87348.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Affidabilit\u00e0 dei bilanciatori HAProxy.<\/i><\/p>\n<p>Lo schema non \u00e8 risultato ideale: abbiamo imparato a riservare HAProxy, ma non a distribuire il carico all'interno dei servizi. Pertanto, abbiamo espanso un po' questa architettura: siamo passati al bilanciamento tra pi\u00f9 indirizzi IP pubblici.<\/p>\n<h2>Bilanciamento basato su DNS e BGP<\/h2>\n<p>\nRimane irrisolto il problema del bilanciamento del carico davanti ai nostri HAProxy. Tuttavia, \u00e8 possibile risolverlo in modo piuttosto semplice, come abbiamo fatto noi.<\/p>\n<p>Per bilanciare tre server sono necessari 3 indirizzi IP pubblici e il buon vecchio DNS. Ognuno di questi indirizzi \u00e8 definito sull'interfaccia loopback di ciascun HAProxy e viene annunciato su Internet. <\/p>\n<p>In OpenStack, per la gestione delle risorse, viene utilizzato un catalogo dei servizi, in cui \u00e8 definito l'endpoint API di ciascun servizio. In questo catalogo, indichiamo il nome di dominio \u2014 public.infra.mail.ru, che viene risolto tramite DNS tramite tre indirizzi IP diversi. Di conseguenza, otteniamo una distribuzione del carico tra i tre indirizzi tramite DNS. <\/p>\n<p>Ma poich\u00e9, nell'annuncio degli indirizzi IP pubblici, non gestiamo le priorit\u00e0 di selezione del server, al momento non si tratta di bilanciamento. Di solito, viene selezionato solo un server in base all'anzianit\u00e0 dell'indirizzo IP, mentre gli altri due rimarranno inattivi, poich\u00e9 non sono state specificate metriche in BGP.<\/p>\n<p>Abbiamo iniziato a trasmettere percorsi tramite ExaBGP con metriche diverse. Ogni bilanciatore annuncia tutti e tre gli indirizzi IP pubblici, ma uno di essi, principale per quel bilanciatore, viene annunciato con la metrica pi\u00f9 bassa. Quindi, finch\u00e9 tutti e tre i bilanciatori sono attivi, le richieste al primo indirizzo IP vanno al primo bilanciatore, quelle al secondo al secondo, e quelle al terzo al terzo.<\/p>\n<p>Cosa succede nel momento in cui uno dei bilanciatori fallisce? In caso di guasto di un bilanciatore, il suo indirizzo principale viene ancora annunciato dagli altri due, e il traffico tra di loro viene ridistribuito. In questo modo, forniamo all'utente tramite DNS immediatamente pi\u00f9 indirizzi IP. Attraverso il bilanciamento via DNS e la metrica diversa, otteniamo una distribuzione uniforme del carico su tutti e tre i bilanciatori, senza perdere la resilienza.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene implementata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/1485367a934aea06b68c6d05c184d263.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Bilanciamento HAProxy basato su DNS + BGP<\/i><\/p>\n<h2>Interazione tra ExaBGP e HAProxy<\/h2>\n<p>\nQuindi, abbiamo implementato la resilienza nel caso di un guasto del server, sulla base dell'interruzione dell'annuncio dei percorsi. Ma HAProxy pu\u00f2 disattivarsi anche per altri motivi, oltre al guasto del server: errori di amministrazione, guasti all'interno del servizio. Vogliamo rimuovere il bilanciatore rotto dal carico anche in questi casi, e serve un altro meccanismo. <\/p>\n<p>Pertanto, espandendo la precedente configurazione, abbiamo realizzato un heartbeat tra ExaBGP e HAProxy. Questa \u00e8 un'implementazione software dell'interazione tra ExaBGP e HAProxy, dove ExaBGP utilizza script personalizzati per controllare lo stato delle applicazioni.<\/p>\n<p>A tal fine, nel file di configurazione di ExaBGP \u00e8 necessario impostare un health checker in grado di verificare lo stato di HAProxy. Nel nostro caso, abbiamo configurato un health backend in HAProxy e, da parte di ExaBGP, verifichiamo con una semplice richiesta GET. Se l'annuncio smette di avvenire, HAProxy probabilmente non funziona e non deve essere annunciato. <\/p>\n<p><img decoding=\"async\" alt=\"Come viene implementata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/d5cda30043fe02ab81355b28c0d83ac6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Controllo dello stato di HAProxy<\/i><\/p>\n<h2>Peer di HAProxy: sincronizzazione delle sessioni <\/h2>\n<p>\nLa successiva operazione da effettuare \u00e8 stata sincronizzare le sessioni. Lavorando attraverso bilanciatori distribuiti, \u00e8 difficile organizzare la conservazione delle informazioni sulle sessioni dei clienti. Ma HAProxy \u00e8 uno dei pochi bilanciatori che pu\u00f2 farlo grazie alla funzionalit\u00e0 Peers, che consente il passaggio delle tabelle di sessioni tra i vari processi di HAProxy. <\/p>\n<p>Esistono diversi metodi di bilanciamento: semplici, come <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Round-robin_(%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC)\">round-robin<\/a><\/noindex>, e avanzati, in cui la sessione del cliente viene memorizzata, e ogni volta il cliente viene indirizzato allo stesso server di prima. Volevamo implementare la seconda opzione.<\/p>\n<p>In HAProxy, per mantenere le sessioni del cliente, viene utilizzato il meccanismo delle stick-tables. Queste memorizzano l'indirizzo IP originale del cliente, l'indirizzo target selezionato (backend) e alcune informazioni di servizio. Di solito, le stick-tables vengono utilizzate per memorizzare la coppia source-IP + destination-IP, il che \u00e8 particolarmente utile per le applicazioni che non possono trasmettere il contesto della sessione utente quando si passa a un altro bilanciatore, ad esempio, in modalit\u00e0 bilanciamento RoundRobin.<\/p>\n<p>Se la stick-table viene addestrata a spostarsi tra i diversi processi di HAProxy (tra cui avviene il bilanciamento), i nostri bilanciatori potranno lavorare con un unico pool di stick-tables. Questo consentir\u00e0 un passaggio senza soluzione di continuit\u00e0 della rete del cliente in caso di caduta di uno dei bilanciatori, e il lavoro con le sessioni dei clienti continuer\u00e0 sugli stessi backend selezionati in precedenza.<\/p>\n<p>Per un funzionamento corretto, deve essere risolta la questione dell'indirizzo IP sorgente del bilanciatore da cui \u00e8 stata stabilita la sessione. Nel nostro caso, si tratta di un indirizzo dinamico sull'interfaccia loopback. <\/p>\n<p>Il corretto funzionamento dei peers si realizza solo in determinate condizioni. In altre parole, i timeout TCP devono essere sufficientemente lunghi oppure il passaggio deve avvenire abbastanza rapidamente affinch\u00e9 la sessione TCP non si interrompa. Tuttavia, ci\u00f2 consente uno switch senza interruzioni. <\/p>\n<p>Nel nostro IaaS abbiamo un servizio costruito con la stessa tecnologia. Questo \u00e8 <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/app\/services\/infra\/balancers-list\/\">Load Balancer come servizio per OpenStack<\/a><\/noindex>, chiamato Octavia. \u00c8 basato su due processi HAProxy, supporta nativamente i peers. In questo servizio, si sono rivelati molto efficaci.<\/p>\n<p>Nell'immagine \u00e8 rappresentato schematicamente il trasferimento delle tabelle dei peers tra tre istanze di HAProxy, \u00e8 fornita una configurazione su come impostarla:<\/p>\n<p><img decoding=\"async\" alt=\"Come viene implementata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/d31fab761da627923345b7ace7f0b943.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>HAProxy Peers (sincronizzazione delle sessioni)<\/i><\/p>\n<p>Se intendi implementare uno schema simile, \u00e8 necessario testarne il funzionamento con attenzione. Non \u00e8 garantito che funzioni allo stesso modo nel 100% dei casi. Tuttavia, perlomeno, non perderai le tabelle stick quando \u00e8 necessario ricordare l'IP sorgente del cliente.<\/p>\n<h2>Limitazione del numero di richieste simultanee da parte dello stesso cliente<\/h2>\n<p>\nQualsiasi servizio accessibile pubblicamente, compresi i nostri API, pu\u00f2 essere soggetto a ondate di richieste. Le cause possono essere completamente diverse, da errori degli utenti a attacchi mirati. Siamo periodicamente soggetti a attacchi DDoS per indirizzi IP. I clienti spesso commettono errori nei loro script, creando mini-DDoS.<\/p>\n<p>In ogni caso, \u00e8 necessario prevedere una protezione aggiuntiva. Una soluzione ovvia \u00e8 limitare il numero di richieste agli API per non sprecare tempo di elaborazione su richieste dannose.<\/p>\n<p>Per implementare tali limitazioni utilizziamo i rate limits, organizzati sulla base di HAProxy, tramite le stesse tabelle stick. I limiti sono facili da configurare e consentono di limitare l'utente per numero di richieste agli API. L'algoritmo memorizza l'IP sorgente da cui vengono effettuate le richieste e limita il numero di richieste simultanee da un singolo utente. Naturalmente, abbiamo calcolato il profilo medio del carico sugli API per ciascun servizio e abbiamo impostato un limite di circa 10 volte superiore a questo valore. Continuiamo a monitorare attentamente la situazione, mantenendo un occhio sempre vigile.<\/p>\n<p>Come appare nella pratica? Abbiamo clienti che utilizzano costantemente le nostre API per l'auto-scalabilit\u00e0. Creano circa duecento-trecento macchine virtuali al mattino e le cancellano verso sera. Per OpenStack, creare una macchina virtuale, insieme ai servizi PaaS, richiede almeno 1000 richieste API, poich\u00e9 l'interazione tra i servizi avviene anch'essa tramite API. <\/p>\n<p>Questi spostamenti di carico causano un notevole sovraccarico. Abbiamo valutato questo sovraccarico, raccolto i picchi giornalieri, aumentati di dieci volte, ed \u00e8 diventato il nostro rate limit. Teniamo la mano sul polso. Spesso vediamo bot e scanner che cercano di capire se abbiamo script CGA che possono essere eseguiti e li blocchiamo attivamente.<\/p>\n<h2>Come aggiornare la base di codice senza che gli utenti se ne accorgano<\/h2>\n<p>\nImplementiamo la tolleranza ai guasti anche a livello di processi di deployment del codice. Durante i rilasci possono verificarsi errori, ma il loro impatto sulla disponibilit\u00e0 dei servizi pu\u00f2 essere minimizzato.<\/p>\n<p>Aggiorniamo continuamente i nostri servizi e dobbiamo garantire il processo di aggiornamento della base di codice senza effetti sugli utenti. Siamo riusciti a risolvere questo problema utilizzando le funzionalit\u00e0 di gestione di HAProxy e implementando il Graceful Shutdown nei nostri servizi.<\/p>\n<p>Per affrontare questa sfida, era necessario garantire il controllo del bilanciatore e lo 'shutdown corretto' dei servizi:<\/p>\n<ul>\n<li>Nel caso di HAProxy, la gestione avviene tramite un file stat, che di fatto \u00e8 un socket e viene definito nella configurazione di HAProxy. Le istruzioni possono essere inviate tramite stdio. Ma il nostro principale strumento per il controllo delle configurazioni \u00e8 Ansible, quindi dispone di un modulo integrato per la gestione di HAProxy, che utilizziamo attivamente. <\/li>\n<li>La maggior parte dei nostri servizi API e Engine supporta tecnologie di downtime controllato: quando vengono spenti, attendono il completamento di attivit\u00e0 in corso, che si tratti di una richiesta http o di qualche compito di servizio. Lo stesso avviene con il worker. Sa quali compiti deve svolgere e si conclude quando ha completato tutto con successo. <\/li>\n<\/ul>\n<p>\nGrazie a questi due aspetti, l'algoritmo sicuro del nostro deployment appare nel seguente modo.<\/p>\n<ol>\n<li>Lo sviluppatore compila un nuovo pacchetto di codice (per noi \u00e8 un RPM), lo testa nell'ambiente di sviluppo, lo testa in fase e lo lascia nel repository di fase.<\/li>\n<li>Lo sviluppatore imposta il compito per il deployment con una descrizione dettagliata degli \"artefatti\": versione del nuovo pacchetto, descrizione delle nuove funzionalit\u00e0 e ulteriori dettagli sul deployment, se necessario.<\/li>\n<li>L'amministratore di sistema inizia l'aggiornamento. Avvia il playbook Ansible, che a sua volta esegue le seguenti operazioni: \n<ul>\n<li>Preleva il pacchetto dal repository di staging e aggiorna la versione del pacchetto nel repository di produzione.<\/li>\n<li>Compila un elenco dei backend del servizio da aggiornare.<\/li>\n<li>Disattiva il primo servizio da aggiornare in HAProxy e attende che i suoi processi siano completati. Grazie allo shutdown controllato, siamo certi che tutte le richieste attuali dei clienti vengano completate con successo.<\/li>\n<li>Dopo la completa disattivazione dell'API, dei worker e lo spegnimento di HAProxy, avviene l'aggiornamento del codice.<\/li>\n<li>Ansible avvia i servizi.<\/li>\n<li>Per ogni servizio attiva determinati \"trigger\" che eseguono il test unitario in base a una serie di test chiave predefiniti. Viene effettuato un controllo di base del nuovo codice.<\/li>\n<li>Se nel passaggio precedente non sono stati rilevati errori, il backend viene attivato.<\/li>\n<li>Si passa al backend successivo.<\/li>\n<\/ul>\n<\/li>\n<li>Dopo l'aggiornamento di tutti i backend, vengono eseguiti test funzionali. Se non sono sufficienti, lo sviluppatore esamina qualsiasi nuova funzionalit\u00e0 che ha sviluppato.<\/li>\n<\/ol>\n<p>\nA questo punto, il deployment \u00e8 completato.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene implementata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/2d889fe1af33653e4bfebabe1cce6552.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ciclo di aggiornamento del servizio<\/i><\/p>\n<p>Questo schema non sarebbe operativo se non avessimo una regola. Manteniamo attivamente sia la versione vecchia che quella nuova. Sin dalla fase di sviluppo del software, si prevede che anche se ci saranno modifiche nel database del servizio, non romperanno il codice precedente. Di conseguenza, avviene un aggiornamento graduale della base di codice.<\/p>\n<h2>Conclusione<\/h2>\n<p>\nCondividendo i miei pensieri riguardo all'architettura WEB a prova di guasto, voglio ribadire alcuni punti chiave:<\/p>\n<ul>\n<li>resilienza fisica;<\/li>\n<li>resilienza di rete (bilanciatori, BGP);<\/li>\n<li>resilienza del software utilizzato e sviluppato.<\/li>\n<\/ul>\n<p>\nA tutti un uptime stabile!<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/474180\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u042f \u0410\u0440\u0442\u0435\u043c \u041a\u0430\u0440\u0430\u043c\u044b\u0448\u0435\u0432, \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Mail.Ru Cloud Solutions (MCS). \u0417\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0433\u043e\u0434 \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432 \u043d\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432. \u041c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b API-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c, \u0431\u044b\u043b\u0438 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u043c\u0438 \u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u043c\u0438 \u043a \u0431\u044b\u0441\u0442\u0440\u043e\u043c\u0443 \u0440\u043e\u0441\u0442\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041d\u0430\u0448\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 OpenStack, \u0438 \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u044c, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52389","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\".\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u0430\u044f \u0432\u0435\u0431-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Mail.ru Cloud Solutions | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\".\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-06T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:05+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Come viene implementata un'architettura web a prova di guasto nella piattaforma Mail.ru Cloud Solutions | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u0430\u044f \u0432\u0435\u0431-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Mail.ru Cloud Solutions | ProHoster","og:description":".","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-06T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:05+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52389","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 03:27:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:44:43","updated":"2026-01-24 03:27:21","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/52389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=52389"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/52389\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=52389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=52389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=52389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}