Reibungslose Canary-Release mit APISIX Ingress Controller und Flagger
Hengliang Tan
January 19, 2023
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.
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
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.
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).
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.
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.