Vytvoření kanálu CI/CD pro mikroslužby v Kubernetes pomocí Azure DevOps a Helmu

Azure Kubernetes Service (AKS)
Azure Container Registry
Azure DevOps

Vytvoření spolehlivého procesu kontinuální integrace a průběžného doručování (CI/CD) pro architekturu mikroslužeb může být náročné. Jednotlivé týmy musí být schopny rychle a spolehlivě vydávat služby, aniž by narušovaly jiné týmy nebo aktivovaly aplikaci jako celek.

Tento článek popisuje příklad kanálu CI/CD pro nasazení mikroslužeb do služby Azure Kubernetes Service (AKS). Každý tým a projekt se liší, takže tento článek nepoužívejte jako sadu pevných a rychlých pravidel. Místo toho je to výchozí bod pro návrh vlastního procesu CI/CD.

Cíle kanálu CI/CD pro hostované mikroslužby Kubernetes je možné shrnout takto:

  • Týmy můžou vytvářet a nasazovat své služby nezávisle.
  • Změny kódu, které předají proces CI, se automaticky nasadí do produkčního prostředí.
  • Brány kvality se vynucují v každé fázi kanálu.
  • Vedle předchozí verze je možné nasadit novou verzi služby.

Další informace najdete v tématu CI/CD pro architektury mikroslužeb.

Předpoklady

Pro účely tohoto příkladu je zde několik předpokladů o vývojovém týmu a základu kódu:

  • Úložiště kódu je monorepo s složkami uspořádanými podle mikroslužby.
  • Strategie větvení týmu je založená na vývoji založeném na kmenech.
  • Tým používá větve vydaných verzí ke správě vydaných verzí. Pro každou mikroslužbu se vytvoří samostatné verze.
  • Proces CI/CD používá Azure Pipelines k sestavení, testování a nasazení mikroslužeb do AKS.
  • Image kontejnerů pro každou mikroslužbu se ukládají ve službě Azure Container Registry.
  • Tým používá k balení jednotlivých mikroslužeb grafy Helm.
  • Používá se model nabízeného nasazení, kde Azure Pipelines a přidružené agenty provádějí nasazení připojením přímo ke clusteru AKS.

Tyto předpoklady řídí mnoho konkrétních podrobností kanálu CI/CD. Základní přístup, který je zde popsaný, se ale přizpůsobí jiným procesům, nástrojům a službám, jako je Jenkins nebo Docker Hub.

Alternativy

Níže jsou uvedené běžné alternativy, které zákazníci můžou použít při výběru strategie CI/CD se službou Azure Kubernetes Service:

  • Jako alternativu k použití nástroje Helm jako správy balíčků a nasazení je Kustomize nativní nástroj pro správu konfigurace Kubernetes, který představuje bezplatný způsob přizpůsobení a parametrizace konfigurace aplikace.
  • Jako alternativu k používání Azure DevOps pro úložiště a kanály Gitu je možné úložiště GitHub použít pro privátní a veřejná úložiště Git a GitHub Actions je možné použít pro kanály CI/CD.
  • Jako alternativu k použití modelu nabízeného nasazení je možné spravovat konfiguraci Kubernetes ve velkém měřítku pomocí GitOps (model nasazení vyžádané replikace), kde operátor Kubernetes v clusteru synchronizuje stav clusteru na základě konfigurace uložené v úložišti Git.

Sestavení ověření

Předpokládejme, že vývojář pracuje na mikroslužbě označované jako Služba doručování. Při vývoji nové funkce vývojář zkontroluje kód do větve funkcí. Podle konvence se větve funkcí nazývají feature/*.

CI/CD workflow

Definiční soubor sestavení obsahuje trigger, který filtruje podle názvu větve a zdrojové cesty:

trigger:
  batch: true
  branches:
    include:
    # for new release to production: release flow strategy
    - release/delivery/v*
    - refs/release/delivery/v*
    - master
    - feature/delivery/*
    - topic/delivery/*
  paths:
    include:
    - /src/shipping/delivery/

Pomocí tohoto přístupu může mít každý tým vlastní kanál buildu. Sestavení služby Delivery Service aktivuje pouze kód, který je vrácený se změnami do /src/shipping/delivery složky. Nasdílení potvrzení do větve, která odpovídá filtru, aktivuje sestavení CI. V tomto okamžiku v pracovním postupu spustí sestavení CI několik minimálních ověření kódu:

  1. Sestavte kód.
  2. Spusťte testy jednotek.

Cílem je udržovat časy sestavení krátké, aby vývojář mohl získat rychlou zpětnou vazbu. Jakmile je tato funkce připravená ke sloučení s hlavním serverem, otevře vývojář žádost o přijetí změn. Tato operace aktivuje další sestavení CI, které provede několik dalších kontrol:

  1. Sestavte kód.
  2. Spusťte testy jednotek.
  3. Sestavte image kontejneru modulu runtime.
  4. Spusťte kontroly ohrožení zabezpečení na imagi.

Diagram showing ci-delivery-full in the Build pipeline.

Poznámka:

V Azure DevOps Repos můžete definovat zásady pro ochranu větví. Zásada může například vyžadovat úspěšné sestavení CI a od schvalovatele od schvalovatele, aby bylo možné sloučit do hlavního serveru.

Úplné sestavení CI/CD

V určitém okamžiku je tým připravený nasadit novou verzi služby Delivery Service. Správce verzí vytvoří větev z hlavní větve s tímto vzorem pojmenování: release/<microservice name>/<semver>. Například release/delivery/v1.0.2.

Diagram showing ci-delivery-full in the Build pipeline and cd-delivery in the Release pipeline.

Vytvoření této větve aktivuje úplné sestavení CI, které spustí všechny předchozí kroky a navíc:

  1. Nasdílení image kontejneru do služby Azure Container Registry Obrázek je označen číslem verze převzatým z názvu větve.
  2. Spuštěním helm package zabalíte chart Helm pro službu. Graf je také označen číslem verze.
  3. Odešlete balíček Helm do služby Container Registry.

Za předpokladu, že se sestavení podaří, aktivuje proces nasazení (CD) pomocí kanálu verze Azure Pipelines. Tento kanál má následující kroky:

  1. Nasaďte chart Helm do prostředí pro kontrolu kvality.
  2. Schvalovatel se před přesunem balíčku do produkčního prostředí odhlásí. Viz Řízení nasazení verzí pomocí schválení.
  3. Znovu napište image Dockeru pro produkční obor názvů ve službě Azure Container Registry. Pokud je myrepo.azurecr.io/delivery:v1.0.2například aktuální značka , je myrepo.azurecr.io/prod/delivery:v1.0.2produkční značka .
  4. Nasaďte chart Helm do produkčního prostředí.

I v monorepo je možné tyto úlohy vymezit na jednotlivé mikroslužby, aby týmy mohly nasazovat s vysokou rychlostí. Tento proces má několik ručních kroků: Schvalování žádostí o přijetí změn, vytváření větví vydaných verzí a schvalování nasazení do produkčního clusteru. Tyto kroky jsou ruční; můžou být automatizované, pokud organizace preferuje.

Izolace prostředí

Budete mít několik prostředí, ve kterých nasazujete služby, včetně prostředí pro vývoj, orientační testování, testování integrace, zátěžové testování a nakonec produkčního prostředí. Tato prostředí potřebují určitou úroveň izolace. V Kubernetes máte na výběr mezi fyzickou izolací a logickou izolací. Fyzická izolace znamená nasazení do samostatných clusterů. Logická izolace používá obory názvů a zásady, jak je popsáno výše.

Naším doporučením je vytvořit vyhrazený produkční cluster spolu s samostatným clusterem pro vaše vývojová/testovací prostředí. Logická izolace slouží k oddělení prostředí v rámci vývojového/testovacího clusteru. Služby nasazené do clusteru pro vývoj/testování by nikdy neměly mít přístup k úložištům dat, která obsahují obchodní data.

Proces sestavení

Pokud je to možné, zabalte proces sestavení do kontejneru Dockeru. Tato konfigurace umožňuje vytvářet artefakty kódu pomocí Dockeru a bez konfigurace prostředí sestavení na každém počítači sestavení. Proces kontejnerizovaného sestavení usnadňuje horizontální navýšení kapacity kanálu CI přidáním nových agentů sestavení. Každý vývojář v týmu může také jednoduše sestavit kód spuštěním kontejneru sestavení.

Pomocí vícefázových sestavení v Dockeru můžete definovat prostředí sestavení a image modulu runtime v jednom souboru Dockerfile. Tady je například soubor Dockerfile, který sestaví aplikaci .NET:

FROM mcr.microsoft.com/dotnet/core/runtime:3.1 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src/Fabrikam.Workflow.Service

COPY Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.csproj

COPY Fabrikam.Workflow.Service/. .
RUN dotnet build Fabrikam.Workflow.Service.csproj -c release -o /app --no-restore

FROM build AS testrunner
WORKDIR /src/tests

COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj

COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]

FROM build AS publish
RUN dotnet publish Fabrikam.Workflow.Service.csproj -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Fabrikam.Workflow.Service.dll"]

Tento soubor Dockerfile definuje několik fází sestavení. Všimněte si, že fáze s názvem base používá modul runtime .NET, zatímco fáze s názvem build používá úplnou sadu .NET SDK. Fáze build se používá k sestavení projektu .NET. Konečný kontejner modulu runtime je ale sestavený z basemodulu runtime, který obsahuje pouze modul runtime a je výrazně menší než úplná image sady SDK.

Sestavení testovacího spouštěče

Dalším dobrým postupem je spuštění testů jednotek v kontejneru. Tady je například část souboru Dockeru, který sestaví spouštěč testů:

FROM build AS testrunner
WORKDIR /src/tests

COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj

COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]

Vývojář může k místnímu spuštění testů použít tento soubor Dockeru:

docker build . -t delivery-test:1 --target=testrunner
docker run delivery-test:1

Kanál CI by měl také spouštět testy v rámci kroku ověření sestavení.

Všimněte si, že tento soubor ke spuštění testů používá příkaz Dockeru ENTRYPOINT , nikoli příkaz Dockeru RUN .

  • Pokud použijete RUN příkaz, testy se spustí při každém sestavení image. Pomocí ENTRYPOINT, testy jsou opt-in. Spustí se jenom tehdy, když explicitně cílíte na testrunner fázi.
  • Neúspěšný test nezpůsobí selhání příkazu Dockeru build . Tímto způsobem můžete rozlišovat selhání sestavení kontejneru od selhání testů.
  • Výsledky testů je možné uložit na připojený svazek.

Osvědčené postupy pro kontejnery

Tady je několik dalších osvědčených postupů, které je potřeba zvážit pro kontejnery:

  • Definujte konvence pro značky kontejnerů, správu verzí a zásady vytváření názvů pro prostředky nasazené do clusteru (pody, služby atd.). To může usnadnit diagnostiku problémů s nasazením.

  • Během vývojového a testovacího cyklu proces CI/CD sestaví mnoho imagí kontejnerů. Pouze některé z těchto imagí jsou kandidáty na vydání a pak se do produkčního prostředí dostanou pouze někteří z těchto kandidátů. Máte jasnou strategii správy verzí, abyste věděli, které image jsou aktuálně nasazené do produkčního prostředí, a v případě potřeby se vraťte k předchozí verzi.

  • Vždy nasaďte konkrétní značky verze kontejneru, nikoli latest.

  • Pomocí oborů názvů ve službě Azure Container Registry můžete izolovat image schválené pro produkční prostředí od imagí, které se stále testují. Nepřesouvejte image do produkčního oboru názvů, dokud nebudete připravení ji nasadit do produkčního prostředí. Pokud tento postup zkombinujete s sémantickou správou verzí imagí kontejnerů, může snížit pravděpodobnost náhodného nasazení verze, která nebyla schválena pro vydání.

  • Postupujte podle principu nejnižšího oprávnění spuštěním kontejnerů jako neprivilegovaného uživatele. V Kubernetes můžete vytvořit zásady zabezpečení podu, které brání spuštění kontejnerů jako kořenového adresáře.

Charty Helm

Zvažte použití Nástroje Helm ke správě sestavování a nasazování služeb. Tady jsou některé funkce Nástroje Helm, které pomáhají s CI/CD:

  • Jedna mikroslužba je často definována několika objekty Kubernetes. Helm umožňuje zabalit tyto objekty do jednoho chartu Helm.
  • Graf je možné nasadit pomocí jednoho příkazu Helm, nikoli pomocí řady příkazů kubectl.
  • Grafy jsou explicitně verze. Použijte Helm k vydání verze, zobrazení verzí a vrácení zpět na předchozí verzi. Sledováníaktualizacích
  • Grafy Helm používají šablony, aby se zabránilo duplikování informací, jako jsou popisky a selektory, napříč mnoha soubory.
  • Helm může spravovat závislosti mezi grafy.
  • Grafy se dají ukládat do úložiště Helm, jako je Azure Container Registry, a integrovat do kanálu buildu.

Další informace o používání služby Container Registry jako úložiště Helm najdete v tématu Použití služby Azure Container Registry jako úložiště Helm pro grafy aplikací.

Jedna mikroslužba může zahrnovat několik konfiguračních souborů Kubernetes. Aktualizace služby může znamenat, že se dotkne všech těchto souborů a aktualizuje selektory, popisky a značky obrázků. Helm je považuje za jeden balíček označovaný jako graf a umožňuje snadno aktualizovat soubory YAML pomocí proměnných. Helm používá jazyk šablony (založený na šablonách Go) k zápisu parametrizovaných konfiguračních souborů YAML.

Tady je například část souboru YAML, která definuje nasazení:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "package.fullname" . | replace "." "" }}
  labels:
    app.kubernetes.io/name: {{ include "package.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
  annotations:
    kubernetes.io/change-cause: {{ .Values.reason }}

...

  spec:
      containers:
      - name: &package-container_name fabrikam-package
        image: {{ .Values.dockerregistry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        env:
        - name: LOG_LEVEL
          value: {{ .Values.log.level }}

Uvidíte, že název nasazení, popisky a specifikace kontejneru používají parametry šablony, které jsou k dispozici v době nasazení. Například z příkazového řádku:

helm install $HELM_CHARTS/package/ \
     --set image.tag=0.1.0 \
     --set image.repository=package \
     --set dockerregistry=$ACR_SERVER \
     --namespace backend \
     --name package-v0.1.0

I když váš kanál CI/CD může nainstalovat graf přímo do Kubernetes, doporučujeme vytvořit archiv grafu (soubor .tgz) a nasdílit graf do úložiště Helm, jako je Azure Container Registry. Další informace najdete v tématu Balení aplikací založených na Dockeru v chartech Helm v Azure Pipelines.

Revize

Grafy Helm mají vždy číslo verze, které musí používat sémantickou správu verzí. Graf může mít také .appVersion Toto pole je volitelné a nemusí souviset s verzí grafu. Některé týmy můžou chtít verze aplikací odděleně od aktualizací grafů. Jednodušší je ale použít jedno číslo verze, takže existuje vztah 1:1 mezi verzí grafu a verzí aplikace. Tímto způsobem můžete uložit jeden graf na každou verzi a snadno nasadit požadovanou verzi:

helm install <package-chart-name> --version <desiredVersion>

Dalším dobrým postupem je poskytnout poznámku k příčině změny v šabloně nasazení:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "delivery.fullname" . | replace "." "" }}
  labels:
     ...
  annotations:
    kubernetes.io/change-cause: {{ .Values.reason }}

To vám umožní zobrazit pole příčiny změny pro každou revizi pomocí kubectl rollout history příkazu. V předchozím příkladu je příčina změny k dispozici jako parametr chartu Helm.

kubectl rollout history deployments/delivery-v010 -n backend
deployment.extensions/delivery-v010
REVISION  CHANGE-CAUSE
1         Initial deployment

Historii revizí můžete zobrazit také pomocí helm list příkazu:

helm list
NAME            REVISION    UPDATED                     STATUS        CHART            APP VERSION     NAMESPACE
delivery-v0.1.0 1           Sun Apr  7 00:25:30 2020    DEPLOYED      delivery-v0.1.0  v0.1.0          backend

Kanál Azure DevOps

V Azure Pipelines jsou kanály rozdělené na kanály buildu a kanály verze. Kanál buildu spustí proces CI a vytvoří artefakty sestavení. Pro architekturu mikroslužeb v Kubernetes jsou tyto artefakty image kontejnerů a grafy Helm, které definují jednotlivé mikroslužby. Kanál verze spustí proces CD, který nasadí mikroslužbu do clusteru.

Na základě toku CI popsaného výše v tomto článku se kanál buildu může skládat z následujících úloh:

  1. Sestavte kontejner test runneru.

    - task: Docker@1
      inputs:
        azureSubscriptionEndpoint: $(AzureSubscription)
        azureContainerRegistry: $(AzureContainerRegistry)
        arguments: '--pull --target testrunner'
        dockerFile: $(System.DefaultWorkingDirectory)/$(dockerFileName)
        imageName: '$(imageName)-test'
    
  2. Testy spusťte vyvoláním dockeru proti kontejneru test runneru.

    - task: Docker@1
      inputs:
        azureSubscriptionEndpoint: $(AzureSubscription)
        azureContainerRegistry: $(AzureContainerRegistry)
        command: 'run'
        containerName: testrunner
        volumes: '$(System.DefaultWorkingDirectory)/TestResults:/app/tests/TestResults'
        imageName: '$(imageName)-test'
        runInBackground: false
    
  3. Publikujte výsledky testu. Viz Sestavení image.

    - task: PublishTestResults@2
      inputs:
        testResultsFormat: 'VSTest'
        testResultsFiles: 'TestResults/*.trx'
        searchFolder: '$(System.DefaultWorkingDirectory)'
        publishRunAttachments: true
    
  4. Sestavte kontejner modulu runtime.

    - task: Docker@1
      inputs:
        azureSubscriptionEndpoint: $(AzureSubscription)
        azureContainerRegistry: $(AzureContainerRegistry)
        dockerFile: $(System.DefaultWorkingDirectory)/$(dockerFileName)
        includeLatestTag: false
        imageName: '$(imageName)'
    
  5. Nasdílení image kontejneru do služby Azure Container Registry (nebo jiného registru kontejneru)

    - task: Docker@1
      inputs:
        azureSubscriptionEndpoint: $(AzureSubscription)
        azureContainerRegistry: $(AzureContainerRegistry)
        command: 'Push an image'
        imageName: '$(imageName)'
        includeSourceTags: false
    
  6. Zabalte chart Helm.

    - task: HelmDeploy@0
      inputs:
        command: package
        chartPath: $(chartPath)
        chartVersion: $(Build.SourceBranchName)
        arguments: '--app-version $(Build.SourceBranchName)'
    
  7. Nasdílení balíčku Helm do služby Azure Container Registry (nebo jiného úložiště Helm)

    task: AzureCLI@1
      inputs:
        azureSubscription: $(AzureSubscription)
        scriptLocation: inlineScript
        inlineScript: |
        az acr helm push $(System.ArtifactsDirectory)/$(repositoryName)-$(Build.SourceBranchName).tgz --name $(AzureContainerRegistry);
    

Výstupem z kanálu CI je image kontejneru připravená pro produkční prostředí a aktualizovaný chart Helm pro mikroslužbu. V tuto chvíli může kanál verze převzít. Pro každou mikroslužbu bude existovat jedinečný kanál verze. Kanál verze bude nakonfigurovaný tak, aby měl zdroj triggeru nastavený na kanál CI, který publikoval artefakt. Tento kanál umožňuje mít nezávislá nasazení jednotlivých mikroslužeb. Kanál verze provede následující kroky:

  • Nasaďte chart Helm do vývojových/qa/přípravných prostředí. Příkaz Helm upgrade lze použít s příznakem --install pro podporu první instalace a následných upgradů.
  • Počkejte, až schvalovatel schválí nebo odmítne nasazení.
  • Opětovné označení image kontejneru pro vydání
  • Odešle značku vydané verze do registru kontejneru.
  • Nasaďte chart Helm v produkčním clusteru.

Další informace o vytvoření kanálu verze najdete v tématu Kanály verze, koncepty verzí a možnosti verze.

Následující diagram znázorňuje kompletní proces CI/CD popsaný v tomto článku:

CD/CD pipeline

Přispěvatelé

Tento článek spravuje Microsoft. Původně byla napsána následujícími přispěvateli.

Hlavní autor:

  • John Poole | Vedoucí architekt cloudových řešení

Pokud chcete zobrazit neveřejné profily LinkedIn, přihlaste se na LinkedIn.

Další kroky