Automatisierte Canary-Deployments mit Flagger und Istio

Automatisierte Canary-Deployments mit Flagger und Istio

CD wird als Praxis für Unternehmenssoftware anerkannt und ist das Ergebnis einer natürlichen Evolution etablierter CI-Prinzipien. Dennoch ist CD nach wie vor ein eher seltenes Phänomen, möglicherweise aufgrund der Komplexität der Verwaltung und der Angst vor fehlgeschlagenen Deployments, die die Systemverfügbarkeit beeinträchtigen könnten.

Flagger ist ein Open-Source-Kubernetes-Operator, dessen Ziel es ist, komplexe Abhängigkeiten zu vermeiden. Er automatisiert die Förderung von Canary-Deployments durch den Einsatz von Istio-Traffic-Shifting und Prometheus-Metriken zur Analyse des Verhaltens der Anwendung während eines gesteuerten Rollouts.

Im Folgenden finden Sie eine schrittweise Anleitung zur Einrichtung und Nutzung von Flagger in Google Kubernetes Engine (GKE).

Kubernetes-Cluster einrichten

Sie beginnen mit der Erstellung eines GKE-Clusters mit Istio-Addons (falls Sie kein GCP-Konto haben, können Sie sich anmelden hier – um kostenlose Credits zu erhalten).

Melden Sie sich bei Google Cloud an, erstellen Sie ein Projekt und aktivieren Sie die Abrechnung dafür. Installieren Sie das Befehlszeilentool gcloud und richten Sie Ihr Projekt mit gcloud init.

Setzen Sie das Standardprojekt, die Rechenregion und die Zone (ersetzen Sie 1) Stellen Sie die folgenden Umgebungsvariablen ein. Ersetzen Sie durch Ihr Projekt):

gcloud config set project PROJECT_ID
gcloud config set compute/region us-central1
gcloud config set compute/zone us-central1-a

Aktivieren Sie den GKE-Dienst und erstellen Sie einen Cluster mit HPA und Istio-Addons:

gcloud services enable container.googleapis.com
K8S_VERSION=$(gcloud beta container get-server-config --format=json | jq -r '.validMasterVersions[0]')
gcloud beta container clusters create istio 
--cluster-version=${K8S_VERSION} 
--zone=us-central1-a 
--num-nodes=2 
--machine-type=n1-standard-2 
--disk-size=30 
--enable-autorepair 
--no-enable-cloud-logging 
--no-enable-cloud-monitoring 
--addons=HorizontalPodAutoscaling,Istio 
--istio-config=auth=MTLS_PERMISSIVE

Der obige Befehl erstellt einen Standardknotenpool, der zwei VMs umfasst n1-standard-2 (vCPU: 2, RAM 7,5 GB, Festplatte: 30 GB). Idealerweise sollten Sie die Istio-Komponenten von Ihren Workloads isolieren, aber es gibt keinen einfachen Weg, Istio-Pods in einem dedizierten Knotenpool zu starten. Die Istio-Manifeste gelten als schreibgeschützt und GKE wird Änderungen wie Knotenbindung oder loslösen von Pods zurücksetzen.

Richten Sie die Anmeldeinformationen für ein kubectl:

gcloud container clusters get-credentials istio

Erstellen Sie eine Cluster-Administratorrollenbindung:

kubectl create clusterrolebinding "cluster-admin-$(whoami)" 
--clusterrole=cluster-admin 
--user="$(gcloud config get-value core/account)"

Installieren Sie das Befehlszeilenwerkzeug Helm:

brew install kubernetes-helm

Homebrew 2.0 ist jetzt auch für Linux.

Erstellen Sie ein Dienstkonto und eine Rollenbindung für Tiller:

kubectl -n kube-system create sa tiller && 
kubectl create clusterrolebinding tiller-cluster-rule 
--clusterrole=cluster-admin 
--serviceaccount=kube-system:tiller

Setzen Sie Tiller im Namespace ein kube-system:

helm init --service-account tiller

Sie sollten in Erwägung ziehen, SSL zwischen Helm und Tiller zu verwenden. Weitere Informationen zum Schutz der Helm-Installation finden Sie unter docs.helm.sh

Bestätigen Sie die Einstellungen:

kubectl -n istio-system get svc

Nach ein paar Sekunden sollte GCP eine externe IP-Adresse für den Dienst zuweisen istio-ingressgateway.

Konfigurieren Sie das Istio-Eingangstor

Erstellen Sie eine statische IP-Adresse mit dem Namen istio-gateway, indem Sie die IP-Adresse des Istio-Gateways verwenden:

export GATEWAY_IP=$(kubectl -n istio-system get svc/istio-ingressgateway -ojson | jq -r .status.loadBalancer.ingress[0].ip)
gcloud compute addresses create istio-gateway --addresses ${GATEWAY_IP} --region us-central1

Jetzt benötigen Sie eine Internet-Domain und Zugriff auf Ihren DNS-Registrar. Fügen Sie zwei A-Einträge hinzu (ersetzen Sie example.com mit Ihrer Domain):

istio.example.com   A ${GATEWAY_IP}
*.istio.example.com A ${GATEWAY_IP}

Stellen Sie sicher, dass das Wildcard-DNS funktioniert:

watch host test.istio.example.com

Erstellen Sie ein allgemeines Istio-Gateway, um Dienste außerhalb des Service-Mesh über HTTP bereitzustellen:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: public-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - "*"

Speichern Sie die obige Ressource als public-gateway.yaml und wenden Sie sie dann an:

kubectl apply -f ./public-gateway.yaml

Keine Produktionssysteme sollten Dienste über das Internet ohne SSL bereitstellen. Um das Istio-Eingangstor mit cert-manager, CloudDNS und Let's Encrypt zu schützen, lesen Sie bitte Dokumentation Flagger GKE.

Installation von Flagger

Die GKE Istio-Installation umfasst keine Prometheus-Instanz, die sich um die Bereinigung des Istio-Telemetriedienstes kümmert. Da Flagger die Istio-HTTP-Metriken für die Canaries-Analyse verwendet, müssen Sie die folgende Prometheus-Konfiguration bereitstellen, die ähnlich der in der offiziellen Istio-Helm-Vorlage ist.

REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master
kubectl apply -f ${REPO}/artifacts/gke/istio-prometheus.yaml

Fügen Sie das Flagger-Helm-Repository hinzu:

helm repo add flagger [https://flagger.app](https://flagger.app/)

Setzen Sie Flagger im Namespace ein istio-system, einschließlich Slack-Benachrichtigungen:

helm upgrade -i flagger flagger/flagger 
--namespace=istio-system 
--set metricsServer=http://prometheus.istio-system:9090 
--set slack.url=https://hooks.slack.com/services/YOUR-WEBHOOK-ID 
--set slack.channel=general 
--set slack.user=flagger

Sie können Flagger in jedem Namespace installieren, wenn er über Port 9090 mit dem Istio-Prometheus-Dienst kommunizieren kann.

Flagger hat ein Grafana-Dashboard für die Canary-Analyse. Installieren Sie Grafana im Namespace istio-system:

helm upgrade -i flagger-grafana flagger/grafana 
--namespace=istio-system 
--set url=http://prometheus.istio-system:9090 
--set user=admin 
--set password=change-me

Ziehen Sie Grafana durch das öffentliche Gateway auf, indem Sie einen virtuellen Dienst erstellen (ersetzen Sie example.com durch Ihre Domain):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: grafana
  namespace: istio-system
spec:
  hosts:
    - "grafana.istio.example.com"
  gateways:
    - public-gateway.istio-system.svc.cluster.local
  http:
    - route:
        - destination:
            host: flagger-grafana

Speichern Sie die oben genannte Ressource als grafana-virtual-service.yaml und wenden Sie sie dann an:

kubectl apply -f ./grafana-virtual-service.yaml

Wenn Sie zu http://grafana.istio.example.com in Ihrem Browser navigieren, sollten Sie zur Anmeldeseite von Grafana geleitet werden.

Bereitstellung von Webanwendungen mit Flagger

Flagger wird in Kubernetes bereitgestellt und erstellt bei Bedarf auch eine horizontale automatische Skalierung (HPA) und dann eine Reihe von Objekten (Kubernetes Deployments, ClusterIP-Dienste und Istio virtuelle Dienste). Diese Objekte stellen die Anwendung im Service-Mesh bereit und verwalten die Canary-Analyse und -Beförderung.

Automatisierte Canary-Deployments mit Flagger und Istio

Erstellen Sie einen Test-Namespace mit aktivierter Istio Sidecar-Integration:

REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master
kubectl apply -f ${REPO}/artifacts/namespaces/test.yaml

Erstellen Sie ein Deployment und ein Tool zur automatischen horizontalen Skalierung des Pods:

kubectl apply -f ${REPO}/artifacts/canaries/deployment.yaml
kubectl apply -f ${REPO}/artifacts/canaries/hpa.yaml

Bereitstellung eines Testlastdienstes zur Generierung von Datenverkehr während der Canary-Analyse:

helm upgrade -i flagger-loadtester flagger/loadtester 
--namepace=test

Erstellen Sie eine benutzerdefinierte Canary-Ressource (ersetzen Sie example.com mit Ihrer Domain):

apiVersion: flagger.app/v1alpha3
kind: Canary
metadata:
  name: podinfo
  namespace: test
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  progressDeadlineSeconds: 60
  autoscalerRef:
    apiVersion: autoscaling/v2beta1
    kind: HorizontalPodAutoscaler
    name: podinfo
  service:
    port: 9898
    gateways:
    - public-gateway.istio-system.svc.cluster.local
    hosts:
    - app.istio.example.com
  canaryAnalysis:
    interval: 30s
    threshold: 10
    maxWeight: 50
    stepWeight: 5
    metrics:
    - name: istio_requests_total
      threshold: 99
      interval: 30s
    - name: istio_request_duration_seconds_bucket
      threshold: 500
      interval: 30s
    webhooks:
      - name: load-test
        url: http://flagger-loadtester.test/
        timeout: 5s
        metadata:
          cmd: "hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"

Speichern Sie die oben genannte Ressource als podinfo-canary.yaml und wenden Sie sie dann an:

kubectl apply -f ./podinfo-canary.yaml

Die obige Analyse wird im Falle eines Erfolgs fünf Minuten lang durchgeführt, wobei alle 30 Sekunden HTTP-Metriken überprüft werden. Sie können die minimale Zeit, die für die Prüfung und Beförderung des Canary-Deployments erforderlich ist, mit der folgenden Formel bestimmen: interval * (maxWeight / stepWeight). Die Felder der Canary-CRD sind dokumentiert hier.

Nach ein paar Sekunden wird Flagger die Canary-Objekte erstellen:

# applied 
deployment.apps/podinfo
horizontalpodautoscaler.autoscaling/podinfo
canary.flagger.app/podinfo
# generated 
deployment.apps/podinfo-primary
horizontalpodautoscaler.autoscaling/podinfo-primary
service/podinfo
service/podinfo-canary
service/podinfo-primary
virtualservice.networking.istio.io/podinfo

Öffnen Sie den Browser und gehen Sie zu app.istio.example.com, Sie sollten die Versionsnummer sehen der Demo-Anwendung.

Automatische Canary-Analyse und -Promotion

Flagger implementiert einen Managementzyklus, der schrittweise den Traffic auf die Canary-Version verschiebt und gleichzeitig wichtige Leistungskennzahlen misst, wie z. B. die Erfolgsquote von HTTP-Anfragen, die durchschnittliche Anfragedauer und die Betriebsbereitschaft des Pods. Basierend auf der Analyse der KPIs wird die Canary-Version befördert oder abgebrochen, und die Analyseergebnisse werden in Slack veröffentlicht.

Automatisierte Canary-Deployments mit Flagger und Istio

Der Canary-Deployment wird initiiert, wenn sich eines der folgenden Objekte ändert:

  • Deployment PodSpec (Container-Image, Befehl, Ports, Umgebungsvariablen usw.)
  • ConfigMaps werden als Volumes gemountet oder in Umgebungsvariablen umgewandelt
  • Secrets werden als Volumes gemountet oder in Umgebungsvariablen umgewandelt

Start des Canary-Deployments bei Aktualisierung des Container-Images:

kubectl -n test set image deployment/podinfo 
podinfod=quay.io/stefanprodan/podinfo:1.4.1

Flagger stellt fest, dass sich die Version des Deployments geändert hat, und beginnt mit der Analyse:

kubectl -n test describe canary/podinfo

Ereignisse:

Neue Revision erkannt podinfo.test
Hochskalieren von podinfo.test
Warten auf den Abschluss des Rollouts von podinfo.test: 0 von 1 aktualisierten Replicas verfügbar
Erhöhung des Canary-Gewichts von podinfo.test auf 5
Erhöhung des Canary-Gewichts von podinfo.test auf 10
Erhöhung des Canary-Gewichts von podinfo.test auf 15
Erhöhung des Canary-Gewichts von podinfo.test auf 20
Erhöhung des Canary-Gewichts von podinfo.test auf 25
Erhöhung des Canary-Gewichts von podinfo.test auf 30
Erhöhung des Canary-Gewichts von podinfo.test auf 35
Erhöhung des Canary-Gewichts von podinfo.test auf 40
Erhöhung des Canary-Gewichts von podinfo.test auf 45
Erhöhung des Canary-Gewichts von podinfo.test auf 50
Kopieren der PodSpec-Vorlage von podinfo.test zu podinfo-primary.test
Warten auf den Abschluss des Rollouts von podinfo-primary.test: 1 von 2 aktualisierten Replicas verfügbar
Beförderung abgeschlossen! Herunterskalieren von podinfo.test

Während der Analyse können die Canary-Ergebnisse mit Grafana verfolgt werden:

Automatisierte Canary-Deployments mit Flagger und Istio

Hinweis: Wenn neue Änderungen während der Canary-Analyse auf das Deployment angewendet werden, wird Flagger die Analysephase neu starten.

Erstellen Sie eine Liste aller "Canarys" in Ihrem Cluster:

watch kubectl get canaries --all-namespaces
NAMESPACE   NAME      STATUS        WEIGHT   LASTTRANSITIONTIME
test        podinfo   Progressing   15       2019-01-16T14:05:07Z
prod        frontend  Succeeded     0        2019-01-15T16:15:07Z
prod        backend   Failed        0        2019-01-14T17:05:07Z

Wenn Sie Slack-Benachrichtigungen aktiviert haben, erhalten Sie die folgenden Nachrichten:

Automatisierte Canary-Deployments mit Flagger und Istio

Automatischer Rollback

Während der Canary-Analyse können synthetische HTTP 500-Fehler und hohe Antwortzeiten generiert werden, um zu überprüfen, ob Flagger das Deployment stoppt.

Erstellen Sie einen Test-Pod und führen Sie Folgendes aus:

kubectl -n test run tester 
--image=quay.io/stefanprodan/podinfo:1.2.1 
-- ./podinfo --port=9898
kubectl -n test exec -it tester-xx-xx sh

Fehler HTTP 500 generieren:

watch curl http://podinfo-canary:9898/status/500

Verzögerung generieren:

beobachten curl http://podinfo-canary:9898/delay/1

Wenn die Anzahl der fehlgeschlagenen Prüfungen den Schwellenwert erreicht, wird der Datenverkehr zurück zum primären Kanal geleitet, das Canary wird auf null skaliert und das Deployment wird als fehlgeschlagen markiert.

Fehler bei der Canary-Überprüfung und Spitzenzeiten werden als Kubernetes-Ereignisse registriert und von Flagger im JSON-Format protokolliert:

kubectl -n istio-system logs deployment/flagger -f | jq .msg

Starten des Canary-Deployments für podinfo.test
Canary-Gewicht von podinfo.test erhöhen auf 5
Canary-Gewicht von podinfo.test erhöhen auf 10
Canary-Gewicht von podinfo.test erhöhen auf 15
Halt podinfo.test Fortschrittsquote 69.17% < 99%
Halt podinfo.test Fortschrittsquote 61.39% < 99%
Halt podinfo.test Fortschrittsquote 55.06% < 99%
Halt podinfo.test Fortschrittsquote 47.00% < 99%
Halt podinfo.test Fortschrittsquote 37.00%  500ms
Halt podinfo.test Anforderungsdauer 1.600s > 500ms
Halt podinfo.test Anforderungsdauer 1.915s > 500ms
Halt podinfo.test Anforderungsdauer 2.050s > 500ms
Halt podinfo.test Anforderungsdauer 2.515s > 500ms
Rollback von podinfo.test, Schwellenwert für fehlgeschlagene Prüfungen erreicht 10
Canary fehlgeschlagen! Skalierung von podinfo.test verringern

Wenn Sie Slack-Benachrichtigungen aktiviert haben, erhalten Sie eine Nachricht, wenn die Ausführungsfrist überschritten wird oder die maximale Anzahl von fehlgeschlagenen Prüfungen während der Analyse erreicht wird:

Automatisierte Canary-Deployments mit Flagger und Istio

Abschließend

Das Starten eines Service Mesh, z. B. Istio, zusätzlich zu Kubernetes, bietet automatisierte Metriken, Protokolle und Logs, aber das Deployment von Workloads hängt weiterhin von externen Tools ab. Flagger strebt danach, dies zu ändern, indem es Istio-Funktionen hinzufügt für progressive Bereitstellung.

Flagger ist mit allen CI/CD-Lösungen für Kubernetes kompatibel, und die Canary-Analyse kann leicht mit Webhooks erweitert werden, um Integrationstests, Akzeptanztests, Lasttests oder andere benutzerdefinierte Überprüfungen durchzuführen. Da Flagger deklarativ und reaktiv auf Kubernetes-Ereignisse ist, kann es in GitOps-Pipelines mit Weave Flux oder JenkinsXverwendet werden. Wenn Sie JenkinsX verwenden, können Sie Flagger mit jx-Add-ons installieren.

Flagger wird unterstützt von Weaveworks und ermöglicht Canary-Deployments in Weave Cloud. Das Projekt wird auf GKE, EKS und „bare metal“ mit kubeadm getestet.

Wenn Sie Verbesserungsvorschläge für Flagger haben, senden Sie bitte eine Anfrage oder einen PR auf GitHub unter stefanprodan/flagger. Beiträge sind mehr als willkommen!

Danke Ray Tsan.

Quelle: habr.com

60GB SSD 8Gb DDR4