Snellere releasecycli zijn een van de belangrijkste voordelen van microservicesarchitecturen. Maar zonder een goed CI/CD-proces bereikt u niet de flexibiliteit die microservices beloven. In dit artikel worden de uitdagingen beschreven en worden enkele benaderingen van het probleem aanbevolen.
Wat is CI/CD?
Wanneer we het hebben over CI/CD, hebben we het echt over verschillende gerelateerde processen: continue integratie, continue levering en continue implementatie.
continue integratie. Codewijzigingen worden vaak samengevoegd in de hoofdbranch. Geautomatiseerde build- en testprocessen zorgen ervoor dat code in de hoofdvertakking altijd productiekwaliteit is.
continue levering. Alle codewijzigingen die het CI-proces doorgeven, worden automatisch gepubliceerd naar een productieachtige omgeving. Implementatie in de live productieomgeving kan handmatige goedkeuring vereisen, maar wordt anders geautomatiseerd. Het doel is dat uw code altijd gereed moet zijn voor implementatie in productie.
continue implementatie. Codewijzigingen die de vorige twee stappen doorstaan, worden automatisch geïmplementeerd in productie.
Hier volgen enkele doelstellingen van een robuust CI/CD-proces voor een microservicesarchitectuur:
Elk team kan de services bouwen en implementeren die het onafhankelijk bezit, zonder dat dit van invloed is op andere teams of deze onderbroken heeft.
Voordat een nieuwe versie van een service in productie wordt geïmplementeerd, wordt deze geïmplementeerd in ontwikkel-/test-/QA-omgevingen voor validatie. Kwaliteitspoorten worden in elke fase afgedwongen.
Een nieuwe versie van een service kan naast de vorige versie worden geïmplementeerd.
Er zijn voldoende beleidsregels voor toegangsbeheer aanwezig.
Voor workloads in containers kunt u de containerinstallatiekopieën vertrouwen die zijn geïmplementeerd in productie.
Waarom een robuuste CI/CD-pijplijn belangrijk is
In een traditionele monolithische toepassing is er één build-pijplijn waarvan de uitvoer het uitvoerbare bestand van de toepassing is. Alle ontwikkelingswerkzaamheden worden in deze pijplijn ingevoerd. Als er een fout met hoge prioriteit wordt gevonden, moet een oplossing worden geïntegreerd, getest en gepubliceerd, waardoor de release van nieuwe functies kan worden vertraagd. U kunt deze problemen verhelpen door goed gefactoreerde modules te gebruiken en functievertakkingen te gebruiken om de impact van codewijzigingen te minimaliseren. Maar naarmate de toepassing complexer wordt en er meer functies worden toegevoegd, wordt het releaseproces voor een monolith meer broos en zal deze waarschijnlijk breken.
Na de microservices-filosofie mag er nooit een lange releasetrein zijn waar elk team in de rij moet komen. Het team dat service 'A' bouwt, kan op elk gewenst moment een update vrijgeven zonder te wachten op wijzigingen in service B, die moeten worden samengevoegd, getest en geïmplementeerd.
Om een hoge releasesnelheid te bereiken, moet uw release-pijplijn geautomatiseerd en zeer betrouwbaar zijn om het risico te minimaliseren. Als u een of meer keren per dag in productie gaat, moeten regressies of serviceonderbrekingen zeldzaam zijn. Als een slechte update wordt geïmplementeerd, moet u tegelijkertijd een betrouwbare manier hebben om snel terug te draaien of terug te draaien naar een eerdere versie van een service.
Uitdagingen
Veel kleine onafhankelijke codebasissen. Elk team is verantwoordelijk voor het bouwen van een eigen service, met een eigen build-pijplijn. In sommige organisaties kunnen teams afzonderlijke codeopslagplaatsen gebruiken. Afzonderlijke opslagplaatsen kunnen leiden tot een situatie waarin de kennis over het bouwen van het systeem verspreid is over teams en niemand in de organisatie weet hoe de hele toepassing moet worden geïmplementeerd. Wat gebeurt er bijvoorbeeld in een scenario voor herstel na noodgevallen als u snel naar een nieuw cluster wilt implementeren?
Risicobeperking: zorg voor een geïntegreerde en geautomatiseerde pijplijn voor het bouwen en implementeren van services, zodat deze kennis niet 'verborgen' is binnen elk team.
meerdere talen en frameworks. Bij elk team dat een eigen combinatie van technologieën gebruikt, kan het lastig zijn om één bouwproces te maken dat in de hele organisatie werkt. Het buildproces moet flexibel genoeg zijn om elk team dit aan te passen aan de keuze van taal of framework.
Mitigation: Containerize the build process for each service. Op die manier moet het buildsysteem alleen de containers kunnen uitvoeren.
integratie- en belastingstests. Als teams updates in hun eigen tempo vrijgeven, kan het lastig zijn om robuuste end-to-end tests te ontwerpen, met name wanneer services afhankelijk zijn van andere services. Bovendien kan het uitvoeren van een volledig productiecluster duur zijn, dus het is onwaarschijnlijk dat elk team een eigen volledig cluster op productieschaal uitvoert, alleen voor tests.
Releasebeheer. Elk team moet een update naar productie kunnen implementeren. Dat betekent niet dat elk teamlid machtigingen heeft om dit te doen. Maar als u een gecentraliseerde Release Manager-rol hebt, kan de snelheid van implementaties worden verminderd.
Risicobeperking: hoe meer uw CI/CD-proces geautomatiseerd en betrouwbaar is, hoe minder er een centrale instantie nodig is. Dat gezegd hebbende, hebt u mogelijk verschillende beleidsregels voor het vrijgeven van belangrijke functie-updates versus kleine bugfixes. Gedecentraliseerd zijn betekent niet nul governance.
Service-updates. Wanneer u een service bijwerkt naar een nieuwe versie, mag deze geen onderbreking van andere services zijn die ervan afhankelijk zijn.
Risicobeperking: gebruik implementatietechnieken zoals blauwgroen of kanarierelease voor niet-belangrijke wijzigingen. Voor belangrijke API-wijzigingen implementeert u de nieuwe versie naast de vorige versie. Op die manier kunnen services die de vorige API gebruiken, worden bijgewerkt en getest voor de nieuwe API. Zie Services bijwerkenhieronder.
Monorepo versus meerdere opslagplaatsen
Voordat u een CI/CD-werkstroom maakt, moet u weten hoe de codebasis wordt gestructureerd en beheerd.
- Werken teams in afzonderlijke opslagplaatsen of in een monorepo (één opslagplaats)?
- Wat is uw vertakkingsstrategie?
- Wie kan code naar productie pushen? Is er een releasemanagerrol?
De monorepo-benadering heeft voordeel gewonnen, maar er zijn voor- en nadelen voor beide.
Monorepo | Meerdere opslagplaatsen | |
---|---|---|
voordelen | Code delen Eenvoudiger om code en hulpprogramma's te standaardiseren Eenvoudiger om code te herstructureren Detectie : één weergave van de code |
Eigendom per team wissen Mogelijk minder samenvoegingsconflicten Helpt bij het afdwingen van ontkoppeling van microservices |
uitdagingen | Wijzigingen in gedeelde code kunnen van invloed zijn op meerdere microservices Groter potentieel voor samenvoegingsconflicten Hulpprogramma's moeten worden geschaald naar een grote codebasis Toegangsbeheer Complexer implementatieproces |
Moeilijker om code te delen Moeilijker om coderingsstandaarden af te dwingen Afhankelijkheidsbeheer Diffuse codebasis, slechte detectie Gebrek aan gedeelde infrastructuur |
Services bijwerken
Er zijn verschillende strategieën voor het bijwerken van een service die al in productie is. Hier bespreken we drie algemene opties: Rolling update, blue-green deployment en canary release.
Rolling updates
In een doorlopende update implementeert u nieuwe exemplaren van een service en de nieuwe exemplaren ontvangen meteen aanvragen. Naarmate de nieuwe exemplaren worden weergegeven, worden de vorige exemplaren verwijderd.
Voorbeeld. In Kubernetes zijn rolling updates het standaardgedrag wanneer u de podspecificatie voor een Deploymentbijwerkt. De implementatiecontroller maakt een nieuwe ReplicaSet voor de bijgewerkte pods. Vervolgens wordt de nieuwe ReplicaSet omhoog geschaald tijdens het omlaag schalen van de oude replica om het gewenste aantal replica's te behouden. Oude pods worden pas verwijderd als de nieuwe klaar zijn. Kubernetes houdt een geschiedenis van de update bij, zodat u indien nodig een update kunt terugdraaien.
Voorbeeld. Azure Service Fabric maakt standaard gebruik van de strategie voor rolling updates. Deze strategie is het meest geschikt voor het implementeren van een versie van een service met nieuwe functies zonder bestaande API's te wijzigen. Service Fabric start een upgrade-implementatie door het toepassingstype bij te werken naar een subset van de knooppunten of een updatedomein. Vervolgens wordt het naar het volgende updatedomein doorgestuurd totdat alle domeinen zijn bijgewerkt. Als een upgradedomein niet kan worden bijgewerkt, wordt het toepassingstype teruggezet naar de vorige versie in alle domeinen. Houd er rekening mee dat een toepassingstype met meerdere services (en als alle services worden bijgewerkt als onderdeel van één upgrade-implementatie) gevoelig is voor fouten. Als de ene service niet kan worden bijgewerkt, wordt de hele toepassing teruggedraaid naar de vorige versie en worden de andere services niet bijgewerkt.
Een uitdaging van rolling updates is dat tijdens het updateproces een combinatie van oude en nieuwe versies wordt uitgevoerd en verkeer ontvangt. Gedurende deze periode kan elke aanvraag worden doorgestuurd naar een van de twee versies.
Voor belangrijke API-wijzigingen is het raadzaam beide versies naast elkaar te ondersteunen totdat alle clients van de vorige versie worden bijgewerkt. Zie API-versiebeheer.
Blauwgroene implementatie
In een blauwgroene implementatie implementeert u de nieuwe versie naast de vorige versie. Nadat u de nieuwe versie hebt gevalideerd, schakelt u al het verkeer in één keer over van de vorige versie naar de nieuwe versie. Na de switch bewaakt u de toepassing op eventuele problemen. Als er iets misgaat, kunt u terugschakelen naar de oude versie. Ervan uitgaande dat er geen problemen zijn, kunt u de oude versie verwijderen.
Met een meer traditionele monolithische of N-tier-toepassing betekende de implementatie blauw-groen doorgaans dat twee identieke omgevingen worden ingericht. U zou de nieuwe versie implementeren in een faseringsomgeving en vervolgens clientverkeer omleiden naar de faseringsomgeving, bijvoorbeeld door VIP-adressen te wisselen. In een microservicearchitectuur worden updates uitgevoerd op het niveau van de microservice, dus u zou de update doorgaans in dezelfde omgeving implementeren en een servicedetectiemechanisme gebruiken om te wisselen.
voorbeeld van. In Kubernetes hoeft u geen afzonderlijk cluster in te richten om blauwgroene implementaties uit te voeren. In plaats daarvan kunt u profiteren van selectors. Maak een nieuwe Deployment resource met een nieuwe podspecificatie en een andere set labels. Maak deze implementatie zonder de vorige implementatie te verwijderen of de service te wijzigen die naar deze implementatie verwijst. Zodra de nieuwe pods worden uitgevoerd, kunt u de selector van de service bijwerken zodat deze overeenkomt met de nieuwe implementatie.
Een nadeel van blauwgroene implementatie is dat u tijdens de update twee keer zoveel pods voor de service uitvoert (huidige en volgende). Als voor de pods veel CPU- of geheugenresources nodig zijn, moet u het cluster mogelijk tijdelijk uitschalen om het resourceverbruik af te handelen.
Canary-release
In een canary-release rolt u een bijgewerkte versie uit naar een klein aantal clients. Vervolgens bewaakt u het gedrag van de nieuwe service voordat u deze voor alle clients uitrolt. Hiermee kunt u een trage implementatie op een gecontroleerde manier uitvoeren, echte gegevens observeren en problemen opsporen voordat alle klanten worden beïnvloed.
Een canary-release is complexer om te beheren dan blauw-groen of rolling update, omdat u aanvragen dynamisch moet routeren naar verschillende versies van de service.
voorbeeld van. In Kubernetes kunt u een Service- configureren om twee replicasets (één voor elke versie) te omvatten en het aantal replica's handmatig aan te passen. Deze benadering is echter nogal grof, vanwege de manier waarop Kubernetes-belasting wordt verdeeld over pods. Als u bijvoorbeeld in totaal 10 replica's hebt, kunt u alleen verkeer verplaatsen in stappen van 10%. Als u een service-mesh gebruikt, kunt u de regels voor service-mesh-routering gebruiken om een geavanceerdere canary-releasestrategie te implementeren.
Volgende stappen
- Leertraject: Continue integratie definiëren en implementeren
- Training: Inleiding tot continue levering
- Microservices-architectuur
- Waarom een microservicesbenadering gebruiken voor het bouwen van toepassingen