Una storia di lancio che ha influenzato tutto

Una storia di lancio che ha influenzato tutto
Nemici della Realtà entro 12f-2

Alla fine di aprile, mentre gli Estranei assediavano Grande Inverno, ci è successo qualcosa di più interessante: abbiamo fatto un lancio insolito. In linea di principio, implementiamo costantemente nuove funzionalità nella produzione (come tutti gli altri). Ma questo era diverso. La portata era tale che qualsiasi potenziale errore che avremmo potuto commettere avrebbe influenzato tutti i nostri servizi e utenti. Di conseguenza, abbiamo implementato tutto secondo i piani, entro il periodo di inattività pianificato e annunciato, senza conseguenze sulle vendite. L'articolo spiega come abbiamo raggiunto questo obiettivo e come chiunque può ripeterlo a casa.

Non descriverò ora le decisioni architettoniche e tecniche che abbiamo preso né racconterò come funziona il tutto. Si tratta piuttosto di appunti a margine su come è avvenuto uno dei rollout più difficili, che ho osservato e nel quale sono stato direttamente coinvolto. Non pretendo completezza o dettagli tecnici, forse appariranno in un altro articolo.

Background + che tipo di funzionalità è questa?

Stiamo costruendo una piattaforma cloud Mail.ru soluzioni cloud (MCS), dove lavoro come direttore tecnico. E ora è il momento di aggiungere IAM (Identity and Access Management) alla nostra piattaforma, che fornisce la gestione unificata di tutti gli account utente, utenti, password, ruoli, servizi e altro ancora. Perché è necessario nel cloud è una domanda ovvia: tutte le informazioni dell'utente sono archiviate al suo interno.

Di solito queste cose iniziano a essere costruite proprio all'inizio di qualsiasi progetto. Ma storicamente le cose sono andate un po’ diversamente nella MCS. MCS è stato costruito in due parti:

  • Openstack con il proprio modulo di autorizzazione Keystone,
  • Hotbox (archiviazione S3) basato sul progetto Mail.ru Cloud,

attorno al quale sono poi comparsi nuovi servizi.

Si trattava essenzialmente di due tipi diversi di autorizzazione. Inoltre, abbiamo utilizzato alcuni sviluppi separati di Mail.ru, ad esempio un archivio generale di password Mail.ru, nonché un connettore openid autoprodotto, grazie al quale è stato fornito SSO (autorizzazione end-to-end) nel pannello Horizon di macchine virtuali (interfaccia utente OpenStack nativa).

Realizzare IAM per noi significava connettere tutto in un unico sistema, completamente nostro. Allo stesso tempo, non perderemo alcuna funzionalità lungo il percorso, ma creeremo una base per il futuro che ci consentirà di perfezionarla in modo trasparente senza refactoring e di ridimensionarla in termini di funzionalità. Anche all'inizio gli utenti avevano un modello per l'accesso ai servizi (RBAC centrale, controllo degli accessi basato sui ruoli) e alcune altre piccole cose.

Il compito si è rivelato non banale: Python e Perl, diversi backend, servizi scritti in modo indipendente, diversi team di sviluppo e amministratori. E, cosa più importante, ci sono migliaia di utenti attivi nel sistema di produzione del combattimento. Tutto ciò doveva essere scritto e, soprattutto, implementato senza vittime.

Cosa lanceremo?

Per dirla in modo molto approssimativo, in circa 4 mesi abbiamo preparato quanto segue:

  • Abbiamo creato diversi nuovi demoni che aggregavano funzioni che precedentemente funzionavano in diverse parti dell'infrastruttura. Al resto dei servizi è stato prescritto un nuovo backend sotto forma di questi demoni.
  • Abbiamo creato il nostro archivio centrale di password e chiavi, disponibile per tutti i nostri servizi, che può essere liberamente modificato in base alle nostre necessità.
  • Abbiamo scritto da zero 4 nuovi backend per Keystone (utenti, progetti, ruoli, assegnazioni di ruoli), che, di fatto, hanno sostituito il relativo database e ora fungono da unico repository per le password dei nostri utenti.
  • Abbiamo insegnato a tutti i nostri servizi Openstack a rivolgersi a un servizio di policy di terze parti per le loro policy invece di leggerle localmente da ciascun server (sì, è così che Openstack funziona per impostazione predefinita!)

Una rielaborazione così importante richiede modifiche ampie, complesse e, soprattutto, sincrone in diversi sistemi scritti da diversi team di sviluppo. Una volta assemblato, l'intero sistema dovrebbe funzionare.

Come implementare tali cambiamenti e non rovinare tutto? Per prima cosa abbiamo deciso di guardare un po’ al futuro.

Strategia di lancio

  • Sarebbe possibile implementare il prodotto in più fasi, ma ciò aumenterebbe di tre volte il tempo di sviluppo. Inoltre, da qualche tempo avremmo la completa desincronizzazione dei dati nei database. Dovresti scrivere i tuoi strumenti di sincronizzazione e convivere con più archivi dati per molto tempo. E questo crea un’ampia varietà di rischi.
  • Tutto ciò che poteva essere preparato in modo trasparente per l'utente è stato preparato in anticipo. Ci sono voluti 2 mesi.
  • Ci siamo concessi tempi di inattività per diverse ore, solo per le operazioni dell'utente volte a creare e modificare le risorse.
  • Per il funzionamento di tutte le risorse già create, i tempi di inattività erano inaccettabili. Abbiamo pianificato che durante l'implementazione le risorse funzionino senza tempi di inattività e senza alcun impatto sui clienti.
  • Per ridurre l'impatto sui nostri clienti se qualcosa va storto, abbiamo deciso di lanciarlo domenica sera. Meno clienti gestiscono le macchine virtuali di notte.
  • Abbiamo avvisato tutti i nostri clienti che durante il periodo selezionato per l'implementazione la gestione del servizio non sarà disponibile.

Digressione: cos'è un rollout?

<attenzione, filosofia>

Ogni specialista IT può facilmente rispondere in cosa consiste un'implementazione. Installi CI/CD e tutto viene automaticamente consegnato al negozio. 🙂

Naturalmente questo è vero. Ma la difficoltà è che con i moderni strumenti di automazione della distribuzione del codice si perde la comprensione del lancio stesso. Come dimenticare l'epicità dell'invenzione della ruota quando si guarda ai trasporti moderni. Tutto è così automatizzato che spesso il rollout viene effettuato senza comprendere il quadro completo.

E l'intera immagine è così. Il rollout si compone di quattro aspetti principali:

  1. Consegna del codice, inclusa la modifica dei dati. Ad esempio, le loro migrazioni.
  2. Il rollback del codice è la possibilità di tornare indietro se qualcosa va storto. Ad esempio, attraverso la creazione di backup.
  3. Ora di ciascuna operazione di rollout/rollback. È necessario comprendere i tempi di qualsiasi operazione dei primi due punti.
  4. Funzionalità interessata. È necessario valutare sia gli effetti positivi attesi che i possibili effetti negativi.

Tutti questi aspetti devono essere presi in considerazione per un lancio di successo. Di solito viene valutato solo il primo, o nella migliore delle ipotesi il secondo, e quindi il lancio viene considerato riuscito. Ma il terzo e il quarto sono ancora più importanti. Quale utente vorrebbe che l'implementazione richiedesse 3 ore anziché un minuto? O se qualcosa di non necessario viene influenzato durante il rollout? Oppure il tempo di inattività di un servizio porterà a conseguenze imprevedibili?

Atto 1..n, preparazione alla liberazione

Inizialmente avevo pensato di descrivere brevemente i nostri incontri: tutto il team, le sue parti, mille discussioni ai coffee point, discussioni, prove, brainstorming. Allora ho pensato che non sarebbe stato necessario. Quattro mesi di sviluppo consistono sempre in questo, soprattutto quando non stai scrivendo qualcosa che può essere consegnato costantemente, ma una grande funzionalità per un sistema live. Ciò riguarda tutti i servizi, ma per gli utenti non dovrebbe cambiare nulla tranne “un pulsante nell’interfaccia web”.

La nostra comprensione di come implementare il progetto è cambiata da ogni nuovo incontro, e in modo abbastanza significativo. Ad esempio, avremmo aggiornato il nostro intero database di fatturazione. Ma abbiamo calcolato il tempo e ci siamo resi conto che era impossibile farlo in un tempo di implementazione ragionevole. Ci è voluta quasi una settimana in più per frammentare e archiviare il database di fatturazione. E quando la velocità di implementazione prevista non era ancora soddisfacente, abbiamo ordinato un hardware aggiuntivo e più potente, dove veniva trascinata l'intera base. Non è che non volessimo farlo prima, ma l'attuale necessità di implementazione ci ha lasciato senza opzioni.

Quando uno di noi ha avuto dei dubbi sul fatto che il rollout potesse influire sulla disponibilità delle nostre macchine virtuali, abbiamo trascorso una settimana a condurre test, esperimenti, analisi del codice e abbiamo capito chiaramente che ciò non sarebbe accaduto nella nostra produzione, e anche le persone più dubbiose hanno concordato con questo.

Nel frattempo, i ragazzi del supporto tecnico hanno condotto i propri esperimenti indipendenti per scrivere istruzioni per i clienti sui metodi di connessione, che avrebbero dovuto cambiare dopo il rollout. Hanno lavorato sulla UX dell'utente, preparato istruzioni e fornito consulenze personali.

Abbiamo automatizzato tutte le operazioni di implementazione possibili. Ogni operazione veniva eseguita tramite script, anche le più semplici, e i test venivano eseguiti costantemente. Discutevano sul modo migliore per disattivare il servizio: omettere il demone o bloccare l'accesso al servizio con un firewall. Abbiamo creato una lista di controllo dei team per ogni fase del lancio e l'abbiamo aggiornata costantemente. Abbiamo disegnato e aggiornato costantemente un diagramma di Gantt per tutto il lavoro di rollout, con relative tempistiche.

E così ...

L'ultimo atto, prima di partire

...è ora di partire.

Come si suol dire, un'opera d'arte non può essere completata, ma solo finita di lavorarci sopra. Devi fare uno sforzo di volontà, comprendendo che non troverai tutto, ma credendo di aver fatto tutte le ipotesi ragionevoli, previsto tutti i casi possibili, chiuso tutti i bug critici e tutti i partecipanti hanno fatto tutto il possibile. Più codice implementi, più è difficile convincertene (inoltre, tutti capiscono che è impossibile prevedere tutto).

Abbiamo deciso che eravamo pronti per l'implementazione quando eravamo convinti di aver fatto tutto il possibile per coprire tutti i rischi per i nostri utenti associati a effetti e tempi di inattività imprevisti. Cioè, tutto può andare storto tranne:

  1. Influiscono sull’infrastruttura utente (sacra per noi, preziosissima),
  2. Funzionalità: l'utilizzo del nostro servizio dopo il lancio dovrebbe essere lo stesso di prima.

Srotolare

Una storia di lancio che ha influenzato tutto
Due tiri, 8 non interferiscono

Prendiamo un tempo di inattività per tutte le richieste degli utenti per 7 ore. Al momento disponiamo sia di un piano di lancio che di un piano di ripristino.

  • L'implementazione vera e propria richiede circa 3 ore.
  • 2 ore per il test.
  • 2 ore - riserva per un eventuale ripristino delle modifiche.

Per ogni azione è stato redatto un diagramma di Gantt, quanto tempo occorre, cosa avviene in sequenza, cosa si fa in parallelo.

Una storia di lancio che ha influenzato tutto
Un pezzo di un diagramma di Gantt di rollout, una delle prime versioni (senza esecuzione parallela). Lo strumento di sincronizzazione più prezioso

A tutti i partecipanti viene determinato il proprio ruolo nell'implementazione, quali compiti svolgere e di cosa sono responsabili. Cerchiamo di portare ogni fase all'automaticità, di implementarla, ripristinarla, raccogliere feedback e implementarla di nuovo.

Cronaca di eventi

Così, domenica 15 aprile, alle 29, sono venute al lavoro 10 persone. Oltre ai partecipanti più importanti, alcuni sono venuti semplicemente per sostenere la squadra, per cui un ringraziamento speciale a loro.

Vale anche la pena ricordare che il nostro tester chiave è in vacanza. È impossibile implementarlo senza test, stiamo esplorando le opzioni. Una collega accetta di metterci alla prova durante le vacanze, per cui riceve un'immensa gratitudine da parte dell'intero team.

00:00. Fermare
Fermiamo le richieste degli utenti, appendiamo un cartello con scritto lavoro tecnico. Il monitoraggio urla, ma è tutto normale. Controlliamo che non sia caduto nulla oltre a quello che doveva cadere. E iniziamo a lavorare sulla migrazione.

Tutti hanno un piano di implementazione stampato punto per punto, tutti sanno chi sta facendo cosa e in quale momento. Dopo ogni azione controlliamo i tempi per assicurarci di non superarli e che tutto vada secondo i piani. Coloro che al momento non partecipano direttamente al rollout si stanno preparando lanciando un giocattolo online (Xonotic, ciarlatani di tipo 3) per non disturbare i colleghi. 🙂

02:00. Srotolato
Una piacevole sorpresa: terminiamo il rollout un'ora prima, grazie all'ottimizzazione dei nostri database e degli script di migrazione. Il grido generale: "srotolato!" Tutte le nuove funzioni sono in produzione, ma finora solo noi possiamo vederle nell'interfaccia. Tutti entrano in modalità test, li suddividono in gruppi e iniziano a vedere cosa è successo alla fine.

Non è andata molto bene, ce ne rendiamo conto dopo 10 minuti, quando nulla è collegato o funzionante nei progetti dei membri del team. Sincronizzazione rapida, esprimiamo i nostri problemi, stabiliamo le priorità, dividiamo in team ed entriamo nel debug.

02:30. Due grossi problemi contro quattro occhi
Troviamo due grossi problemi. Ci siamo resi conto che i clienti non avrebbero visto alcuni servizi connessi e che sarebbero sorti problemi con gli account dei partner. Entrambi sono dovuti a script di migrazione imperfetti per alcuni casi limite. Dobbiamo sistemarlo adesso.

Scriviamo query che registrino questo, con almeno 4 occhi. Li testiamo durante la pre-produzione per assicurarci che funzionino e non rompano nulla. Puoi andare avanti. Allo stesso tempo, eseguiamo i nostri regolari test di integrazione, che rivelano alcuni altri problemi. Sono tutti piccoli, ma hanno anche bisogno di essere riparati.

03:00. -2 problemi +2 problemi
I due grandi problemi precedenti sono stati risolti, e anche quasi tutti quelli minori. Tutti coloro che non sono occupati nelle correzioni lavorano attivamente nei loro account e riferiscono ciò che trovano. Diamo la priorità, distribuiamo tra i team e lasciamo gli elementi non critici per la mattina.

Rieseguiamo i test, scoprono due nuovi grossi problemi. Non tutte le policy di servizio sono arrivate correttamente, quindi alcune richieste degli utenti non superano l'autorizzazione. Inoltre un nuovo problema con gli account dei partner. Corriamo a guardare.

03:20. Sincronizzazione di emergenza
Un nuovo problema risolto. Per il secondo stiamo organizzando una sincronizzazione d'emergenza. Comprendiamo cosa sta succedendo: la soluzione precedente ha risolto un problema, ma ne ha creato un altro. Ci prendiamo una pausa per capire come farlo correttamente e senza conseguenze.

03:30. Sei occhi
Comprendiamo quale dovrebbe essere lo stato finale della base affinché tutto vada bene per tutti i partner. Scriviamo una richiesta con 6 occhi, la implementiamo in pre-produzione, la testiamo, la implementiamo per la produzione.

04:00. Tutto funziona
Tutti i test sono stati superati, nessun problema critico visibile. Di tanto in tanto qualcosa nel team non funziona per qualcuno, reagiamo prontamente. Molto spesso l'allarme è falso. Ma a volte qualcosa non arriva o una pagina separata non funziona. Ci sediamo, sistemiamo, sistemiamo, sistemiamo. Un team separato sta lanciando l'ultima grande funzionalità: la fatturazione.

04:30. Punto di non ritorno
Si sta avvicinando il punto di non ritorno, cioè il momento in cui, se iniziamo a tornare indietro, non riusciremo a soddisfare il tempo di inattività che ci è stato concesso. Ci sono problemi con la fatturazione, che sa e registra tutto, ma si rifiuta ostinatamente di cancellare i soldi dai clienti. Sono presenti diversi bug su singole pagine, azioni e stati. La funzionalità principale funziona, tutti i test vengono superati con successo. Se decidiamo che il rollout è avvenuto, non eseguiremo il rollback.

06:00. Aperto a tutti nell'interfaccia utente
Bug risolti. Alcuni che non piacciono agli utenti vengono lasciati per dopo. Apriamo l'interfaccia a tutti. Continuiamo a lavorare sulla fatturazione, aspettando il feedback degli utenti e monitorando i risultati.

07:00. Problemi con il caricamento dell'API
Diventa chiaro che abbiamo pianificato leggermente erroneamente il carico sulla nostra API e abbiamo testato questo carico, che non è stato in grado di identificare il problema. Di conseguenza, ≈5% delle richieste falliscono. Mobilitiamoci e cerchiamo il motivo.

La fatturazione è testarda e non vuole neanche funzionare. Decidiamo di rimandare a più tardi per poter attuare i cambiamenti con calma. Cioè, tutte le risorse vengono accumulate al suo interno, ma le cancellazioni da parte dei clienti non vengono effettuate. Naturalmente questo è un problema, ma rispetto al lancio generale non sembra importante.

08:00. Correggi l'API
Abbiamo implementato una correzione per il carico e i guasti sono scomparsi. Iniziamo a tornare a casa.

10:00. Tutto
Tutto è risolto. Tutto è tranquillo nel monitoraggio e a casa dei clienti, la squadra va gradualmente a dormire. La fatturazione rimane, la ripristineremo domani.

Poi durante il giorno ci sono state implementazioni che hanno corretto registri, notifiche, codici di ritorno e personalizzazioni per alcuni dei nostri clienti.

Quindi il lancio ha avuto successo! Naturalmente potrebbe essere migliore, ma abbiamo tratto conclusioni su ciò che non ci bastava per raggiungere la perfezione.

In totale

Durante i 2 mesi di preparazione attiva per l'implementazione, sono state completate 43 attività, della durata da un paio d'ore a diversi giorni.

Durante il lancio:

  • demoni nuovi e modificati - 5 pezzi, in sostituzione di 2 monoliti;
  • modifiche all'interno dei database: tutti e 6 i nostri database con i dati degli utenti sono stati interessati, sono stati effettuati download da tre vecchi database a uno nuovo;
  • frontend completamente ridisegnato;
  • quantità di codice scaricato - 33mila righe di nuovo codice, ≈ 3mila righe di codice nei test, ≈ 5mila righe di codice di migrazione;
  • tutti i dati sono intatti, nessuna macchina virtuale del cliente è stata danneggiata. 🙂

Buone pratiche per un buon lancio

Ci hanno guidato in questa difficile situazione. Ma, in generale, è utile seguirli durante ogni eventuale rollout. Ma quanto più complessa è l’implementazione, tanto maggiore è il ruolo che svolgono.

  1. La prima cosa che devi fare è capire in che modo il lancio può o influenzerà gli utenti. Ci saranno tempi di inattività? Se sì, qual è il tempo di inattività? In che modo ciò influirà sugli utenti? Quali sono i possibili scenari migliori e peggiori? E coprire i rischi.
  2. Pianifica tutto. In ogni fase è necessario comprendere tutti gli aspetti dell'implementazione:
    • consegna del codice;
    • ripristino del codice;
    • ora di ciascuna operazione;
    • funzionalità interessata.
  3. Gioca attraverso gli scenari fino a quando tutte le fasi del lancio, così come i rischi in ciascuno di essi, diventano evidenti. Se avete dei dubbi potete prendervi una pausa ed esaminare separatamente la fase discutibile.
  4. Ogni fase può e deve essere migliorata se aiuta i nostri utenti. Ad esempio, ridurrà i tempi di inattività o eliminerà alcuni rischi.
  5. Il test di rollback è molto più importante del test di consegna del codice. È necessario verificare che a seguito del rollback il sistema ritorni allo stato originale e confermarlo con dei test.
  6. Tutto ciò che può essere automatizzato dovrebbe essere automatizzato. Tutto ciò che non può essere automatizzato dovrebbe essere scritto in anticipo su un foglietto illustrativo.
  7. Registrare il criterio di successo. Quali funzionalità dovrebbero essere disponibili e a che ora? Se ciò non accade, esegui un piano di rollback.
  8. E, soprattutto, le persone. Tutti dovrebbero essere consapevoli di ciò che stanno facendo, del perché e di cosa dipende dalle loro azioni nel processo di implementazione.

E in una frase, con una buona pianificazione ed elaborazione puoi realizzare tutto ciò che desideri senza conseguenze sulle vendite. Anche qualcosa che influenzerà tutti i tuoi servizi in produzione.

Fonte: habr.com

Aggiungi un commento