Tutorial: Verwenden einer Canary-Bereitstellungsstrategie für Kubernetes-Bereitstellungen
Azure DevOps Services | Azure DevOps Server 2022
Eine Canary-Bereitstellungsstrategie sieht die Bereitstellung neuer Versionen einer Anwendung neben stabilen Produktionsversionen vor. Sie können dann erkennen, wie die Canary-Version im Vergleich zur Baseline abschneidet, ehe Sie die Bereitstellung höherstufen oder ablehnen.
In dieser Schritt-für-Schritt-Anleitung wird erläutert, wie Sie die Canary-Strategie für die Kubernetes-Manifestaufgabe umsetzen. Insbesondere erfahren Sie, wie Sie Canary-Bereitstellungen für Kubernetes und den zugehörigen Workflow zum Bewerten von Code einrichten. Anschließend vergleichen Sie anhand dieses Codes Baseline- und Canary-App-Bereitstellungen, sodass Sie entscheiden können, ob sie die Canary-Bereitstellung höherstufen oder ablehnen.
Wenn Sie Azure Kubernetes Service verwenden, ist der Azure Resource Manager-Dienstverbindungstyp die beste Möglichkeit, eine Verbindung mit einem privaten Cluster oder einem Cluster mit deaktivierten lokalen Konten herzustellen.
Voraussetzungen
- Ein Azure-Konto mit einem aktiven Abonnement. Sie können kostenlos ein Konto erstellen.
- Ein GitHub-Konto. Sofern nicht bereits geschehen, können Sie ein kostenloses GitHub-Konto erstellen.
- Eine Azure Container Registry-Instanz mit Pushberechtigungen. Erstellen Sie eine Azure Container Registry-Instanz, sofern Sie noch keine haben.
- Ein Kubernetes-Cluster. Stellen Sie einen Azure Kubernetes Service-Cluster (AKS) bereit.
Beispielcode
Forken Sie das folgende Repository auf GitHub.
https://github.com/MicrosoftDocs/azure-pipelines-canary-k8s
Hier finden Sie eine Kurzübersicht über die Dateien im Repository, die in dieser Anleitung verwendet werden:
- ./app:
- app.py: ein einfacher, auf Flask basierender Webserver, der mithilfe der Prometheus-Instrumentierungsbibliothek für Python-Anwendungen instrumentiert ist. Ein benutzerdefinierter Zähler wird für die Anzahl von guten und schlechten Antworten eingerichtet, die basierend auf dem Wert der Variablen
success_rate
ausgegeben werden. - Dockerfile: dient zum Erstellen des Images mit jeder an app.py erfolgten Änderung. Bei jeder Änderung wird die Buildpipeline ausgelöst, das Image erstellt und in die Containerregistrierung gepusht.
- app.py: ein einfacher, auf Flask basierender Webserver, der mithilfe der Prometheus-Instrumentierungsbibliothek für Python-Anwendungen instrumentiert ist. Ein benutzerdefinierter Zähler wird für die Anzahl von guten und schlechten Antworten eingerichtet, die basierend auf dem Wert der Variablen
- ./manifests:
- deployment.yml: enthält die Spezifikation der Bereitstellungsworkload von
sampleapp
, die dem zuvor veröffentlichten Image entspricht. Sie verwenden diese Manifestdatei nicht nur für die stabile Version des Bereitstellungsobjekts, sondern auch für die Ableitung der Baseline- und Canary-Varianten der Workloads. - service.yml: dient zum Erstellen des
sampleapp
-Diensts. Dieser Dienst leitet Anforderungen an die Pods weiter, die von den zuvor erwähnten Bereitstellungen (Stabil, Baseline und Canary) bereitgestellt werden.
- deployment.yml: enthält die Spezifikation der Bereitstellungsworkload von
- ./misc
- service-monitor.yml: dient zum Einrichten eines ServiceMonitor-Objekts. Dieses Objekt richtet das Scraping von Prometheus-Metriken ein.
- fortio-deploy.yml: dient zum Einrichten einer fortio-Bereitstellung. Diese Bereitstellung wird später als Tool für Auslastungstests verwendet, um einen Datenstrom von Anforderungen an den zuvor bereitgestellten
sampleapp
-Dienst zu senden. Der Datenstrom der ansampleapp
gesendeten Anforderungen wird unter allen drei Bereitstellungen (Stabil, Baseline und Canary) an Pods weitergeleitet.
Hinweis
In diesem Leitfaden verwenden Sie für Codeinstrumentierung und Überwachung Prometheus. Alternativ kann eine gleichwertige Lösung, wie z. B. Azure Application Insights, zum Einsatz kommen.
Installieren von prometheus-operator
Zum Installieren von Prometheus in Ihrem Cluster führen Sie auf Ihrem Entwicklungscomputer den folgenden Befehl aus. kubectl und Helm müssen installiert sein, und Sie müssen den Kontext auf den Cluster festlegen, für den Sie die Bereitstellung vornehmen möchten. Grafana, das Sie später zum Visualisieren der Baseline- und Canary-Metriken in Dashboards nutzen, wird als Teil dieses Helm-Diagramms installiert.
Sie fügen zuerst das Prometheus Community Kubernetes Helm Charts Repository zu Ihrer Helm-Installation hinzu. Anschließend installieren Sie den kube-prometheus-Stapel, eine Sammlung von Kubernetes-Manifesten, Grafana-Dashboards und Prometheus-Regeln.
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update # update local cache
helm install --name sampleapp prometheus-community/kube-prometheus-stack
Erstellen von Dienstverbindungen
- Navigieren Sie im Azure DevOps-Menü zu Projekteinstellungen>Pipelines>Dienstverbindungen.
- Erstellen Sie eine Docker-Registrierungsdienstverbindung, die Ihrer Containerregistrierung zugeordnet ist. Nennen Sie sie azure-pipelines-canary-k8s.
- Erstellen Sie eine Kubernetes-Dienstverbindung für den Kubernetes-Cluster und -Namespace, in dem die Bereitstellung erfolgen soll. Nennen Sie sie azure-pipelines-canary-k8s.
Hinweis
Wenn Sie Azure Kubernetes Service verwenden, ist der Azure Resource Manager-Dienstverbindungstyp die beste Möglichkeit, eine Verbindung mit einem privaten Cluster oder einem Cluster mit deaktivierten lokalen Konten herzustellen.
Einrichten von Continuous Integration
Wechseln Sie zu Pipelines>Pipeline erstellen, und wählen Sie Ihr Repository aus.
Wählen Sie auf der Registerkarte Konfigurieren die Option Starterpipeline aus.
Ersetzen Sie auf der Registerkarte Überprüfen den YAML-Code der Pipeline durch diesen Code.
trigger: - main pool: vmImage: ubuntu-latest variables: imageName: azure-pipelines-canary-k8s steps: - task: Docker@2 displayName: Build and push image inputs: containerRegistry: azure-pipelines-canary-k8s #replace with name of your Docker registry service connection repository: $(imageName) command: buildAndPush Dockerfile: app/Dockerfile tags: | $(Build.BuildId)
Wenn die von Ihnen erstellte Docker-Registrierungsdienstverbindung
example.azurecr.io
zugeordnet ist, wird das Image auf Grundlage der vorherigen Konfiguration mitexample.azurecr.io/azure-pipelines-canary-k8s:$(Build.BuildId)
verbunden.
Bearbeiten der Manifestdatei
Ersetzen Sie <example>
in manifests/deployment.yml durch die URL Ihrer Containerregistrierung. Nach Ersetzen sollte das Feld „Image“ beispielsweise etwa so contosodemo.azurecr.io/azure-pipelines-canary-k8s
aussehen.
Einrichten der fortlaufenden Bereitstellung
In den folgenden Abschnitten erfahren Sie, wie Sie Continuous Deployment einrichten, die Canary-Phase bereitstellen und das Canary-Projekt durch manuelle Eingriffe höherstufen oder ablehnen können.
Bereitstellen der Canary-Phase
Sie können die Bereitstellung mit YAML oder klassisch durchführen.
Wechseln Sie zu Pipelines>Umgebungen>Umgebung erstellen.
Erstellen Sie eine neue Umgebung.
- Name: akscanary
- Ressource: Wählen Sie Kubernetes.
Wählen Sie Weiter aus, und konfigurieren Sie Ihre Kubernetes-Ressource wie folgt:
- Anbieter: Azure Kubernetes Service
- Azure-Abonnement: Wählen Sie das Abonnement mit Ihrem Kubernetes-Cluster.
- Cluster-: Wählen Sie Ihren Cluster aus.
- Namespace: Erstellen Sie einen neuen Namespace mit dem Namen canarydemo.
Wählen Sie Überprüfen und erstellen aus.
Navigieren Sie zu Pipelines. Wählen Sie die Pipeline aus, die Sie erstellt haben, und dann Bearbeiten aus.
Ändern Sie den zuvor erstellten Schritt so, dass nun eine Phase verwendet wird. Fügen Sie zwei weitere Schritte hinzu, um die Manifeste und misc-Verzeichnisse als Artefakte zur Verwendung durch aufeinander folgende Phasen zu kopieren. Möglicherweise möchten Sie auch ein paar Werte in Variablen verlagern, um sie später in Ihrer Pipeline leichter verwenden zu können. Ihr vollständiger YAML-Code sollte nun wie folgt aussehen.
trigger: - main pool: vmImage: ubuntu-latest variables: imageName: azure-pipelines-canary-k8s dockerRegistryServiceConnection: dockerRegistryServiceConnectionName #replace with name of your Docker registry service connection imageRepository: 'azure-pipelines-canary-k8s' containerRegistry: example.azurecr.io #replace with the name of your container registry, Should be in the format example.azurecr.io tag: '$(Build.BuildId)' stages: - stage: Build displayName: Build stage jobs: - job: Build displayName: Build pool: vmImage: ubuntu-latest steps: - task: Docker@2 displayName: Build and push image inputs: containerRegistry: $(dockerRegistryServiceConnection) repository: $(imageName) command: buildAndPush Dockerfile: app/Dockerfile tags: | $(tag) - publish: manifests artifact: manifests - publish: misc artifact: misc
Fügen Sie am Ende Ihrer YAML-Datei eine Phase hinzu, um die Canary-Version bereitzustellen.
- stage: DeployCanary displayName: Deploy canary dependsOn: Build condition: succeeded() jobs: - deployment: Deploycanary displayName: Deploy canary pool: vmImage: ubuntu-latest environment: 'akscanary.canarydemo' strategy: runOnce: deploy: steps: - task: KubernetesManifest@0 displayName: Create imagePullSecret inputs: action: createSecret secretName: azure-pipelines-canary-k8s dockerRegistryEndpoint: azure-pipelines-canary-k8s - task: KubernetesManifest@0 displayName: Deploy to Kubernetes cluster inputs: action: 'deploy' strategy: 'canary' percentage: '25' manifests: | $(Pipeline.Workspace)/manifests/deployment.yml $(Pipeline.Workspace)/manifests/service.yml containers: '$(containerRegistry)/$(imageRepository):$(tag)' imagePullSecrets: azure-pipelines-canary-k8s - task: KubernetesManifest@0 displayName: Deploy Forbio and ServiceMonitor inputs: action: 'deploy' manifests: | $(Pipeline.Workspace)/misc/*
Speichern Sie Ihre Pipeline durch einen direkten Commit im Mainbranch. Durch diesen Commit sollte Ihre Pipeline bereits erfolgreich ausgeführt werden.
Manuelles Eingreifen zum Höherstufen oder Ablehnen des Canarys
Sie können manuell mit YAML oder klassisch eingreifen.
Wechseln Sie zu Pipelines>Umgebungen>Neue Umgebung.
Konfigurieren Sie die neue Umgebung.
- Name: akspromote
- Ressource: Wählen Sie Kubernetes.
Wählen Sie Weiter aus, und konfigurieren Sie Ihre Kubernetes-Ressource wie folgt:
- Anbieter: Azure Kubernetes Service
- Azure-Abonnement: Wählen Sie das Abonnement mit Ihrem Kubernetes-Cluster.
- Cluster: Wählen Sie Ihren Cluster.
- Namespace: Wählen Sie den zuvor erstellten Namespace canarydemo.
Wählen Sie Überprüfen und erstellen aus.
Wählen Sie in der Liste der Umgebungen Ihre neue
akspromote
-Umgebung aus.Wählen Sie Genehmigungen und Überprüfungen>Genehmigungen aus. Wählen Sie dann das Auslassungssymbol (die drei Punkte) aus.
Konfigurieren Sie Ihre Genehmigung wie folgt:
- Genehmigende Personen: Fügen Sie Ihr eigenes Benutzerkonto hinzu.
- Erweitert: Stellen Sie sicher, dass das Kontrollkästchen Genehmigern erlauben, ihre eigenen Ausführungen zu genehmigen aktiviert ist.
Klicken Sie auf Erstellen.
Wechseln Sie zu Pipelines, und wählen Sie die Pipeline aus, die Sie erstellt haben. Klicken Sie dann auf Bearbeiten.
Fügen Sie eine weitere Phase,
PromoteRejectCanary
, am Ende Ihrer YAML-Datei hinzu, um die Änderungen höherzustufen.- stage: PromoteRejectCanary displayName: Promote or Reject canary dependsOn: DeployCanary condition: succeeded() jobs: - deployment: PromoteCanary displayName: Promote Canary pool: vmImage: ubuntu-latest environment: 'akspromote.canarydemo' strategy: runOnce: deploy: steps: - task: KubernetesManifest@0 displayName: promote canary inputs: action: 'promote' strategy: 'canary' manifests: '$(Pipeline.Workspace)/manifests/*' containers: '$(containerRegistry)/$(imageRepository):$(tag)' imagePullSecrets: '$(imagePullSecret)'
Fügen Sie eine weitere Phase,
RejectCanary
, am Ende Ihrer YAML-Datei hinzu, um für die Änderungen ein Rollback auszuführen.- stage: RejectCanary displayName: Reject canary dependsOn: PromoteRejectCanary condition: failed() jobs: - deployment: RejectCanary displayName: Reject Canary pool: vmImage: ubuntu-latest environment: 'akscanary.canarydemo' strategy: runOnce: deploy: steps: - task: KubernetesManifest@0 displayName: reject canary inputs: action: 'reject' strategy: 'canary' manifests: '$(Pipeline.Workspace)/manifests/*'
Speichern Sie Ihre YAML-Pipeline, indem Sie Speichern auswählen, und committen Sie sie direkt im Mainbranch.
Bereitstellen einer stabilen Version
Sie können eine stabile Version mit YAML oder klassisch bereitstellen.
Für die erste Ausführung der Pipeline sind die stabile Version der Workloads und ihre Baseline- oder Canary-Versionen nicht im Cluster vorhanden. So stellen Sie die stabile Version bereit
- Ändern Sie
success_rate = 5
in app/app.py insuccess_rate = 10
. Diese Änderung löst die Pipeline aus, was zu einem Build und Push des Images in die Containerregistrierung führt. Außerdem wird die PhaseDeployCanary
ausgelöst. - Da Sie eine Genehmigung für die
akspromote
Umgebung konfiguriert haben, wartet die Veröffentlichung, bevor diese Phase ausgeführt wird. - Wählen Sie in der Zusammenfassung der Ausführung Überprüfen>Genehmigen aus. Dadurch wird die stabile Version der Workloads (die
sampleapp
-Bereitstellung in manifests/deployment.yml) im Namespace bereitgestellt.
Einleiten des Canary-Workflows
Die stabile Version der Workload sampleapp
ist jetzt im Cluster vorhanden. Nehmen Sie als Nächstes an der Simulationsanwendung die folgende Änderung vor:
Ändern Sie success_rate = 10
in app/app.py in success_rate = 20
.
Diese Änderung löst die Buildpipeline aus, was zum Build und Push des Images in die Containerregistrierung führt. Dieser Prozess löst wiederum die Releasepipeline aus und startet die Phase Canary bereitstellen.
Simulieren von Anforderungen
Führen Sie auf Ihrem Entwicklungscomputer die folgenden Befehle aus, und sorgen Sie dafür, dass ein konstanter Datenstrom von Anforderungen an den sampleapp
-Dienst gesendet wird. sampleapp
leitet die Anforderungen an die Pods weiter, die von der stabilen sampleapp
Bereitstellung ausgeführt werden, und an die Pods, die von den sampleapp-baseline
- und sampleapp-canary
-Bereitstellungen ausgeführt werden. Der für sampleapp
angegebene Selektor gilt für alle diese Pods.
FORTIO_POD=$(kubectl get pod | grep fortio | awk '{ print $1 }')
kubectl exec -it $FORTIO_POD -c fortio /usr/bin/fortio -- load -allow-initial-errors -t 0 http://sampleapp:8080/
Einrichten des Grafana-Dashboards
Führen Sie auf Ihrem lokalen Entwicklungscomputer den folgenden Befehl zur Portweiterleitung aus, um auf Grafana zugreifen zu können.
kubectl port-forward svc/sampleapp-grafana 3000:80
Öffnen Sie in einem Browser die folgende URL.
http://localhost:3000/login
Wenn Sie zur Eingabe von Anmeldeinformationen aufgefordert werden, können Sie die folgenden Werte verwenden, es sei denn, der Wert
adminPassword
wurde während der Installation des Helm-Diagramms fürprometheus-operator
überschrieben:- Benutzername: admin
- Kennwort: prom-operator
Wählen Sie im Menü auf der linken Seite +>Dashboard>Graph aus.
Wählen Sie eine beliebige Stelle im neu hinzugefügten Bereich aus, und geben Sie
e
ein, um den Bereich zu bearbeiten.Geben Sie auf der Registerkarte Metriken die folgende Abfrage ein:
rate(requests_total{pod=~"sampleapp-.*", custom_status="good"}[1m])
Ändern Sie auf der Registerkarte Allgemein den Namen dieses Bereichs in Alle Beispiel-App-Pods.
Ändern Sie auf der Übersichtsleiste oben auf der Seite den Bereich „Dauer“ in Letzte 5 Minuten oder Letzte 15 Minuten.
Wählen Sie zum Speichern dieses Bereichs auf der Übersichtsleiste das Symbol „Speichern“ aus.
Im vorherigen Bereich werden Erfolgsquotenmetriken aus allen Varianten visualisiert. Dazu gehören „Stabil“ (aus der
sampleapp
-Bereitstellung), „Baseline“ (aus dersampleapp-baseline
-Bereitstellung) und „Canary“ (aus dersampleapp-canary
-Bereitstellung). Sie können ausschließlich die Baseline- und Canary-Metriken visualisieren, indem Sie einen weiteren Bereich mit der folgenden Konfiguration hinzufügen:- Wählen Sie auf der Registerkarte Allgemein unter Titel die Option Baseline und Canary für Beispiel-App aus.
- Geben Sie auf der Registerkarte Metriken die folgende Abfrage ein:
rate(requests_total{pod=~"sampleapp-baseline-.*|sampleapp-canary-.*", custom_status="good"}[1m])
Hinweis
Im Bereich für Baseline- und Canary-Metriken sind die Metriken nur unter bestimmten Bedingungen zum Vergleichen verfügbar. Diese Bedingungen liegen vor, wenn die Phase „Canary bereitstellen“ erfolgreich abgeschlossen wurde und die Canary-Phase „Höherstufen/Ablehnen“ auf einen manuellen Eingriff wartet.
Tipp
Richten Sie Anmerkungen für Grafana-Dashboards ein, um Phasenabschlussereignisse für Canary bereitstellen und Canary höherstufen/ablehnen visuell darzustellen. Dies ist hilfreich, damit Sie wissen, wann Sie mit dem Vergleich zwischen Baseline und Canary beginnen und wann das Höherstufen bzw. Ablehnen des Canarys abgeschlossen ist.
Vergleichen von Baseline und Canary
An diesem Punkt wurde die Phase Canary bereitstellen erfolgreich abgeschlossen (basierend auf der Änderung von
success_rate
von10
in20
). Die Phase Canary höherstufen/ablehnen wartet auf einen manuellen Eingriff. Sie können jetzt im Grafana-Dashboard die Erfolgsquote (gemäßcustom_status=good
) der Baseline- und Canary-Varianten vergleichen. Es sollte ungefähr wie folgt aussehen:Basierend auf der Beobachtung, dass die Erfolgsquote für Canary höher ist, stufen Sie den Canary höher. Wählen Sie in der Aufgabe für manuellen Eingriff Fortsetzen aus.