Multi-Cluster-Gateway für gewichtete Trafficaufteilung bereitstellen

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.

Multi-Cluster-Gateways bieten eine leistungsstarke Möglichkeit, Traffic für Dienste zu verwalten, die in mehreren GKE-Clustern bereitgestellt werden. Mit der globalen Load-Balancing-Infrastruktur von Google können Sie einen einzigen Einstiegspunkt für Ihre Anwendungen erstellen, was die Verwaltung vereinfacht und die Zuverlässigkeit verbessert.

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:

  1. GKE-Cluster bereitstellen.

  2. Registrieren Sie Ihre Cluster für eine Flotte, falls noch nicht geschehen.

  3. 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:

  1. 100%-Header-basierter Canary: Per HTTP-Header-Routing wird ausschließlich Test- oder synthetischer Traffic zum neuen Cluster gesendet.
  2. 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.
  3. 90% bis 10%: Eine Canary-Aufteilung des Traffic von 10 %, um den neuen Cluster langsam für echten Traffic verfügbar zu machen.
  4. 0%100%: Vollständige Umstellung auf den neuen Cluster mit der Option, zurückzugehen, falls Fehler auftreten.

Blau/Grün-Aufteilung des Traffic auf zwei GKE-Cluster

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:

  1. Umgebung für Multi-Cluster-Gateways vorbereiten

  2. Demoanwendung bereitstellen

    In diesem Beispiel werden die Cluster gke-west-1 und gke-west-2 verwendet, die Sie bereits eingerichtet haben. Diese Cluster befinden sich in derselben Region, da die GatewayClass gke-l7-rilb-mc regional ist und nur Cluster-Back-Ends in derselben Region unterstützt.

  3. 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.yaml
    

    In 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.
  • REGION ist die Region des Nur-Proxy-Subnetzes.
  • VPC_NETWORK_NAME ist der Name des VPC-Netzwerks, das das Subnetz enthält.
  • CIDR_RANGE: der primäre IP-Adressbereich des Subnetzes. Die Subnetzmaske darf maximal /26 groß sein, damit mindestens 64 IP-Adressen für Proxys in der Region verfügbar sind. Als Subnetzmaske wird /23 empfohlen.

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.

  1. Wenden Sie das folgende Gateway-Manifest auf den Konfigurationscluster gke-west-1 in 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
    
  2. Ü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 store
    

    Die 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.

  1. Wenden Sie das folgende HTTPRoute-Manifest auf den Konfigurationscluster gke-west-1 in 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
    EOF
    

    Nach der Bereitstellung konfiguriert diese HTTPRoute folgendes Routingverhalten:

    • Interne Anfragen an store.example.internal ohne den HTTP-Header env: canary werden an store-Pods im gke-west-1-Cluster weitergeleitet
    • Interne Anfragen an store.example.internal mit dem HTTP-Header env: canary werden an store-Pods im gke-west-2-Cluster weitergeleitet

    HTTPRoute ermöglicht das Routing an verschiedene Cluster, je nach den HTTP-Headern

    Senden Sie Traffic an die Gateway-IP-Adresse, um zu prüfen, ob die HTTPRoute ordnungsgemäß funktioniert.

  2. Rufen Sie die interne IP-Adresse von internal-http ab.

    kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace store
    

    Ersetzen Sie VIP in den folgenden Schritten durch die IP-Adresse, die Sie als Ausgabe erhalten.

  3. Senden Sie mit dem HTTP-Header env: canary eine Anfrage an das Gateway. Dadurch wird bestätigt, dass der Traffic an gke-west-2 weitergeleitet 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://VIP
    

    Die Ausgabe bestätigt, dass die Anfrage von einem Pod aus dem Cluster gke-west-2 bereitgestellt 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.

  1. Wenden Sie das folgende HTTPRoute-Manifest auf den Konfigurationscluster gke-west-1 in 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
    EOF
    
  2. Senden 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/mirror
    
  3. Die Ausgabe bestätigt, dass der Client eine Antwort von einem Pod im Cluster gke-west-1 erhalten 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.

  4. Prüfen Sie die Anwendungslogs eines store-Pods im Cluster gke-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 /mirror
    
  5. Diese Ausgabe bestätigt, dass Pods im Cluster gke-west-2 auch 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.

  1. Wenden Sie das folgende HTTPRoute-Manifest auf den Konfigurationscluster gke-west-1 in 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
    EOF
    
  2. Senden 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; done
    

    Die 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.

  1. Wenden Sie das folgende HTTPRoute-Manifest auf den Konfigurationscluster gke-west-1 in 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
    EOF
    
  2. Senden 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; done
    

    Die Ausgabe sieht in etwa so aus; der gesamte Traffic wird jetzt an gke-west-2 gesendet.

    "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:

  1. Löschen Sie die Cluster.

  2. Heben Sie die Registrierung der Cluster für die Flotte auf, wenn sie nicht für einen anderen Zweck registriert werden müssen.

  3. Deaktivieren Sie die Funktion multiclusterservicediscovery.

    gcloud container fleet multi-cluster-services disable
    
  4. Deaktivieren sie Multi-Cluster-Ingress:

    gcloud container fleet ingress disable
    
  5. Deaktivieren 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.

Nächste Schritte