Canary Deployment in Kubernetes #1: Gitlab CI

Wir werden Gitlab CI und manuelles GitOps für die Implementierung und Nutzung von Canary-Deployments in Kubernetes verwenden.

Canary Deployment in Kubernetes #1: Gitlab CI

Artikel aus dieser Reihe:

Das Canary-Deployment führen wir manuell über GitOps und die Erstellung/Änderung der grundlegenden Kubernetes-Ressourcen durch. Dieser Artikel ist in erster Linie dazu gedacht, einen Einblick in die Funktionsweise von Canary Deployments in Kubernetes zu geben, da es effizientere Automatisierungsmethoden gibt, die wir in den kommenden Artikeln behandeln werden.


Canary Deployment in Kubernetes #1: Gitlab CI

https://www.norberteder.com/canary-deployment/

Canary Deployment

Bei der Canary-Strategie werden Aktualisierungen zunächst nur für einen Teil der Benutzer angewendet. Durch Monitoring, Log-Daten, manuelle Tests oder andere Feedback-Kanäle wird das Release vor seiner Anwendung für alle Benutzer getestet.

Kubernetes Deployment (rolling update)

Die Standardstrategie für Kubernetes Deployments ist das Rolling-Update, bei dem eine bestimmte Anzahl von Pods mit neuen Versionen der Images gestartet wird. Wenn diese ohne Probleme erstellt wurden, werden die Pods mit den alten Versionen der Images beendet, während parallel neue Pods erstellt werden.

GitOps

Wir verwenden GitOps in diesem Beispiel, da wir:

  • Git als einzige Quelle der Wahrheit nutzen
  • Git-Operationen für das Builden und Deployen verwenden (keine Befehle außer git tag/merge erforderlich sind)

Beispiel

Nehmen wir eine bewährte Praxis — einen Repository für Anwendungscode und einen für die Infrastruktur zu haben.

Anwendungs-Repository

Dies ist eine sehr einfache API in Python+Flask, die eine Antwort im JSON-Format zurückgibt. Wir werden das Paket über GitlabCI erstellen und das Ergebnis ins Gitlab-Registry pushen. In der Registry haben wir zwei verschiedene Versionen der Releases:

  • wuestkamp/k8s-deployment-example-app:v1
  • wuestkamp/k8s-deployment-example-app:v2

Der einzige Unterschied zwischen ihnen ist die Änderung der zurückgegebenen JSON-Datei. Wir verwenden diese Anwendung für eine maximal einfache Visualisierung, mit welcher Version wir kommunizieren.

Infrastruktur-Repository

In diesem Repository werden wir über GitlabCI in Kubernetes deployen. .gitlab-ci.yml folgendermaßen aus:

image: traherom/kustomize-docker

before_script:
   - printenv
   - kubectl version

stages:
 - deploy

deploy test:
   stage: deploy
   before_script:
     - echo $KUBECONFIG
   script:
     - kubectl get all
     - kubectl apply -f i/k8s

   only:
     - master

Um ihn selbst auszuführen, benötigen Sie einen Cluster, Gcloud kann verwendet werden:

gcloud container clusters create canary --num-nodes 3 --zone europe-west3-b

gcloud compute firewall-rules create incoming-80 --allow tcp:80

Sie müssen einen Fork erstellen https://gitlab.com/wuestkamp/k8s-deployment-example-canary-infrastructure und eine Variable KUBECONFIG in GitlabCI anlegen, die die Konfiguration für den Zugriff enthält kubectl auf Ihren Cluster.

Wie man die Anmeldeinformationen für den Cluster (Gcloud) erhält, kann hier nachgelesen werden. hier.

Infrastruktur-YAML

Im Infrastruktur-Repository haben wir einen Service:

apiVersion: v1
kind: Service
metadata:
 labels:
   id: app
 name: app
spec:
 ports:
 - port: 80
   protocol: TCP
   targetPort: 5000
 selector:
   id: app
 type: LoadBalancer

Und das Deployment in deploy.yaml:

apiVersion: apps\/v1
kind: Deployment
metadata:
 name: app
spec:
 replicas: 10
 selector:
   matchLabels:
     id: app
     type: main
 template:
   metadata:
     labels:
       id: app
       type: main
   spec:
     containers:
     - image: registry.gitlab.com\/wuestkamp\/k8s-deployment-example-app:v1
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

Und ein weiterer Deployment in deploy-canary.yaml:

kind: Deployment
metadata:
 name: app-canary
spec:
 replicas: 0
 selector:
   matchLabels:
     id: app
     type: canary
 template:
   metadata:
     labels:
       id: app
       type: canary
   spec:
     containers:
     - image: registry.gitlab.com\/wuestkamp\/k8s-deployment-example-app:v2
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

Beachten Sie, dass der app-deploy derzeit keine definierten Replikate hat.

Durchführung des initialen Deployments

Um den ursprünglichen Deployment zu starten, können Sie das GitlabCI-Pipeline manuell im Master-Branch starten. Danach kubectl sollte Folgendes ausgegeben werden:

Canary Deployment in Kubernetes #1: Gitlab CI

Wir sehen App einen Deployment mit 10 Replikaten und app-canary mit 0. Außerdem gibt es einen LoadBalancer, über den wir ansprechen können curl über die externe IP:

while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done

Canary Deployment in Kubernetes #1: Gitlab CI

Wir sehen, dass unsere Testanwendung nur “v1” zurückgibt.

Durchführung des Canary-Deployments

Schritt 1: Eine neue Version für einen Teil der Benutzer freigeben

Wir haben die Anzahl der Replikate in der Datei deploy-canary.yaml auf 1 gesetzt und das Image der neuen Version:

kind: Deployment
metadata:
 name: app-canary
spec:
 replicas: 1
 selector:
   matchLabels:
     id: app
     type: canary
 template:
   metadata:
     labels:
       id: app
       type: canary
   spec:
     containers:
     - image: registry.gitlab.com\/wuestkamp\/k8s-deployment-example-app:v2
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

In der Datei deploy.yaml wir haben die Anzahl der Replikate auf 9 geändert:

kind: Deployment
metadata:
 name: app
spec:
 replicas: 9
 selector:
   matchLabels:
     id: app
...

Wir pushen diese Änderungen in das Repository, aus dem das Deployment gestartet wird (durch GitlabCI) und sehen am Ende:

Canary Deployment in Kubernetes #1: Gitlab CI

Unser Service wird auf beide Deployments verweisen, da beide einen Selector app haben. Aufgrund der standardmäßigen Zufallsverteilung in Kubernetes sollten wir verschiedene Antworten auf ~ 10% der Anfragen sehen:

Canary Deployment in Kubernetes #1: Gitlab CI

Der aktuelle Zustand unserer Anwendung (GitOps, aus Git als Single Source Of Truth genommen) ist das Vorhandensein von zwei Deployments mit aktiven Replikaten, jeweils eines für jede Version.

~10% der Benutzer haben bereits Kontakt mit der neuen Version und testen sie unbeabsichtigt. Jetzt ist es an der Zeit, Protokolle und Überwachungsdaten auf Fehler zu prüfen, um Probleme zu identifizieren.

Schritt 2: Eine neue Version für alle Benutzer freigeben

Wir haben entschieden, dass alles gut gelaufen ist und jetzt müssen wir die neue Version für alle Benutzer bereitstellen. Dazu aktualisieren wir einfach deploy.yaml das Image auf die neue Version und setzen die Anzahl der Replikate auf 10. deploy-canary.yaml Wir setzen die Anzahl der Replikate auf 0. Nach dem Deployment wird das Ergebnis wie folgt aussehen:

Canary Deployment in Kubernetes #1: Gitlab CI

Zusammenfassend

Für mich hilft es, das Deployment manuell so zu starten, um zu verstehen, wie einfach es mit k8s eingerichtet werden kann. Da Kubernetes alles über die API aktualisiert, können diese Schritte über Skripte automatisiert werden.

Eine weitere Sache, die umgesetzt werden muss, ist der Einstiegspunkt für den Tester (LoadBalancer oder über Ingress), über den nur auf die neue Version zugegriffen werden kann. Dies kann für manuelle Überprüfungen verwendet werden.

In den folgenden Artikeln werden wir andere automatisierte Lösungen überprüfen, die die meisten der Dinge umsetzen, die wir gemacht haben.

Lesen Sie auch andere Artikel in unserem Blog:

Quelle: habr.com

60GB SSD 8Gb DDR4