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

Artikel aus dieser Reihe:
- (dieser Artikel)
- Canary Deployment mit Istio
- Canary Deployment mit Jenkins-X Istio Flagger
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
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:v1wuestkamp/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:80Sie müssen einen Fork erstellen 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. .
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: LoadBalancerUnd 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: 100MiUnd 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: 100MiBeachten 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:

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

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: 100MiIn 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:

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:

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:

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
