Reibungslose Canary-Release mit APISIX Ingress Controller und Flagger

Hengliang Tan

January 19, 2023

Ecosystem

Autor: Hengliang Tan, Engineering Manager bei XPENG

Im Prozess der Projektentwicklung sind Service-Updates oft eine Herausforderung. Um das beste Benutzererlebnis zu bieten, müssen wir das Risiko von Service-Unverfügbarkeit so weit wie möglich vermeiden. So wurde Continuous Delivery geboren, als eine Unternehmenssoftware-Praxis akzeptiert und als natürliche Weiterentwicklung der etablierten Continuous-Integration-Prinzipien. Dennoch ist Continuous Deployment aufgrund der Komplexität des Managements und der Angst, dass Bereitstellungsfehler die Systemverfügbarkeit beeinträchtigen könnten, immer noch sehr selten. Canary Release ist wahrscheinlich das klassischste Szenario im Continuous-Delivery-System. Basierend darauf können wir schnell ungesunde und problematische Dienste erkennen und mühelos auf die vorherige Version zurückrollen.

Canary Release

Canary Release wird auch als Graustufen-Release bezeichnet. Im Allgemeinen wird die neue Version der Anwendung als "Canary" veröffentlicht und bereitgestellt, um die Leistung zu testen. Die alte Version bleibt für den normalen Betrieb in derselben Phase erhalten. Während des Upgrades werden einige Benutzer auf die neue Version umgeleitet, während andere Benutzer weiterhin die alte Version verwenden. Unter der Voraussetzung, dass die Stabilität des Gesamtsystems gewährleistet ist, ermöglicht dies die frühzeitige Erkennung von Fehlern und eine rechtzeitige Anpassung.

Der Canary Release gibt das Update nicht direkt frei. Es leitet langsam einen bestimmten Prozentsatz des Datenverkehrs zu einer kleinen Anzahl von Benutzern. Wenn keine Fehler festgestellt werden, wird es für alle Benutzer freigegeben, und die alte Version wird schrittweise abgelöst. Diese Methode reduziert das Risiko, neue Funktionen in die Produktionsumgebung einzuführen.

Dieser Artikel wird vorstellen, wie man durch Apache APISIX Ingress und Flagger einen reibungslosen Canary Release erreichen, die Release-Effizienz verbessern und die Release-Risiken reduzieren kann.

Über Apache APISIX Ingress

Apache APISIX Ingress wird durch den Kubernetes Ingress Controller realisiert, der Apache APISIX als Datenebenen-Proxy verwendet. Es bietet Hunderte von Funktionen wie Lastenausgleich, dynamisches Upstream, Canary Release, fein abgestimmtes Routing, Ratenbegrenzung, Service-Degradation, Service-Circuit-Breaker, Authentifizierung und Beobachtbarkeit. Es wurde von in- und ausländischen Unternehmen und Organisationen übernommen, darunter Zoom, Tencent Cloud, Jiakaobaodian, Horizon Robotics, European Copernicus Reference System usw.

Über Flagger

Flagger ist ein CNCF-Projekt (Cloud Native Computing Foundation) und Teil der Flux-Familie von GitOps-Tools. Kürzlich hat die CNCF auch die offizielle Graduierung von Flux bekannt gegeben, was ein guter Indikator für den Erfolg und die vielversprechende Zukunft der Cloud-Native-Technologie ist. Als ein progressives Bereitstellungstool automatisiert Flagger den Release-Prozess für Anwendungen, die auf Kubernetes laufen. Es reduziert das Risiko, eine neue Softwareversion in der Produktion einzuführen, indem es den Datenverkehr schrittweise auf die neue Version umleitet, während es Analyse-Metriken misst und Konformitätstests durchführt.

Nach kontinuierlichen Bemühungen der Apache-APISIX- und Flux-Communities hat Flagger kürzlich v1.27.0 veröffentlicht, das automatisierte Canary Releases mit Apache APISIX Ingress und Flagger unterstützt.

featured-<Flagger und Apache APISIX Ingress>.jpg

Lassen Sie uns gemeinsam diesen reibungslosen Canary-Release-Prozess erleben.

Umgebung

Erfordert einen Kubernetes-Cluster der Version 1.19 oder neuer, den Sie über kind installieren können.

Komponenten installieren

Verwenden Sie Helm V3, um Apache APISIX und den Apache APISIX Ingress Controller zu installieren.

helm repo add apisix https://charts.apiseven.com kubectl create ns apisix helm upgrade -i apisix apisix/apisix --version=0.11.3 \ --namespace apisix \ --set apisix.podAnnotations."prometheus\.io/scrape"=true \ --set apisix.podAnnotations."prometheus\.io/port"=9091 \ --set apisix.podAnnotations."prometheus\.io/path"=/apisix/prometheus/metrics \ --set pluginAttrs.prometheus.export_addr.ip=0.0.0.0 \ --set pluginAttrs.prometheus.export_addr.port=9091 \ --set pluginAttrs.prometheus.export_uri=/apisix/prometheus/metrics \ --set pluginAttrs.prometheus.metric_prefix=apisix_ \ --set ingress-controller.enabled=true \ --set ingress-controller.config.apisix.serviceNamespace=apisix

Installieren Sie die Flagger- und Prometheus-Komponenten im apisix-Namespace.

helm repo add flagger https://flagger.app helm upgrade -i flagger flagger/flagger \ --namespace apisix \ --set prometheus.install=true \ --set meshProvider=apisix

Hinweis: Wenn Sie Prometheus oder den Prometheus-Operator anpassen müssen, können Sie nach verwandten Artikeln suchen, um Änderungen vorzunehmen.

Anwendungsinitialisierung

Flagger kann auf Kubernetes-Deployments und andere Workloads angewendet werden und kann auch mit HPA kombiniert werden. Es wird eine Reihe von Objekten erstellen: Kubernetes-Deployments, ClusterIP-Services und ApisixRoute. Diese Objekte können Anwendungen für Cluster-externe Dienste verfügbar machen und werden für die Analyse des Canary-Release-Prozesses verwendet.

Erstellen Sie einen neuen Test-Namespace:

kubectl create ns test

Erstellen Sie ein neues Deployment und HPA. Hier extrahieren wir den offiziellen Code-Beispiel von Flagger.

kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main

Stellen Sie den Lasttestdienst von Flagger bereit, um während des Canary-Releases Datenverkehr für die Analyse zu generieren.

helm upgrade -i flagger-loadtester flagger/loadtester \ --namespace=test

Erstellen Sie die ApisixRoute von Apache APISIX, und dann wird Flagger die erstellte Ressource referenzieren und die ApisixRoute von Apache APISIX Ingress in der Canary-Version generieren. (Ersetzen Sie app.example.com im folgenden Beispiel durch Ihren tatsächlichen Domainnamen)

apiVersion: apisix.apache.org/v2 kind: ApisixRoute metadata: name: podinfo namespace: test spec: http: - backends: - serviceName: podinfo servicePort: 80 match: hosts: - app.example.com methods: - GET paths: - /* name: method plugins: - name: prometheus enable: true config: disable: false prefer_name: true

Speichern Sie es als podinfo-apisixroute.yaml und übermitteln Sie es an den Cluster:

kubectl apply -f ./podinfo-apisixroute.yaml

Erstellen Sie eine Flagger-Custom-Resource Canary. (Ersetzen Sie app.example.com im Beispiel durch Ihren tatsächlichen Domainnamen)

apiVersion: flagger.app/v1beta1 kind: Canary metadata: name: podinfo namespace: test spec: provider: apisix targetRef: apiVersion: apps/v1 kind: Deployment name: podinfo # Referenzieren Sie die apisix route routeRef: apiVersion: apisix.apache.org/v2 kind: ApisixRoute name: podinfo progressDeadlineSeconds: 60 service: port: 80 targetPort: 9898 analysis: interval: 10s # Maximale Anzahl von Fehlern für den Rollback threshold: 10 # Maximaler Prozentsatz des Datenverkehrs zur Canary-Version # (0-100) maxWeight: 50 # Die Schrittgröße der Canary-Analyse # (0-100) stepWeight: 10 # Verwenden Sie Prometheus, um die Verkehrsinformationen von APISIX zu überprüfen metrics: - name: request-success-rate # Die minimale Erfolgsrate (keine 5xx-Antworten) # (0-100) thresholdRange: min: 99 interval: 1m - name: request-duration # P99 ist die größte Anforderungsverzögerung(ms) thresholdRange: max: 500 interval: 30s webhooks: # Automatisierter Datenverkehr für die Canary-Analyse, basierend auf dem tatsächlichen Szenario angepasst - name: load-test url: http://flagger-loadtester.test/ timeout: 5s type: rollout metadata: cmd: |- hey -z 1m -q 10 -c 2 -h2 -host app.example.com http://apisix-gateway.apisix/api/info

Speichern Sie es als podinfo-canary.yaml und übermitteln Sie es an den Cluster:

kubectl apply -f ./podinfo-canary.yaml

Flagger wird automatisch verwandte Ressourcen generieren:

# Übermittelt deployment.apps/podinfo horizontalpodautoscaler.autoscaling/podinfo apisixroute/podinfo canary.flagger.app/podinfo

# Automatisch generiert deployment.apps/podinfo-primary horizontalpodautoscaler.autoscaling/podinfo-primary service/podinfo service/podinfo-canary service/podinfo-primary apisixroute/podinfo-podinfo-canary

featured-<version 1>.jpg

An diesem Punkt können Sie die Anwendung über den Domainnamen app.example.com aufrufen (Ersetzen Sie app.example.com im Beispiel durch Ihren tatsächlichen Domainnamen), und Sie werden die aktuelle Version der Anwendung sehen.

Automatisierung des Canary-Releases

Flagger implementiert eine Kontrollschleife, die den Datenverkehr schrittweise auf Canary-Knoten umleitet, während wichtige Leistungsmetriken wie die HTTP-Anfrageerfolgsrate, die durchschnittliche Anforderungsdauer und die Pod-Gesundheit gemessen werden. Basierend auf der Analyse der relevanten Indikatoren wird die Freigabe oder das Stoppen der Canary-Bereitstellung durchgeführt und die Analyseergebnisse an relevante Plattformen wie Slack, MS Teams oder Prometheus Alert Manager usw. veröffentlicht.

Flagger Control Loop

Lösen Sie einen Canary-Release aus, indem Sie die Container-Image-Version aktualisieren.

kubectl -n test set image deployment/podinfo \ podinfod=stefanprodan/podinfo:6.0.1

Flagger erkennt, dass es eine neue Version des Deployments gibt, und wird einen Testlauf der Canary-Analysefreigabe starten.

kubectl -n test describe canary/podinfo Status: Canary Weight: 0 Conditions: Message: Canary analysis completed successfully, promotion finished. Reason: Succeeded Status: True Type: Promoted Failed Checks: 1 Iterations: 0 Phase: Succeeded Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning Synced 2m59s flagger podinfo-primary.test not ready: waiting for rollout to finish: observed deployment generation less than desired generation Warning Synced 2m50s flagger podinfo-primary.test not ready: waiting for rollout to finish: 0 of 1 (readyThreshold 100%) updated replicas are available Normal Synced 2m40s (x3 over 2m59s) flagger all the metrics providers are available! Normal Synced 2m39s flagger Initialization done! podinfo.test Normal Synced 2m20s flagger New revision detected! Scaling up podinfo.test Warning Synced 2m (x2 over 2m10s) flagger canary deployment podinfo.test not ready: waiting for rollout to finish: 0 of 1 (readyThreshold 100%) updated replicas are available Normal Synced 110s flagger Starting canary analysis for podinfo.test Normal Synced 109s flagger Advance podinfo.test canary weight 10 Warning Synced 100s flagger Halt advancement no values found for apisix metric request-success-rate probably podinfo.test is not receiving traffic: running query failed: no values found Normal Synced 90s flagger Advance podinfo.test canary weight 20 Normal Synced 80s flagger Advance podinfo.test canary weight 30 Normal Synced 69s flagger Advance podinfo.test canary weight 40 Normal Synced 59s flagger Advance podinfo.test canary weight 50 Warning Synced 30s (x2 over 40s) flagger podinfo-primary.test not ready: waiting for rollout to finish: 1 old replicas are pending termination Normal Synced 9s (x3 over 50s) flagger (combined from similar events): Promotion completed! Scaling down podinfo.test

Während des Canary-Release-Prozesses erhalten Sie unterschiedliche Antworten, wenn Sie die Anwendung über den Domainnamen app.example.com aufrufen (Ersetzen Sie app.example.com durch Ihren tatsächlichen Domainnamen).

featured-<version 2>.jpg

Durch das Anzeigen der ApisixRoute-Ressource podinfo-podinfo-canary von Apache APISIX, die automatisch von Flagger erstellt wurde, werden Sie feststellen, dass die Gewichtungen des Dienstes podinfo-primary und des Dienstes podinfo-canary sich mit dem Veröffentlichungsprozess ändern.

spec: http: - backends: - serviceName: podinfo-primary servicePort: 80 # Automatisch von Flagger angepasst weight: 80 - serviceName: podinfo-canary servicePort: 80 # Automatisch von Flagger angepasst weight: 20

Sie werden die neueste stabile Version sehen, wenn der endgültige Release abgeschlossen ist.

featured-<version 3>.jpg

Hinweis: Flagger wird die Canary-Analyse erneut ausführen, wenn Sie das Deployment während des Canary-Releases erneut ändern.

Sie können alle Canary-Releases mit diesem Befehl beobachten:

watch kubectl get canaries --all-namespaces NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME test podinfo-2 Progressing 10 2022-11-23T05:00:54Z test podinfo Succeeded 0 2022-11-23T06:00:54Z

Rollback

Während der Canary-Release-Analyse können Sie Flagger testen, um den Canary-Release zu unterbrechen und auf die alte Version zurückzurollen, indem Sie einen HTTP 500 Bad Request generieren.

Lösen Sie einen weiteren Canary-Release aus:

kubectl -n test set image deployment/podinfo \ podinfod=stefanprodan/podinfo:6.0.2

Geben Sie den Lasttest-Container ein.

kubectl -n test exec -it deploy/flagger-loadtester bash

Generieren Sie einen HTTP 500-Fehler:

hey -z 1m -c 5 -q 5 -host app.example.com http://apisix-gateway.apisix/status/500

Simulieren Sie eine Serververzögerung:

watch -n 1 curl -H \"host: app.example.com\" http://apisix-gateway.apisix/delay/1

Wenn die Anzahl der erkannten Fehler den Schwellenwert der Canary-Analyse erreicht, wird der Datenverkehr automatisch zurück zum Master-Knoten geleitet, der Canary-Knoten wird auf Null herunterskaliert, und der Canary-Release-Prozess wird als fehlgeschlagen markiert.

kubectl -n apisix logs deploy/flagger -f | jq .msg "New revision detected! Scaling up podinfo.test" "canary deployment podinfo.test not ready: waiting for rollout to finish: 0 of 1 (readyThreshold 100%) updated replicas are available" "Starting canary analysis for podinfo.test" "Advance podinfo.test canary weight 10" "Halt podinfo.test advancement success rate 0.00% < 99%" "Halt podinfo.test advancement success rate 26.76% < 99%" "Halt podinfo.test advancement success rate 34.19% < 99%" "Halt podinfo.test advancement success rate 37.32% < 99%" "Halt podinfo.test advancement success rate 39.04% < 99%" "Halt podinfo.test advancement success rate 40.13% < 99%" "Halt podinfo.test advancement success rate 48.28% < 99%" "Halt podinfo.test advancement success rate 50.35% < 99%" "Halt podinfo.test advancement success rate 56.92% < 99%" "Halt podinfo.test advancement success rate 67.70% < 99%" "Rolling back podinfo.test failed checks threshold reached 10" "Canary failed! Scaling down podinfo.test"

Anpassen von Metriken für die Canary-Analyse

Die Canary-Analyse kann durch das Abfragen von Prometheus-Metriken erweitert werden. Wir passen basierend auf den tatsächlichen Geschäftsszenarien an. Erstellen Sie eine Metrikvorlage und übermitteln Sie sie an den Cluster.

apiVersion: flagger.app/v1beta1 kind: MetricTemplate metadata: name: not-found-percentage namespace: test spec: provider: type: prometheus address: http://flagger-prometheus.apisix:9090 query: | sum( rate( apisix_http_status{ route=~"{{ namespace }}_{{ route }}-{{ target }}-canary_.+", code!~"4.." }[{{ interval }}] ) ) / sum( rate( apisix_http_status{ route=~"{{ namespace }}_{{ route }}-{{ target }}-canary_.+" }[{{ interval }}] ) ) * 100 # Ändern Sie die Analyse im Canary-Release und fügen Sie die oben erstellte Indikatorvorlage hinzu. analysis: metrics: - name: "404s percentage" templateRef: name: not-found-percentage thresholdRange: max: 5 interval: 1m

Die obige Konfiguration validiert den Canary, indem sie überprüft, ob die QPS (Queries per second) von HTTP 404-Anfragen höher als 5 % des gesamten Datenverkehrs ist. Der Canary-Rollout schlägt fehl, wenn die HTTP 404-Anfragen den 5 %-Schwellenwert überschreiten.

Zusammenfassung

Der obige Prozess kann mit weiteren benutzerdefinierten Metrikprüfungen, Webhooks, manuellen Genehmigungen und Benachrichtigungen über Slack oder MS Teams erweitert werden.

Ein sehr reibungsloser Canary-Release wird durch die Integration von Apache APISIX und Flagger erreicht, was die Release-Effizienz verbessert und die Release-Risiken reduziert. In Zukunft werden die beiden Communities enger zusammenarbeiten, um weitere Veröffentlichungsfunktionen wie Blue/Green Mirroring und A/B Testing zu realisieren.

Tags: