Infrastructuur als code: hoe we Ons ontwikkelings- / releaseproces vernieuwd om onze teamschaal te omarmen

(11 dec.2020)

In dit artikel laten we zien hoe we in het verleden met ons continue implementatieproces omgingen, wat ons ertoe aanzette om te veranderen wat we hebben, en welke inspanningen we hebben geleverd om het proces zo eenvoudig / effectief mogelijk te maken.

Het artikel geeft misschien een eerste smaak aan de devops, maar in wezen beïnvloedt het releaseproces alle teams en hoe ze zelfstandig functioneren of samenwerken met andere teams, zullen we laten zien hoe rollen worden verschoven door het proces te veranderen.

Over ons

Wij bij Halan helpen met het aanbieden van oplossingen voor het aanreiken van ritten en logistieke on-demand ( termijnen, levering, online betalingen, e-commerce) voor de onderbediende bevolking door de bestaande technologieën in transport en andere diensten, kunt u onze ap p hier ( android / iOS )

Het oude proces geven het is verschuldigd, het goede en het slechte

We zullen beginnen met hoe we ons proces in het verleden hebben aangepakt en hoe dat ons positief of negatief heeft beïnvloed.

Voor mijn team hebben we bijna alles geïmplementeerd via AWS met GitHub als ons versiebeheersysteem, dus we moeten een manier vinden om functies van onze GitHub-opslagplaatsen naar AWS-services te verzenden.

Implementaties voor versiebeheer

We vertrouwd op AWS-codepipeline , stellen we triggers in om een ​​ implementatiepipeline te starten telkens wanneer een nieuwe commit wordt samengevoegd in een van de hoofdtakken die de bekende stadia vertegenwoordigen: dev , prod en staging omgevingen.

overzicht van hoe implementaties worden geactiveerd

Deze stroom betekent dat elke functie op de master branch zich op productie bevindt, die het samenvoegen tot master zeker een taboe-onderwerp maakt om te bespreken en niet iedereen had die toestemming om je PR op master samen te voegen.

Hetzelfde gold voor andere branches, maar dat was niet Het is echt een probleem, aangezien dev en staging-envs niet echt zo eng zijn.

Onze QC is begonnen met het testen en verifiëren van functies wanneer ze worden samengevoegd op de staging, wat betekent dat ze eerst testen op staging-env en vervolgens als ze geverifieerd zijn , zal de functie worden samengevoegd in de master branch. dat lijkt goed te werken, maar laten we eens kijken naar de nadelen van een dergelijk proces.

Hierdoor konden we meerdere functies tegelijkertijd testen en implementeren in elke fase (dev, staging), wat goed en slecht is in tegelijkertijd omdat:

  • Dat betekent dat ontwikkelaars niet op elkaar hoeven te wachten om controle te krijgen over de dev / staging-omgeving.
  • Maar het betekent dat functies op dev-fase kan ten onrechte ertoe leiden dat elkaar niet werken of work (vals positief), en beide gevallen zijn erg slecht en kunnen ervoor zorgen dat code in productie gaat terwijl het niet echt werkt.

Divergerende takken, onnodige rebasen

Zoals je misschien al hebt opgemerkt, hebben we gezegd dat om te implementeren op dev env, je moet je code samenvoegen in de dev branch. Welnu, dat deel bracht helaas snel de tijdlijn van onze branch in de war omdat:

  • Niet alle features die op dev zijn getest, gaan in productie, dus we hadden als ghost commits die rondslingerden in onze verenigde dev branch .
  • Zonder twijfel een experimenteerlab, mensen kunnen na een tijdje ontdekken dat ze iets verkeerds hebben gedaan en besluiten om hun code / commits te laten vallen en een nieuwe te starten, maar dat laat ons nog steeds achter met hun oude commits samengevoegd op de dev branch.

Dit soort gedrag produceerde wat we divergentie tussen branches noemen, om een ​​ feature branch die master heeft als base in dev, moet je conflicten ! wat onhandig is dat je letterlijk in conflict komt met geesten en dingen oplost die nooit meer in de productie zullen zijn, dat geeft je zeker twee slechte opties:

  • Bouw een nieuwe branch voor je feature, geforkt uit je originele feature branch en los conflicten daarop op, en als je klaar bent met testen, merge je de originele branch in master.
  • Los conflicten in je branch op en kies vervolgens je commits in een nieuwe branch bij het samenvoegen met master.

Met meer ontwikkelaars die ons team vervoegen, zullen de dingen lelijker worden en divergentie zal zeker een stijging vergen.

Het build / deploy-proces vernieuwen

Het eerste wat we in gedachten hadden is hoe we van die divergerende branches af kunnen komen, we hebben een nieuwe methode nodig om functies naadloos aan de productie te leveren en te bepalen hoeveel functies in de productie worden geïmplementeerd zonder broncontrole te betrekken bij de implementatie.

Een kleine bespreking van AWS

Eerst moeten we de belangrijkste elementen die bij ons een rol zullen spelen in het proces:

  • Github : source control met opslagplaatsen voor elke microservice die er is.
  • Amazon ECR : een Docker-imageregister dat is onderverdeeld in `repos`, vertegenwoordigt elke repo ook een microservice en bevat de afbeeldingen die zijn gepusht voor service X en die rechtstreeks kunnen worden gebruikt of geïmplementeerd in deze service om deze te laten werken.
  • Amazon ECS / EC2 / EKS : dit is waar onze microservices leven, samen met hun omgevingen, ECS is verdeeld in clusters, elk cluster bevat een aantal services, elk heeft een taakdefinitie die informatie bevat zoals omgevingsvariabelen , rekenspecificaties, netwerk, enz.

We moeten dus een manier vinden om deze samen te binden, zodat het voor ons als ontwikkelaarsteam gemakkelijker wordt om functies te leveren en voor QC om deze te controleren en te verifiëren functies.

We dachten dat we een tussenliggende service konden definiëren, een service die verantwoordelijk is voor implementatie van andere services. We hadden twee hoofdopdrachten die we met deze service wilden laten afhandelen:

  • Build-opdracht: we wil in staat zijn om een ​​image te bouwen en deze naar ECR te pushen vanuit elke branch / commit die we willen van een bepaalde GitHub-repo naar een bepaalde ECR-repo.
  • Deploy Command: we willen in staat zijn om een ​​bepaalde afbeelding van een opslagplaats op ECR te implementeren naar alle clusters met service X.

Laten we nemen elk van deze commandos onder de loep nemen en zien wat elk ervan inhoudt, we beginnen met de Build Commando:

  • Allereerst moeten we de repo klonen bij de gespecificeerde commit / branch.
  • Bouw een docker-image met behulp van de Dockerfile in die repo.
  • Push de afbeelding gebouwd naar ECR-repo met een nieuwe tag indien nodig of als laatste.

Hoewel al deze stappen zeker doab zijn le in onze nieuwe implementatieservice, maar we ontdekten dat het omslachtig is omdat het bouwen van docker afbeeldingen veel resources en dat zal onze nieuwe service beperken tot een paar gelijktijdige implementaties of maak het zo gigantisch in resources.

We dachten dat we in plaats van al dit werk aan de service zelf te doen, een nieuwe workflow op Github op die repo en geef het allemaal door taakdetails, zoals naar welke tak moet worden afgerekend en naar welke ECR-opslagplaats moet worden gepusht, als het eindelijk klaar is, zal het de gebruiker terug signaleren met een web-hook . Natuurlijk zijn daar andere oplossingen voor, zoals Jenkins voor betere beveiliging om ervoor te zorgen dat je code wordt gebouwd op machines die je beheert.

Dat veranderde de workflow die we hierboven noemden, het gaat nu als volgt:

  • Ontvang bouwdetails van de gebruiker.
  • Activeer een Github actie op de gespecificeerde opslagplaats.
  • Github-acties zullen een nieuwe machine draaien die ons zal informeren over de buildstatus wanneer gedaan, zal het de commit ook taggen met het Jira-kaartnummer waar je aan werkt.

Tweede commando is het Depoly commando, dat veel eenvoudiger is dan het build commando, we hoeven hier alleen:

  • Ontvang implementatiedetails van de gebruiker.
  • Start een nieuwe implementatietaak op elk cluster dat de service bevat en geef de afbeeldings-URL op in ECR.

implementatieworkflow

Dat is echt het voor implementatie! gewoon een faciliterende taak tussen twee AWS-producten, laten we deze workflow vergelijken met wat we eerder hadden en kijken hoe onze releasestrategie veranderde.

Het gebruik van het nieuwe proces om uw code te implementeren op een van de fasen (prod, dev, staging) vereist geen enkele vorm van fusies , de code is volledig onafhankelijk van de implementatie , we zouden 20 features klaar op de master branch en kies er alleen voor om te implementeren 10 van hen.

Maar dit impliceert ook dat we maar één functie kunnen hebben getest op de dev-branch tenzij twee ontwikkelaars het eens waren met rebase op elkaar.

Implementatiegeschiedenis en tagging

Dit leverde ons ook een betere rollback strategie tegen productieproblemen. Nu hebben we een getagde master branch voor elke feature / taak die we hadden, telkens als we een productieprobleem tegenkomen en een functie willen terugdraaien, kunnen we gemakkelijk terug navigeren naar waar deze functie begon en indien mogelijk terugdraaien naar de vastlegging ervoor.

Ook dat stelde ons in staat om alle werkende features op de master branch samen te voegen, zelfs als ze niet geïmplementeerd gaan worden, kunnen we ze nog steeds op master klaar hebben staan ​​voor de volgende batch features die in productie komen wanneer dat nodig is, dat zal zeker onze teamfocus op het leveren van taken zonder zich zorgen te hoeven maken over wanneer die taak zal worden samengevoegd tot master om te worden geïmplementeerd, hier voegen we eerst samen en maken ons vervolgens zorgen over implementaties.

Volgende stappen

We werken momenteel aan automatisering ons proces beter, inclusief omgevingsvariabelen en machinespecificaties, ze zullen allemaal beschikbaar zijn als code, telkens wanneer we die specificaties wijzigen, wordt dat automatisch ect op onze machines op AWS in de respectievelijke Omgeving , het is niet nodig om deze waarden elke keer met de hand te coderen op AWS.

Hiermee hebben we een betere controle en zichtbaarheid van al onze dienstenconfiguraties, alles in onze infrastructuur zal in code zijn en één klik verwijderd om te updaten! ook dat maakt het wijzigen van onze infrastructuur onafhankelijk van de serviceprovider, we kunnen bijvoorbeeld overschakelen van AWS naar Google Cloud en hoeven alleen de commandos te wijzigen die door de implementatieservice worden gebruikt om onze infrastructuur op de nieuwe serviceprovider te implementeren.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *