CI/CD pro mikroslužby

Rychlejší cykly vydávání verzí představují hlavní výhodu architektury mikroslužeb. Bez spolehlivého procesu kontinuální integrace a průběžného doručování (CI/CD) ztratíte flexibilitu, kterou mikroslužby poskytují. Tento článek popisuje běžné problémy s CI/CD v architekturách mikroslužeb a doporučuje přístupy k vytváření, ověřování, zabezpečení a nasazování služeb nezávisle.

Co je CI/CD?

CI/CD označuje několik souvisejících procesů: kontinuální integraci, průběžné doručování a průběžné nasazování.

  • Kontinuální integrace (CI): Změny kódu se často sloučí do hlavní větve. Automatizované procesy sestavení a testování zajišťují, že kód v hlavní větvi je vždy v produkční kvalitě.

  • Průběžné doručování (CD): Změny kódu, které úspěšně projdou procesem CI, se automaticky nasazují do prostředí podobného produkčnímu. Nasazení do produkčního prostředí za provozu může vyžadovat ruční schválení, ale jinak je automatizované. Cílem je, že váš kód je vždy připravený k nasazení do produkčního prostředí.

  • Průběžné nasazování: Změny kódu, které předávají předchozí dva kroky, se automaticky nasadí do produkčního prostředí.

Zvažte následující cíle robustního procesu CI/CD pro architekturu mikroslužeb:

  • Každý tým může vytvářet a nasazovat služby, které vlastní nezávisle, aniž by to ovlivnilo nebo nenarušilo jiné týmy.

  • Před nasazením nové verze služby do produkčního prostředí se nasadí do prostředí pro vývoj/testování a kontrolu kvality pro účely ověření. V každé fázi se uplatňují brány kvality.

  • Vedle předchozí verze je možné nasadit novou verzi služby.

  • Jsou zavedeny dostatečné zásady řízení přístupu. Pipeline se vůči Azure ověřují pomocí krátkodobých federovaných přihlašovacích údajů místo dlouhodobých tajných údajů.

  • U kontejnerizovaných úloh můžete důvěřovat imagím kontejnerů, které jsou nasazené do produkčního prostředí. Tato důvěra se vytváří prostřednictvím podepsaných imagí, atestací k seznamu softwarových komponent (SBOM) a skenování zranitelností vynucovaného v pipeline.

Proč je důležité mít robustní CI/CD potrubí

V tradiční monolitické aplikaci vytvoří jeden kanál sestavení spustitelný soubor aplikace. Veškerá vývojová práce se integruje do tohoto kanálu. Pokud tým najde chybu s vysokou prioritou, musí být oprava integrovaná, otestovaná a publikovaná, což může zpozdit vydání nových funkcí. Tyto problémy můžete snížit pomocí dobře faktorizovaných modulů a větví funkcí, abyste omezili účinek změn kódu. Jak se však aplikace stává složitější a přibývají další funkce, proces vydávání monolitické aplikace bývá složitější a náchylnější k selhání.

Podle filozofie mikroslužeb by nikdy neměl existovat dlouhý proces vydávání, do kterého se každý tým musí zařadit. Tým, který sestaví službu A, může vydat aktualizaci, když zvolí a nemusí čekat na změny ve službě B ke sloučení, testování a nasazení.

Diagram, který porovnává CI/CD pro monolitické architektury a architektury mikroslužeb

Aby bylo možné dosáhnout rychlého nasazování, musí být nasazovací proces automatizovaný a vysoce spolehlivý, aby se minimalizovalo riziko. Pokud nasazujete do produkčního prostředí jednou nebo vícekrát denně, regrese ani výpadky služeb by neměly být časté. Zároveň platí, že pokud nasadíte chybnou aktualizaci, musíte mít spolehlivý způsob, jak se rychle vrátit na předchozí verzi služby nebo na ni rychle přejít.

Challenges

  • Mnoho malých nezávislých základů kódu: Každý tým zodpovídá za vytvoření vlastní služby s vlastním kanálem buildu. V některých organizacích můžou týmy používat samostatná úložiště kódu. Samostatná úložiště můžou rozptylovat znalosti o tom, jak vytvořit systém napříč týmy. V důsledku toho nikdo v organizaci neví, jak nasadit celou aplikaci.

    Opatření ke zmírnění: Zajistěte jednotnou a automatizovanou pipeline nebo alespoň společnou infrastrukturu pro pipeline pro sestavování a nasazování služeb, aby tyto znalosti nebyly ukryté v jednotlivých týmech. Opakovaně použitelné šablony kanálů, jako jsou GitHub Actions opakovaně použitelné pracovní postupy nebo šablony Azure Pipelines, pomáhají standardizovat sestavení, testovat, kontrolovat a nasazovat kroky napříč všemi službami.

  • Více jazyků a architektur: Každý tým používá vlastní kombinaci technologií, takže může být obtížné vytvořit jeden proces sestavení, který funguje v celé úloze. Proces sestavení musí být dostatečně flexibilní, aby ho každý tým mohl přizpůsobit pro zvolený jazyk nebo architekturu.

    Opatření: Kontejnerizujte proces sestavení u každé služby, aby systém sestavení musel pouze spouštět kontejnery. Platformy, jako jsou GitHub Actions, Azure Pipelines a úlohy Azure Container Registry můžou konzistentně vytvářet a publikovat image kontejnerů bez ohledu na zdrojový jazyk.

  • Integrace a zátěžové testování: Týmy vydávají aktualizace svým vlastním tempem, takže může být náročné navrhnout spolehlivé end-to-end testování, zejména pokud jsou služby závislé na jiných službách. Spuštění kompletního produkčního clusteru může být nákladné, takže je nepravděpodobné, že každý tým provozuje vlastní úplný cluster v produkčním měřítku jenom pro účely testování.

    Mitigation: Používejte dočasná testovací prostředí, například jmenné prostory pro každou žádost o přijetí změn v Kubernetes nebo prostředí Azure Container Apps, která se vytvářejí na vyžádání. Používejte testy kontraktů, abyste problémy s integrací mohli včas zobrazit bez nutnosti úplného škálování duplicity produkčního prostředí.

  • Správa verzí: Každý tým by měl být schopný nasadit aktualizaci do produkčního prostředí. Tento požadavek neznamená, že každý člen týmu má oprávnění k nasazení. Centralizovaná role správce verzí může snížit rychlost nasazení.

    Zmírnění: Čím více je proces CI/CD automatizovaný a spolehlivý, tím méně potřebujete centrální autoritu. Stále můžete mít různé zásady pro vydávání hlavních aktualizací funkcí a menší opravy chyb. Decentralizovaný přístup neznamená nulové zásady správného řízení. Vynucujte schvalování pomocí prostředí a schválení ve službě Azure Pipelines nebo prostředí nasazení v GitHub Actions a povinných schvalovatelů a definujte zásady na straně clusteru pomocí Azure Policy pro Azure Kubernetes Service (AKS) nebo OPA Gatekeeper.

  • Aktualizace služeb: Při aktualizaci služby na novou verzi by aktualizace neměla způsobit selhání jiných služeb, které na ní závisejí.

    Zmírnění: Použijte techniky nasazení, jako jsou modré zelené nebo kanárské verze, pro neprolomné změny. V případě zásadních změn rozhraní API nasaďte novou verzi souběžně s předchozí verzí. Díky tomuto přístupu je možné aktualizovat a testovat služby, které využívají předchozí rozhraní API. Další informace najdete v tématu Update Services.

  • Správa identit a tajných údajů v pipeline: Dlouhodobě platné tajné údaje instančního objektu služby uložené v pipeline jsou častým zdrojem narušení zabezpečení a dodatečné provozní práce. Tajné údaje instančního objektu služby expirují, mohou uniknout a vyžadují obměnu v mnoha nezávislých kanálech mikroslužeb.

    Zmírnění rizika: Ověřujte kanály vůči Azure pomocí federace identit úloh, která používá OpenID Connect (OIDC), takže se v kanálu neukládá žádný tajný klíč klienta. Další informace najdete v článcích Identity úloh pro Azure Pipelines a Konfigurace OpenID Connect v Azure pro GitHub Actions. Ukládejte všechny zbývající tajné kódy v Azure Key Vault a odkazujte na ně za běhu.

  • Zabezpečení dodavatelského řetězce: Vše, co odesíláte do produkčního prostředí, musí být trasovatelné pro kód a závislosti, ze kterého byl sestaven. Mikroslužby zvyšují počet imagí, registrů a kanálů, což zvyšuje prostor pro útoky dodavatelského řetězce.

    Zmírnění rizika: Podepisujte image kontejnerů pomocí Notation a Key Vault a ověřujte podpisy při přijímání pomocí funkce integrity imagí v AKS nebo Ratify. Vygenerujte SBOM jako artefakt sestavení. Skenujte kód, závislosti a kanály CI/CD pomocí Microsoft Defender for Cloud DevOps Security a GitHub Advanced Security. Kontrolujte image za běhu pomocí Microsoft Defender for Containers. Vyžadovat, aby před pokračováním vydání prošly všechny skeny.

Monorepo vs. multirepo

Před vytvořením pracovního postupu CI/CD musíte vědět, jak je základ kódu strukturovaný a spravovaný, včetně:

  • Ať už týmy pracují v samostatných úložištích, nebo v monorepo.
  • Vaše strategie větvení.
  • Kdo může odeslat kód do produkčního prostředí a jestli existuje správce verzí.

Týmy v produkci široce používají oba přístupy. Vaše volba závisí na topologii týmu, vyspělosti nástrojů a na tom, kolik kódu se sdílí napříč službami.

  Monorepo Více repozitářů
Výhody - Sdílení kódu

- Jednodušší standardizace kódu a nástrojů

- Jednodušší refaktorování kódu

– Zjistitelnost (jediné zobrazení kódu)
- Jasné vlastnictví pro každý tým

– Potenciálně méně konfliktů při slučování

- Pomáhá vynucovat oddělení mikroslužeb.
výzvy – Změny sdíleného kódu můžou mít vliv na více mikroslužeb.

- Větší potenciál konfliktů při slučování

- Nástroje musí být škálovatelné pro rozsáhlou kódovou základnu.

- Řízení přístupu

– Složitější proces nasazení
- Obtížnější sdílet kód

- Obtížnější vynucovat standardy kódování

– Správa závislostí

- Difuzní základ kódu, špatná zjistitelnost

- Nedostatek sdílené infrastruktury

Bez ohledu na to, který model zvolíte, používejte ve svých pipelinech triggery omezené na konkrétní cesty, například filtry cest v GitHub Actions nebo cesty triggerů v Azure Pipelines. Triggery omezené na cestu pomáhají zajistit, aby se při každém commitu znovu sestavily a nasadily pouze dotčené mikroslužby.

Aktualizace služeb

Existují různé strategie aktualizace služby, která je již v produkčním prostředí, včetně postupné aktualizace, modrého zeleného nasazení a kanárkové verze. Tyto vzory se často koordinují prostřednictvím pracovního postupu GitOps. Další informace najdete v tématu GitOps a postupné doručování.

Postupné aktualizace

V kumulativní aktualizaci nasadíte nové instance služby a nové instance začnou přijímat žádosti okamžitě. Jakmile budou nové instance připravené, předchozí instance se odeberou.

Příklad v Kubernetes: V Kubernetes jsou kumulativní aktualizace výchozím chováním při aktualizaci specifikace podu pro nasazení. Řadič nasazení vytvoří nový objekt ReplicaSet pro aktualizované pody. Poté navýší nový ReplicaSet a současně sníží předchozí ReplicaSet tak, aby byl zachován požadovaný počet replik. Neodstraní předchozí pody, dokud nebudou nové pody připravené. Kubernetes uchovává historii aktualizace, takže v případě potřeby můžete vrátit aktualizaci zpět.

Příklad v kontejnerových aplikacích: Container Apps používá revize ke správě kumulativních aktualizací. Když nasadíte novou revizi, služba Container Apps může postupně přesouvat provoz z předchozí revize na novou revizi pomocí pravidel rozdělení provozu. Pokud nová revize narazí na problémy, můžete vrátit zpět přesměrováním provozu na předchozí revizi. Můžete současně nakonfigurovat více aktivních revizí a řídit procento provozu, které každá revize obdrží.

Jednou z výzev průběžných aktualizací je, že během aktualizace současně běží předchozí i nové verze a přijímají provoz. Během této doby může systém směrovat jakýkoli požadavek na některou verzi.

V případě zásadních změn rozhraní API je dobrým postupem podporovat obě verze vedle sebe, dokud nebudou aktualizováni všichni klienti předchozí verze. Další informace najdete v tématu Správa verzí rozhraní API.

Nasazení pomocí strategie modrá-zelená

V modrém nasazení nasadíte novou verzi společně s předchozí verzí. Po ověření nové verze přepnete veškerý provoz najednou z předchozí verze na novou verzi. Po přepnutí monitorujete aplikaci v případě jakýchkoli problémů. Pokud dojde k problému, můžete přepnout provoz zpět na předchozí verzi. Pokud nedojde k žádným problémům, můžete předchozí verzi odstranit.

V případě tradiční monolitické nebo N-vrstvé aplikace obecně modré-zelené nasazení znamená, že vytvoříte dvě identická prostředí. Novou verzi nasadíte do přípravného prostředí a pak přesměrujete klientský provoz do daného prostředí, například tak, že prohodíte virtuální IP adresu. V architektuře mikroslužeb dochází k aktualizacím na úrovni mikroslužby, takže aktualizaci obvykle nasadíte do stejného prostředí a k přepnutí provozu použijete mechanismus zjišťování služeb.

Příklad v Kubernetes: V Kubernetes nemusíte vytvářet samostatný cluster, abyste mohli provádět nasazení s modrou zelenou barvou. Místo toho můžete využít selektory. Vytvořte nový prostředek Deployment s novou specifikací Podu a jinou sadou štítků. Vytvořte toto nasazení, ale neodstraňujte předchozí nasazení ani neupravujte službu, která na něj odkazuje. Po spuštění nových podů můžete aktualizovat selektor služby tak, aby odpovídal novému nasazení.

Jednou z nevýhod modrého nasazení je, že během aktualizace spustíte dvakrát tolik podů pro službu (aktuální a další). Pokud pody využívají značné prostředky CPU nebo paměti, možná budete muset cluster dočasně rozšířit, aby pokryl vyšší nároky na prostředky.

Kanárské vydání

V kanárské verzi nasadíte aktualizovanou verzi do malé podmnožině klientů a pak budete sledovat chování nové služby, než ji nasadíte pro všechny klienty. Díky tomuto přístupu můžete postupně zavádět řízeným způsobem, monitorovat skutečná data a identifikovat problémy předtím, než ovlivní všechny zákazníky.

Kanárské vydání je složitější pro správu než modrá zelená nebo kumulativní aktualizace, protože žádosti musíte dynamicky směrovat do různých verzí služby.

Příklad v Kubernetes: V Kubernetes můžete nakonfigurovat službu tak, aby přesahovali dvě sady replik (jednu pro každou verzi) a počet replik upravte ručně. Tento přístup je však hrubozrnný vzhledem k tomu, jak Kubernetes vyrovnává zatížení mezi pody. Pokud máte například celkem 10 replik, můžete provoz přesunout pouze po 10% přírůstcích. Pokud používáte síť služeb, můžete použít pravidla směrování sítě služeb k implementaci sofistikovanější kanárské strategie vydávání.

Příklad ve službě Container Apps: Ve službě Container Apps můžete pomocí rozdělení provozu směrovat stanovené procento provozu na novou revizi (například 10 % na v2, zatímco 90 % zůstává na v1) a s rostoucí důvěrou upravovat poměry, aniž by byl vyžadován externí service mesh.

Progresivní doručování a GitOps

Pro týmy, které v Kubernetes provozují mnoho mikroslužeb, představuje GitOps pull model vhodný doplněk k dříve uvedeným příkladům založeným na push principu. Požadovaný stav clusteru se nachází v Gitu a operátor v clusteru tento stav odsouhlasí. CI sestaví, otestuje, proskenuje, podepíše a nahraje image. CD uvede cluster do souladu s manifestem. Toto oddělení vám poskytuje auditní záznamy a usnadňuje obnovu po havárii (DR). Zároveň eliminuje potřebu, aby spouštěč CI držel přímé přihlašovací údaje clusteru.

Další kroky