Een uitrolverhaal dat alles beïnvloedde

Een uitrolverhaal dat alles beïnvloedde
Vijanden van de werkelijkheid door 12f-2

Eind april, terwijl de White Walkers Winterfell belegerden, gebeurde er iets interessanters met ons: we voerden een ongebruikelijke uitrol uit. In principe rollen we voortdurend nieuwe functies uit in productie (net als iedereen). Maar deze was anders. De omvang ervan was zodanig dat eventuele fouten die we zouden kunnen maken gevolgen zouden hebben voor al onze diensten en gebruikers. Hierdoor hebben we alles volgens plan uitgerold, binnen de geplande en aangekondigde downtime, zonder gevolgen voor de omzet. Het artikel gaat over hoe we dit hebben bereikt en hoe iedereen dit thuis kan herhalen.

Ik zal nu niet de architectonische en technische beslissingen beschrijven die we hebben genomen, of vertellen hoe het allemaal werkt. Dit zijn eerder aantekeningen in de kantlijn over hoe een van de moeilijkste uitrol plaatsvond, die ik heb waargenomen en waarbij ik direct betrokken was. Ik claim geen volledigheid of technische details; misschien verschijnen ze in een ander artikel.

Achtergrond + wat voor functionaliteit is dit?

We bouwen een cloudplatform Mail.ru Cloud-oplossingen (MCS), waar ik werk als technisch directeur. En nu is het tijd om IAM (Identity and Access Management) toe te voegen aan ons platform, dat uniform beheer biedt van alle gebruikersaccounts, gebruikers, wachtwoorden, rollen, services en meer. Waarom het in de cloud nodig is, ligt voor de hand: alle gebruikersinformatie wordt erin opgeslagen.

Meestal beginnen dergelijke dingen aan het begin van elk project te worden gebouwd. Maar historisch gezien zijn de zaken in MCS een beetje anders geweest. MCS werd in twee delen gebouwd:

  • Openstack met een eigen Keystone-autorisatiemodule,
  • Hotbox (S3-opslag) gebaseerd op het Mail.ru Cloud-project,

waarrond vervolgens nieuwe diensten verschenen.

In wezen waren dit twee verschillende soorten machtigingen. Bovendien hebben we enkele afzonderlijke Mail.ru-ontwikkelingen gebruikt, bijvoorbeeld een algemene Mail.ru-wachtwoordopslag, evenals een zelfgeschreven openid-connector, waardoor SSO (end-to-end-autorisatie) werd aangeboden in het Horizon-paneel van virtuele machines (native OpenStack UI).

IAM maken betekende voor ons dat we alles in één systeem moesten samenbrengen, helemaal van onszelf. Tegelijkertijd zullen we gaandeweg geen enkele functionaliteit verliezen, maar een basis voor de toekomst creëren die ons in staat zal stellen deze op transparante wijze te verfijnen zonder te refactoriseren en op te schalen in termen van functionaliteit. Ook in het begin hadden gebruikers een rolmodel voor toegang tot services (centrale RBAC, op rollen gebaseerde toegangscontrole) en nog enkele andere kleine dingen.

De taak bleek niet triviaal: Python en Perl, verschillende backends, onafhankelijk geschreven services, verschillende ontwikkelingsteams en beheerders. En het allerbelangrijkste: er zijn duizenden live gebruikers op het gevechtsproductiesysteem. Dit alles moest worden geschreven en, belangrijker nog, zonder slachtoffers worden uitgerold.

Wat gaan we uitrollen?

Om het heel grof te zeggen: in ongeveer 4 maanden tijd hebben we het volgende voorbereid:

  • We hebben verschillende nieuwe daemons gemaakt die functies samenvoegden die voorheen in verschillende delen van de infrastructuur werkten. De rest van de diensten kreeg een nieuwe backend voorgeschreven in de vorm van deze demonen.
  • We hebben onze eigen centrale opslag van wachtwoorden en sleutels geschreven, beschikbaar voor al onze diensten, die naar behoefte vrij kunnen worden gewijzigd.
  • We hebben vanuit het niets 4 nieuwe backends voor Keystone geschreven (gebruikers, projecten, rollen, roltoewijzingen), die in feite de database hebben vervangen en nu fungeren als een enkele opslagplaats voor onze gebruikerswachtwoorden.
  • We hebben al onze Openstack-services geleerd om voor hun beleid naar een beleidsservice van derden te gaan in plaats van dit beleid lokaal vanaf elke server te lezen (ja, zo werkt Openstack standaard!)

Een dergelijke grote herwerking vereist grote, complexe en vooral synchrone veranderingen in verschillende systemen die door verschillende ontwikkelingsteams zijn geschreven. Eenmaal gemonteerd zou het hele systeem moeten werken.

Hoe kun je zulke veranderingen doorvoeren zonder het te verpesten? Eerst besloten we een beetje in de toekomst te kijken.

Uitrol strategie

  • Het zou mogelijk zijn om het product in meerdere fases uit te rollen, maar daarmee zou de ontwikkeltijd wel drie keer zo lang worden. Bovendien zouden we gedurende enige tijd te maken krijgen met een volledige desynchronisatie van de gegevens in de databases. Je zou je eigen synchronisatietools moeten schrijven en lange tijd met meerdere datastores moeten leven. En dit brengt een grote verscheidenheid aan risico's met zich mee.
  • Alles wat transparant voor de gebruiker kon worden voorbereid, werd vooraf gedaan. Het duurde 2 maanden.
  • We hebben onszelf enkele uren downtime toegestaan ​​- alleen voor gebruikersbewerkingen om bronnen te maken en te wijzigen.
  • Voor de werking van alle reeds gecreëerde bronnen was downtime onaanvaardbaar. We hadden gepland dat tijdens de uitrol de middelen zouden moeten werken zonder downtime en zonder gevolgen voor klanten.
  • Om de impact voor onze klanten te verkleinen als er iets misgaat, hebben we besloten om op zondagavond uit te rollen. Minder klanten beheren 's nachts virtuele machines.
  • We hebben al onze klanten gewaarschuwd dat tijdens de geselecteerde periode voor uitrol servicebeheer niet beschikbaar zal zijn.

Uitweiding: wat is een uitrol?

<voorzichtigheid, filosofie>

Iedere IT-specialist kan eenvoudig antwoorden wat een uitrol is. Je installeert CI/CD en alles wordt automatisch in de winkel afgeleverd. 🙂

Natuurlijk is dit waar. Maar de moeilijkheid is dat met moderne automatiseringstools voor het leveren van code het begrip van de uitrol zelf verloren gaat. Hoe je het epische karakter van de uitvinding van het wiel vergeet als je naar modern transport kijkt. Alles is zo geautomatiseerd dat de uitrol vaak wordt uitgevoerd zonder het hele plaatje te begrijpen.

En het hele plaatje is zo. De uitrol bestaat uit vier belangrijke aspecten:

  1. Levering van code, inclusief datamodificatie. Hun migraties bijvoorbeeld.
  2. Code rollback is de mogelijkheid om terug te gaan als er iets misgaat. Bijvoorbeeld door het maken van back-ups.
  3. Tijdstip van elke uitrol-/terugdraaibewerking. U moet de timing van elke bewerking van de eerste twee punten begrijpen.
  4. Beïnvloede functionaliteit. Het is noodzakelijk om zowel de verwachte positieve als de mogelijke negatieve effecten te evalueren.

Voor een succesvolle uitrol moet met al deze aspecten rekening worden gehouden. Meestal wordt alleen het eerste, of in het beste geval het tweede punt beoordeeld, waarna de uitrol als succesvol wordt beschouwd. Maar de derde en vierde zijn nog belangrijker. Welke gebruiker zou het leuk vinden als de uitrol 3 uur zou duren in plaats van een minuut? Of als er iets onnodigs wordt beïnvloed tijdens de uitrol? Of zal de downtime van één dienst tot onvoorspelbare gevolgen leiden?

Act 1..n, voorbereiding voor vrijlating

In eerste instantie dacht ik eraan om onze bijeenkomsten kort te beschrijven: het hele team, de onderdelen ervan, de vele discussies bij koffiepunten, ruzies, tests, brainstorms. Toen dacht ik dat het niet nodig zou zijn. Hieruit bestaan ​​altijd vier maanden ontwikkeling, vooral als je niet iets schrijft dat constant kan worden opgeleverd, maar één grote feature voor een live systeem. Dat heeft invloed op alle diensten, maar voor gebruikers mag er niets veranderen behalve ‘één knop in de webinterface’.

Ons begrip van hoe we dit moesten uitrollen, veranderde bij elke nieuwe bijeenkomst, en behoorlijk aanzienlijk. We gingen bijvoorbeeld onze volledige factureringsdatabase updaten. Maar we berekenden de tijd en realiseerden ons dat het onmogelijk was om dit binnen een redelijke uitroltijd te doen. Het kostte ons bijna een extra week om de factureringsdatabase op te delen en te archiveren. En toen de verwachte uitrolsnelheid nog steeds niet bevredigend was, bestelden we extra, krachtigere hardware, waarbij de hele basis werd meegesleept. Het is niet dat we dit niet eerder wilden doen, maar de huidige noodzaak om dit uit te rollen liet ons geen opties meer over.

Toen een van ons twijfelde of de uitrol de beschikbaarheid van onze virtuele machines zou kunnen beïnvloeden, hebben we een week lang tests, experimenten en code-analyses uitgevoerd en kregen we een duidelijk inzicht dat dit niet zou gebeuren in onze productie, en zelfs de meest twijfelachtige mensen waren het daarmee eens hiermee.

In de tussentijd voerden de jongens van de technische ondersteuning hun eigen onafhankelijke experimenten uit om instructies voor klanten te schrijven over verbindingsmethoden, die na de uitrol zouden veranderen. Ze werkten aan de user UX, bereidden instructies voor en gaven persoonlijk advies.

We hebben alle mogelijke uitroloperaties geautomatiseerd. Elke bewerking was in een script geschreven, zelfs de eenvoudigste, en er werden voortdurend tests uitgevoerd. Ze maakten ruzie over de beste manier om de service uit te schakelen: laat de daemon weg of blokkeer de toegang tot de service met een firewall. We hebben voor elke fase van de uitrol een checklist met teams gemaakt en deze voortdurend bijgewerkt. We hebben een Gantt-diagram getekend en voortdurend bijgewerkt voor al het uitrolwerk, met timing.

En dus…

De laatste act, voordat het uitrolt

...het is tijd om uit te rollen.

Zoals ze zeggen: een kunstwerk kan niet worden voltooid, je kunt er alleen maar aan werken. Je moet een wilsinspanning leveren, in het besef dat je niet alles zult vinden, maar in de overtuiging dat je alle redelijke aannames hebt gedaan, voor alle mogelijke gevallen hebt gezorgd, alle kritieke bugs hebt gesloten en dat alle deelnemers alles hebben gedaan wat ze konden. Hoe meer code je uitrolt, hoe moeilijker het is om jezelf hiervan te overtuigen (bovendien begrijpt iedereen dat het onmogelijk is om alles te voorzien).

We besloten dat we klaar waren om uit te rollen toen we ervan overtuigd waren dat we al het mogelijke hadden gedaan om alle risico's voor onze gebruikers die gepaard gaan met onverwachte gevolgen en stilstandtijden af ​​te dekken. Dat wil zeggen dat er van alles mis kan gaan, behalve:

  1. Beïnvloed de (voor ons meest waardevolle) gebruikersinfrastructuur,
  2. Functionaliteit: het gebruik van onze dienst na de uitrol moet hetzelfde zijn als ervoor.

Uitrollen

Een uitrolverhaal dat alles beïnvloedde
Twee rollen, 8 interfereren niet

We nemen een downtime van 7 uur voor alle verzoeken van gebruikers. Op dit moment hebben we zowel een uitrolplan als een terugdraaiplan.

  • De uitrol zelf duurt ongeveer 3 uur.
  • 2 uur voor testen.
  • 2 uur - reserveer voor een mogelijke terugdraaiing van wijzigingen.

Voor elke actie is een Gantt-diagram opgesteld, hoe lang het duurt, wat er opeenvolgend gebeurt, wat er parallel gebeurt.

Een uitrolverhaal dat alles beïnvloedde
Een stukje van een uitrol-Gantt-diagram, een van de vroege versies (zonder parallelle uitvoering). De meest waardevolle synchronisatietool

Voor alle deelnemers is hun rol bij de uitrol bepaald, welke taken zij uitvoeren en waarvoor zij verantwoordelijk zijn. We proberen elke fase naar automatisering te brengen, uit te rollen, terug te rollen, feedback te verzamelen en opnieuw uit te rollen.

Kroniek van gebeurtenissen

Zo kwamen er op zondag 15 april om 29 uur 10 mensen werken. Naast de belangrijkste deelnemers waren er ook enkelen die het team kwamen aanmoedigen, waarvoor speciale dank aan hen.

Vermeldenswaard is ook dat onze sleuteltester op vakantie is. Uitrollen zonder testen is onmogelijk, we onderzoeken de mogelijkheden. Een collega stemt ermee in om ons vanaf de vakantie te testen, waarvoor ze enorme dankbaarheid krijgt van het hele team.

00:00 uur. Stop
We houden gebruikersverzoeken tegen, hangen een bord op met de tekst 'Technisch werk'. De monitoring schreeuwt, maar alles is normaal. We controleren of er niets anders is gevallen dan wat had moeten vallen. En we beginnen te werken aan migratie.

Iedereen heeft punt voor punt een uitgeprint uitrolplan, iedereen weet wie wat doet en op welk moment. Na elke actie controleren we de timing om er zeker van te zijn dat we deze niet overschrijden, en alles verloopt volgens plan. Degenen die in de huidige fase niet direct aan de uitrol deelnemen, bereiden zich voor door een online speeltje (Xonotic, type 3 kwakzalvers) te lanceren om hun collega's niet te storen. 🙂

02:00 uur. Uitgerold
Een aangename verrassing: we ronden de uitrol een uur eerder af, dankzij de optimalisatie van onze databases en migratiescripts. De algemene kreet: “uitgerold!” Alle nieuwe functies zijn in productie, maar tot nu toe kunnen alleen wij ze in de interface zien. Iedereen gaat in de testmodus, sorteert ze in groepen en begint te zien wat er uiteindelijk is gebeurd.

Het pakte niet zo goed uit, dat beseffen we na 10 minuten, als er niets is aangesloten of werkt in de projecten van de teamleden. Snelle synchronisatie, we uiten onze problemen, stellen prioriteiten, verdelen teams en gaan aan de slag met debuggen.

02:30 uur. Twee grote problemen versus vier ogen
We constateren twee grote problemen. We realiseerden ons dat klanten bepaalde verbonden services niet zouden zien en dat er problemen zouden ontstaan ​​met partneraccounts. Beide zijn te wijten aan imperfecte migratiescripts voor sommige randgevallen. We moeten het nu repareren.

Wij schrijven queries die dit vastleggen, met minimaal 4 ogen. We testen ze tijdens de pre-productie om er zeker van te zijn dat ze werken en niets kapot maken. Je kunt verder rollen. Tegelijkertijd voeren we onze reguliere integratietests uit, waaruit nog een aantal problemen naar voren komen. Ze zijn allemaal klein, maar ze moeten ook gerepareerd worden.

03:00 uur. -2 problemen +2 problemen
De twee voorgaande grote problemen zijn opgelost, en bijna alle kleine ook. Iedereen die zich niet bezighoudt met oplossingen, werkt actief aan zijn accounts en rapporteert wat hij vindt. We prioriteren, verdelen onder teams en laten niet-kritieke items achter voor de ochtend.

Als we de tests opnieuw uitvoeren, ontdekken ze twee nieuwe grote problemen. Niet al het servicebeleid is correct aangekomen, waardoor sommige gebruikersverzoeken niet door de autorisatie komen. Plus een nieuw probleem met partneraccounts. Laten we ons haasten om te kijken.

03:20. Noodsynchronisatie
Eén nieuw probleem opgelost. Voor de tweede organiseren we een noodsynchronisatie. We begrijpen wat er gebeurt: de vorige oplossing loste één probleem op, maar creëerde een ander probleem. We nemen een pauze om erachter te komen hoe we dit correct en zonder gevolgen kunnen doen.

03:30 uur. Zes ogen
Wij begrijpen wat de eindtoestand van de basis moet zijn, zodat alles goed verloopt voor alle partners. We schrijven een verzoek met 6 ogen, rollen het uit in de pre-productie, testen het, rollen het uit voor productie.

04:00 uur. Alles werkt
Alle tests zijn geslaagd, er zijn geen kritische problemen zichtbaar. Af en toe werkt er iets in het team niet voor iemand, dan reageren we snel. Meestal is het alarm vals. Maar soms komt er iets niet aan, of werkt een aparte pagina niet. Wij zitten, repareren, repareren, repareren. Een apart team lanceert de laatste grote functie: facturering.

04:30 uur. Punt van geen terugkeer
Het point of no return nadert, dat wil zeggen het moment waarop we, als we beginnen terug te draaien, de downtime die ons is geboden niet zullen halen. Er zijn problemen met de facturering, die alles weet en registreert, maar koppig weigert geld van klanten af ​​te schrijven. Er zijn verschillende bugs op individuele pagina's, acties en statussen. De hoofdfunctionaliteit werkt, alle tests zijn succesvol verlopen. We besluiten dat de uitrol heeft plaatsgevonden, we gaan niet terugdraaien.

06:00 uur. Open voor iedereen in de gebruikersinterface
Bugs gefixed. Sommige die gebruikers niet aanspreken, blijven voor later. We openen de interface voor iedereen. We blijven werken aan de facturering, wachten op feedback van gebruikers en monitoren de resultaten.

07:00 uur. Problemen met het laden van de API
Het wordt duidelijk dat we de belasting van onze API enigszins verkeerd hebben gepland en deze belasting hebben getest, waardoor het probleem niet kon worden geïdentificeerd. Als gevolg hiervan mislukt ≈5% van de verzoeken. Laten we mobiliseren en op zoek gaan naar de reden.

Facturering is koppig en wil ook niet werken. We besluiten het uit te stellen tot later, zodat we de veranderingen op een rustige manier kunnen doorvoeren. Dat wil zeggen, alle middelen worden erin verzameld, maar afschrijvingen van klanten gaan niet door. Natuurlijk is dit een probleem, maar vergeleken met de algemene uitrol lijkt het onbelangrijk.

08:00 uur. API repareren
We hebben een oplossing voor de belasting uitgerold, de storingen verdwenen. We beginnen naar huis te gaan.

10:00 uur. Alle
Alles staat vast. Het is stil bij de monitoring en bij de klanten gaat het team geleidelijk aan slapen. De factuur blijft staan, we zullen deze morgen herstellen.

Gedurende de dag waren er implementaties die logs, meldingen, retourcodes en aanpassingen voor sommige van onze klanten herstelden.

De uitrol was dus succesvol! Het kan natuurlijk beter, maar we trokken conclusies over wat niet genoeg was om perfectie te bereiken.

In totaal

Tijdens een actieve voorbereiding van 2 maanden op de uitrol werden 43 taken voltooid, variërend van enkele uren tot meerdere dagen.

Tijdens de uitrol:

  • nieuwe en gewijzigde demonen - 5 stuks, ter vervanging van 2 monolieten;
  • veranderingen binnen de databases - alle 6 onze databases met gebruikersgegevens zijn getroffen, er zijn downloads gemaakt van drie oude databases naar één nieuwe;
  • volledig opnieuw ontworpen frontend;
  • hoeveelheid gedownloade code - 33 duizend regels nieuwe code, ≈ 3 duizend regels code in tests, ≈ 5 duizend regels migratiecode;
  • alle gegevens zijn intact en geen enkele virtuele machine van een klant is beschadigd. 🙂

Good practices voor een goede uitrol

Zij hebben ons begeleid in deze lastige situatie. Maar over het algemeen is het nuttig om ze tijdens elke uitrol te volgen. Maar hoe complexer de uitrol, hoe groter de rol die ze spelen.

  1. Het eerste dat u hoeft te doen, is begrijpen welke gevolgen de uitrol voor gebruikers kan of zal hebben. Zal er sprake zijn van downtime? Zo ja, wat is de downtime? Welke gevolgen heeft dit voor gebruikers? Wat zijn de mogelijke beste en slechtste scenario's? En dek de risico’s af.
  2. Plan alles. In elke fase moet u alle aspecten van de uitrol begrijpen:
    • levering van codes;
    • code terugdraaien;
    • tijd van elke bewerking;
    • aangetaste functionaliteit.
  3. Speel de scenario's totdat alle fasen van de uitrol, evenals de risico's bij elk ervan, duidelijk worden. Als u twijfelt, kunt u een pauze nemen en de twijfelachtige fase afzonderlijk onderzoeken.
  4. Elke fase kan en moet worden verbeterd als deze onze gebruikers helpt. Het zal bijvoorbeeld de downtime verminderen of bepaalde risico's wegnemen.
  5. Rollback-testen zijn veel belangrijker dan testen voor het leveren van code. Het is noodzakelijk om te controleren of het systeem als gevolg van het terugdraaien terugkeert naar de oorspronkelijke staat, en dit te bevestigen met tests.
  6. Alles wat geautomatiseerd kan worden, moet geautomatiseerd worden. Alles wat niet geautomatiseerd kan worden, moet vooraf op een spiekbriefje worden geschreven.
  7. Leg het succescriterium vast. Welke functionaliteit moet beschikbaar zijn en op welk tijdstip? Als dit niet gebeurt, voer dan een rollback-plan uit.
  8. En het allerbelangrijkste: mensen. Iedereen moet zich bewust zijn van wat ze doen, waarom en wat afhangt van hun acties tijdens het uitrolproces.

En in één zin kun je met een goede planning en uitwerking alles uitrollen wat je wilt, zonder gevolgen voor de verkoop. Zelfs iets dat van invloed zal zijn op al uw diensten in de productie.

Bron: www.habr.com

Voeg een reactie