In diesem Dokument wird die Blau/Grün-Bereitstellung einer store-Beispielanwendung in zwei GKE-Clustern beschrieben. Blau/Grün-Deployments sind eine effektive Strategie, um Ihre Anwendungen mit minimalem Risiko zu neuen GKE-Clustern zu migrieren. Indem Sie den Traffic nach und nach vom aktuellen Cluster (blau) zum neuen Cluster (grün) verschieben, können Sie die neue Umgebung in der Produktion validieren, bevor Sie sich für eine vollständige Umstellung entscheiden.
In dieser Anleitung verwenden Sie eine store-Beispielanwendung, um ein reales Szenario zu simulieren, in dem ein Online-Shopping-Dienst von separaten Teams betrieben und über eine Flotte freigegebener GKE-Cluster bereitgestellt wird.
Hinweise
Multi-Cluster-Gateways erfordern eine gewisse Umgebungsvorbereitung, bevor sie bereitgestellt werden können. Bevor Sie fortfahren, führen Sie die Schritte unter Umgebung für Multi-Cluster-Gateways vorbereiten aus:
GKE-Cluster bereitstellen.
Registrieren Sie Ihre Cluster für eine Flotte, falls noch nicht geschehen.
Aktivieren Sie den Multi-Cluster-Service und die Multi-Cluster-Gateway-Controller.
Prüfen Sie dann vor der Verwendung in der Umgebung die Einschränkungen und bekannten Probleme des GKE Gateway-Controllers.
Blau/Grün-Multi-Cluster-Routing mit Gateway
Die GatewayClasses gke-l7-global-external-managed-*, gke-l7-regional-external-managed-* und gke-l7-rilb-* bieten viele erweiterte Funktionen für das Traffic-Routing, einschließlich Traffic-Aufteilung, Header-Abgleich, Header-Bearbeitung, Traffic-Spiegelung und mehr. In diesem Beispiel erfahren Sie, wie Sie mit der gewichteten Trafficaufteilung den Trafficanteil zweier GKE-Cluster explizit steuern.
In diesem Beispiel werden einige realistische Schritte beschrieben, die ein Dienstinhaber ausführen würde, um seine Anwendung in einen neuen GKE-Cluster zu verschieben oder zu erweitern. Das Ziel von Blau/Grün-Bereitstellungen ist es, das Risiko durch mehrere Validierungsschritte zu reduzieren, die bestätigen, dass der neue Cluster ordnungsgemäß funktioniert. In diesem Beispiel werden vier Phasen der Bereitstellung durchlaufen:
- 100%-Header-basierter Canary: Per HTTP-Header-Routing wird ausschließlich Test- oder synthetischer Traffic zum neuen Cluster gesendet.
- 100% – Traffic spiegeln: Der Nutzertraffic wird auf den Canary-Cluster gespiegelt. Damit wird die Kapazität des Canary-Clusters getestet, wozu 100 % des Nutzer-Traffics in diesen Cluster kopiert werden.
- 90% bis 10%: Eine Canary-Aufteilung des Traffic von 10 %, um den neuen Cluster langsam für echten Traffic verfügbar zu machen.
- 0% – 100%: Vollständige Umstellung auf den neuen Cluster mit der Option, zurückzugehen, falls Fehler auftreten.
Dieses Beispiel ähnelt dem vorherigen, mit dem Unterschied, dass stattdessen ein internes Multi-Cluster-Gateway bereitgestellt wird. Dadurch wird ein interner Application Load Balancer bereitgestellt, der nur innerhalb der VPC privat zugänglich ist. Sie verwenden die Cluster und dieselbe Anwendung, die Sie in den vorherigen Schritten bereitgestellt haben, mit Ausnahme der Bereitstellung über ein anderes Gateway.
Vorbereitung
Das folgende Beispiel baut auf einigen der Schritte unter Externes Multi-Cluster-Gateway bereitstellen auf. Führen Sie die folgenden Schritte aus, bevor Sie mit diesem Beispiel fortfahren:
-
In diesem Beispiel werden die Cluster
gke-west-1undgke-west-2verwendet, die Sie bereits eingerichtet haben. Diese Cluster befinden sich in derselben Region, da die GatewayClassgke-l7-rilb-mcregional ist und nur Cluster-Back-Ends in derselben Region unterstützt. Stellen Sie die für jeden Cluster erforderlichen Services und ServiceExports bereit. Wenn Sie Services und ServiceExports aus dem vorherigen Beispiel bereitgestellt haben, haben Sie einige davon bereits bereitgestellt.
kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store-west-1-service.yaml kubectl apply --context gke-west-2 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store-west-2-service.yamlIn jedem Cluster werden ähnliche Ressourcen bereitgestellt:
service/store created serviceexport.net.gke.io/store created service/store-west-2 created serviceexport.net.gke.io/store-west-2 created
Nur-Proxy-Subnetz konfigurieren
Konfigurieren Sie ein Nur-Proxy-Subnetz für jede Region, in der Sie interne Gateways bereitstellen, falls noch nicht geschehen. Dieses Subnetz wird verwendet, um auf den Load-Balancer-Proxys interne IP-Adressen bereitzustellen. Es muss mit einem --purpose konfiguriert werden, der auf nur REGIONAL_MANAGED_PROXY gesetzt ist.
Sie müssen ein Nur-Proxy-Subnetz erstellen, bevor Sie Gateways erstellen, die interne Application Load Balancer verwalten. Jede Region eines VPC-Netzwerks (Virtual Private Cloud), in dem Sie interne Application Load Balancer verwenden, muss ein Nur-Proxy-Subnetz haben.
Der Befehl gcloud compute networks subnets create wir mit einem Nur-Proxy-Subnetz erstellt.
gcloud compute networks subnets create SUBNET_NAME \
--purpose=REGIONAL_MANAGED_PROXY \
--role=ACTIVE \
--region=REGION \
--network=VPC_NETWORK_NAME \
--range=CIDR_RANGE
Dabei gilt:
SUBNET_NAME: die Region des Nur-Proxy-Subnetzes.REGIONist die Region des Nur-Proxy-Subnetzes.VPC_NETWORK_NAMEist der Name des VPC-Netzwerks, das das Subnetz enthält.CIDR_RANGE: der primäre IP-Adressbereich des Subnetzes. Die Subnetzmaske darf maximal/26groß sein, damit mindestens 64 IP-Adressen für Proxys in der Region verfügbar sind. Als Subnetzmaske wird/23empfohlen.
Gateway bereitstellen
Das folgende Gateway wird aus der GatewayClass gke-l7-rilb-mc erstellt. Dies ist ein regionales internes Gateway, das nur GKE-Cluster in derselben Region ansprechen kann.
Wenden Sie das folgende
Gateway-Manifest auf den Konfigurationsclustergke-west-1in diesem Beispiel an:cat << EOF | kubectl apply --context gke-west-1 -f - kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-http namespace: store spec: gatewayClassName: gke-l7-rilb-mc listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute EOFÜberprüfen Sie, ob das Gateway erfolgreich eingerichtet wurde. Mit diesem Befehl können Sie speziell nach Ereignissen in diesem Gateway filtern:
kubectl get events --field-selector involvedObject.kind=Gateway,involvedObject.name=internal-http --context=gke-west-1 --namespace storeDie Gateway-Bereitstellung war erfolgreich, wenn die Ausgabe in etwa so aussieht:
LAST SEEN TYPE REASON OBJECT MESSAGE 5m18s Normal ADD gateway/internal-http store/internal-http 3m44s Normal UPDATE gateway/internal-http store/internal-http 3m9s Normal SYNC gateway/internal-http SYNC on store/internal-http was a success
Header-basierter Canary-Test
Beim Header-basierten Canary-Test kann der Serviceinhaber synthetischen Testtraffic abgleichen, der nicht von echten Nutzern stammt. So lässt sich einfach prüfen, ob das grundlegende Netzwerk der Anwendung funktioniert, ohne dieses Nutzern direkt freizugeben.
Wenden Sie das folgende
HTTPRoute-Manifest auf den Konfigurationsclustergke-west-1in diesem Beispiel an:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: # Matches for env=canary and sends it to store-west-2 ServiceImport - matches: - headers: - name: env value: canary backendRefs: - group: net.gke.io kind: ServiceImport name: store-west-2 port: 8080 # All other traffic goes to store-west-1 ServiceImport - backendRefs: - group: net.gke.io kind: ServiceImport name: store-west-1 port: 8080 EOFNach der Bereitstellung konfiguriert diese HTTPRoute folgendes Routingverhalten:
- Interne Anfragen an
store.example.internalohne den HTTP-Headerenv: canarywerden anstore-Pods imgke-west-1-Cluster weitergeleitet - Interne Anfragen an
store.example.internalmit dem HTTP-Headerenv: canarywerden anstore-Pods imgke-west-2-Cluster weitergeleitet
Senden Sie Traffic an die Gateway-IP-Adresse, um zu prüfen, ob die HTTPRoute ordnungsgemäß funktioniert.
- Interne Anfragen an
Rufen Sie die interne IP-Adresse von
internal-httpab.kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace storeErsetzen Sie VIP in den folgenden Schritten durch die IP-Adresse, die Sie als Ausgabe erhalten.
Senden Sie mit dem HTTP-Header
env: canaryeine Anfrage an das Gateway. Dadurch wird bestätigt, dass der Traffic angke-west-2weitergeleitet wird. Verwenden Sie einen privaten Client in derselben VPC wie für den GKE-Cluster, um zu bestätigen, dass Anfragen korrekt weitergeleitet werden. Der folgende Befehl muss auf einem Computer ausgeführt werden, der privaten Zugriff auf die Gateway-IP-Adresse hat. Andernfalls funktioniert er nicht.curl -H "host: store.example.internal" -H "env: canary" http://VIPDie Ausgabe bestätigt, dass die Anfrage von einem Pod aus dem Cluster
gke-west-2bereitgestellt wurde:{ "cluster_name": "gke-west-2", "host_header": "store.example.internal", "node_name": "gke-gke-west-2-default-pool-4cde1f72-m82p.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-9kdb5", "pod_name_emoji": "😂", "project_id": "agmsb-k8s", "timestamp": "2021-05-31T01:21:55", "zone": "us-west1-a" }
Traffic-Spiegelung
In dieser Phase wird Traffic an den Ziel-Cluster gesendet, aber auch an den Canary-Cluster gespiegelt.
Die Spiegelung ist hilfreich, um festzustellen, wie sich die Trafficlast auf die Anwendungsleistung auswirkt, ohne dass sich dies auf Antworten an Ihre Clients auswirkt. Sie sind zwar nicht für alle Arten Rollouts erforderlich, können aber bei der Einführung großer Änderungen nützlich sein, die sich auf Leistung oder Last auswirken können.
Wenden Sie das folgende
HTTPRoute-Manifest auf den Konfigurationsclustergke-west-1in diesem Beispiel an:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: # Sends all traffic to store-west-1 ServiceImport - backendRefs: - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 # Also mirrors all traffic to store-west-2 ServiceImport filters: - type: RequestMirror requestMirror: backendRef: group: net.gke.io kind: ServiceImport name: store-west-2 port: 8080 EOFSenden Sie mit Ihrem privaten Client eine Anfrage an das
internal-http-Gateway. Verwenden Sie den Pfad/mirror, damit Sie diese Anfrage in einem späteren Schritt in den Anwendungslogs eindeutig identifizieren können.curl -H "host: store.example.internal" http://VIP/mirrorDie Ausgabe bestätigt, dass der Client eine Antwort von einem Pod im Cluster
gke-west-1erhalten hat:{ "cluster_name": "gke-west-1", "host_header": "store.example.internal", "node_name": "gke-gke-west-1-default-pool-65059399-ssfq.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-brg5w", "pod_name_emoji": "🎖", "project_id": "agmsb-k8s", "timestamp": "2021-05-31T01:24:51", "zone": "us-west1-a" }Damit ist bestätigt, dass der primäre Cluster auf Traffic reagiert. Sie müssen noch bestätigen, dass der Cluster, zu dem Sie migrieren, gespiegelten Traffic empfängt.
Prüfen Sie die Anwendungslogs eines
store-Pods im Clustergke-west-2. Die Logs sollten bestätigen, dass der Pod gespiegelten Traffic vom Load Balancer erhalten hat.kubectl logs deployment/store --context gke-west-2 -n store | grep /mirrorDiese Ausgabe bestätigt, dass Pods im Cluster
gke-west-2auch die gleichen Anfragen erhalten. Ihre Antworten auf diese Anfragen werden jedoch nicht an den Client zurückgesendet. Die in den Logs angezeigten IP-Adressen sind die internen IP-Adressen des Load Balancers, die mit Ihren Pods kommunizieren.Found 2 pods, using pod/store-5c65bdf74f-vpqbs [2023-10-12 21:05:20,805] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:20] "GET /mirror HTTP/1.1" 200 - [2023-10-12 21:05:27,158] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:27] "GET /mirror HTTP/1.1" 200 - [2023-10-12 21:05:27,805] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:27] "GET /mirror HTTP/1.1" 200 -
Trafficaufteilung
Die Traffic-Aufteilung ist eine der am häufigsten verwendeten Methoden für die Einführung von neuem Code oder die sichere Bereitstellung in neuen Umgebungen. Der Dienstinhaber legt einen expliziten Prozentsatz des Traffics fest, der an die Canary-Back-Ends gesendet wird. Dieser Prozentsatz ist in der Regel ein sehr kleiner Teil des Gesamt-Traffics, damit der Erfolg des Rollouts mit akzeptablem Risiko für echte Nutzeranfragen bestimmt werden kann.
Wenn Sie eine Trafficaufteilung mit einem kleinen Teil des Traffics vornehmen, kann der Serviceinhaber den Zustand der Anwendung und der Antworten prüfen. Sind alle Signale fehlerfrei, so können sie zur vollständigen Umstellung übergehen.
Wenden Sie das folgende
HTTPRoute-Manifest auf den Konfigurationsclustergke-west-1in diesem Beispiel an:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: - backendRefs: # 90% of traffic to store-west-1 ServiceImport - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 weight: 90 # 10% of traffic to store-west-2 ServiceImport - name: store-west-2 group: net.gke.io kind: ServiceImport port: 8080 weight: 10 EOFSenden Sie mit Ihrem privaten Client eine kontinuierliche curl-Anfrage an das
internal- http-Gateway.while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; doneDie Ausgabe sieht in etwa so aus, was darauf hinweist, dass eine 90/10-Trafficaufteilung erfolgt.
"cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-2", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", ...
Trafficumstellung
Die letzte Phase der Blau/Grün-Migration besteht darin, vollständig auf den neuen Cluster umzustellen und den alten Cluster zu entfernen. Wenn der Dienstinhaber einem vorhandenen Cluster tatsächlich einen zweiten Cluster hinzufügt, wäre dieser letzte Schritt anders, da zum Schluss Traffic an beide Cluster geht. In diesem Szenario wird ein einzelner store-ServiceImport empfohlen, der Pods aus den Clustern gke-west-1 und gke-west-2 enthält. So kann der Load-Balancer anhand von Nähe, Zustand und Kapazität entscheiden, wohin der Traffic für eine Aktiv-Aktiv-Anwendung geleitet werden soll.
Wenden Sie das folgende
HTTPRoute-Manifest auf den Konfigurationsclustergke-west-1in diesem Beispiel an:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: - backendRefs: # No traffic to the store-west-1 ServiceImport - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 weight: 0 # All traffic to the store-west-2 ServiceImport - name: store-west-2 group: net.gke.io kind: ServiceImport port: 8080 weight: 100 EOFSenden Sie mit Ihrem privaten Client eine kontinuierliche curl-Anfrage an das
internal- http-Gateway.while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; doneDie Ausgabe sieht in etwa so aus; der gesamte Traffic wird jetzt an
gke-west-2gesendet."cluster_name": "gke-west-2", "cluster_name": "gke-west-2", "cluster_name": "gke-west-2", "cluster_name": "gke-west-2", ...
Mit diesem letzten Schritt wird eine vollständige Blau/Grün-Anwendungsmigration von einem GKE-Cluster zu einem anderen GKE-Cluster abgeschlossen.
Bereinigen
Wenn Sie mit den Übungen in diesem Dokument fertig sind, entfernen Sie mit den folgenden Schritten die Ressourcen, damit Sie unerwünschte Kosten für Ihr Konto vermeiden:
Heben Sie die Registrierung der Cluster für die Flotte auf, wenn sie nicht für einen anderen Zweck registriert werden müssen.
Deaktivieren Sie die Funktion
multiclusterservicediscovery.gcloud container fleet multi-cluster-services disableDeaktivieren sie Multi-Cluster-Ingress:
gcloud container fleet ingress disableDeaktivieren Sie die APIs:
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
Fehlerbehebung
Kein gesunder Upstream
Symptom:
Das folgende Problem kann auftreten, wenn Sie ein Gateway erstellen, aber nicht auf die Backend-Dienste zugreifen können (Antwortcode 503):
no healthy upstream
Grund:
Diese Fehlermeldung gibt an, dass der Prüfer für die Systemdiagnose keine fehlerfreien Backend-Dienste finden kann. Möglicherweise sind Ihre Back-End-Dienste in Ordnung, aber Sie müssen die Systemdiagnosen möglicherweise anpassen.
Workaround:
Um dieses Problem zu beheben, passen Sie Ihre Systemdiagnose anhand der Anforderungen Ihrer Anwendung (z. B. /health) mithilfe einer HealthCheckPolicy an.