Multi-Cluster-Gateways bereitstellen


Auf dieser Seite wird beschrieben, wie Sie Kubernetes-Gateway-Ressourcen bereitstellen, um Load Balancing auf eingehenden Traffic über mehrere GKE-Cluster (oder Flotten) von Google Kubernetes Engine hinweg anzuwenden. Lesen Sie die Informationen zum Vorbereiten Ihrer Umgebung unter Multi-Cluster-Gateways aktivieren, bevor Sie Multi-Cluster-Gateways bereitstellen.

Informationen zum Bereitstellen von Gateways für das Load Balancing von eingehendem Traffic auf nur einen GKE-Cluster finden Sie unter Gateways bereitstellen.

Multi-Cluster-Gateways

Ein Multi-Cluster-Gateway ist eine Gateway-Ressource, bei der der Traffic auf mehrere Kubernetes-Cluster verteilt wird. In GKE stellen die GatewayClasses gke-l7-global-external-managed-mc, gke-l7-regional-external-managed-mc, gke-l7-rilb-mc und gke-l7-gxlb-mc Multi-Cluster-Gateways bereit, die HTTP-Routing, Trafficaufteilung, Trafficspiegelung, Systemdiagnose-Failover und mehr über verschiedene GKE-Cluster, Kubernetes Namespaces und verschiedene Regionen hinweg bieten. Multi-Cluster-Gateways machen die Verwaltung von Anwendungsnetzwerken über viele Cluster und Teams hinweg für Infrastrukturadministratoren einfach, sicher und skalierbar.

Ein Multi-Cluster-Gateway ist eine Gateway-Ressource, bei der der Traffic auf mehrere Kubernetes-Cluster verteilt wird.

Auf dieser Seite werden drei Beispiele vorgestellt, die zeigen, wie Sie Multi-Cluster-Gateways mit dem GKE-Gateway-Controller bereitstellen:

  • Beispiel 1: Ein externes Multi-Cluster-Gateway, das Load Balancing auf zwei GKE-Clustern für den Internet-Traffic anwendet.
  • Beispiel 2: Blau-grüne, gewichtete Trafficaufteilung und Trafficspiegelung für zwei GKE-Cluster für internen VPC-Traffic.
  • Beispiel 3: Ein kapazitätsbasiertes Gateway zum Load Balancing von Anfragen an verschiedene Back-Ends basierend auf ihrer maximalen Kapazität.

Beide Beispiele nutzen dieselben Speicher- und Website-Anwendungen, um ein reales Szenario zu modellieren, in dem ein Online-Shopping-Dienst und ein Website-Dienst von separaten Teams betrieben und über eine Flotte freigegebener GKE-Cluster bereitgestellt werden. Die Beispiele heben verschiedene Topologien und Anwendungsfälle hervor, die Multi-Cluster-Gateways nutzen.

Multi-Cluster-Gateways erfordern eine gewisse Umgebungsvorbereitung, bevor sie bereitgestellt werden können. Bevor Sie fortfahren, führen Sie die Schritte unter Multi-Cluster-Gateways aktivieren aus:

  1. GKE-Cluster bereitstellen.

  2. Registrieren Sie Ihre Cluster bei einer Flotte.

  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.

Externes Multi-Cluster-/Multi-Region-Gateway

In dieser Anleitung erstellen Sie ein externes Multi-Cluster-Gateway, das externen Traffic für eine Anwendung bereitstellt, die in zwei GKE-Clustern ausgeführt wird.

store.example.com wird in zwei GKE-Clustern bereitgestellt und über ein Multi-Cluster-Gateway im Internet freigegeben.

In den nächsten Schritten führen Sie die folgenden Aufgaben aus:

  1. Stellen Sie die store-Beispielanwendung in den Clustern gke-west-1 und gke-east-1 bereit.
  2. Konfigurieren Sie Dienste auf jedem Cluster, der in Ihre Flotte exportiert werden soll (Multi-Cluster-Dienste).
  3. Stellen Sie ein externes Multi-Cluster-Gateway und eine HTTP-Route in Ihrem Konfigurationscluster (gke-west-1) bereit.

Nachdem die Anwendungs- und Gateway-Ressourcen bereitgestellt wurden, können Sie den Traffic zwischen den beiden GKE-Clustern über pfadbasierte Routings steuern:

  • Anfragen an /west werden an store-Pods im gke-west-1-Cluster weitergeleitet.
  • Anfragen an /east werden an store-Pods im gke-east-1-Cluster weitergeleitet.
  • Anfragen an jeden anderen Pfad werden abhängig von ihrem Zustand, ihrer Kapazität und der Nähe zum anfragenden Client an einen der Cluster weitergeleitet.

Demoanwendung bereitstellen

  1. Erstellen Sie das store-Deployment und den Namespace in allen drei Clustern, die unter Multi-Cluster-Gateways aktivieren bereitgestellt wurden:

    kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.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.yaml
    kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml
    

    In jedem Cluster werden folgende Ressourcen bereitgestellt:

    namespace/store created
    deployment.apps/store created
    

    Für alle Beispiele auf dieser Seite wird die in diesem Schritt bereitgestellte Anwendung verwendet. Prüfen Sie, ob die Anwendung in allen drei Clustern bereitgestellt wird, bevor Sie einen der verbleibenden Schritte ausführen. In diesem Beispiel werden nur die Cluster gke-west-1 und gke-east-1 verwendet. In einem anderen Beispiel wird gke-west-2 verwendet.

Multi-Cluster-Dienste

Services werden wie Pods für Clients verfügbar gemacht. Da der GKE-Gateway-Controller containernatives Load Balancing verwendet, wird nicht das ClusterIP- oder Kubernetes-Load-Balancing verwendet, um Pods zu erreichen. Der Traffic wird direkt vom Load Balancer an die Pod-IP-Adressen gesendet. Services spielen jedoch weiterhin eine wichtige Rolle als logische Kennzeichnung für die Pod-Gruppierung.

Multi-Cluster-Service (MCS) ist ein API-Standard für Services, die Cluster umfassen. Der zugehörige GKE-Controller stellt Service Discovery in GKE-Clustern bereit. Der Multi-Cluster-Gateway-Controller verwendet MCS-API-Ressourcen, um Pods in einem Service zu gruppieren, der über mehrere Cluster adressierbar ist oder sich über mehrere Cluster erstreckt.

Die Multi-Cluster Services API definiert folgende benutzerdefinierte Ressourcen:

  • ServiceExports werden einem Kubernetes-Dienst zugeordnet und exportieren die Endpunkte dieses Dienstes auf alle Cluster, die für die Flotte registriert sind. Wenn ein Service einen entsprechenden ServiceExport hat, kann er von einem Multi-Cluster-Gateway adressiert werden.
  • ServiceImports werden vom Multi-Cluster-Service-Controller automatisch generiert. ServiceExport und ServiceImport sind paarweise verfügbar. Wenn ein ServiceExport in der Flotte vorhanden ist, wird ein entsprechender ServiceImport erstellt, damit der Service, der dem ServiceExport zugeordnet ist, über alle Cluster zugänglich ist.

Der Export von Services funktioniert auf folgende Weise. In gke-west-1 befindet sich ein Speicher-Service, der eine Gruppe von Pods in diesem Cluster auswählt. Im Cluster wird ein ServiceExport erstellt, durch den die Pods in gke-west-1 von den anderen Clustern in der Flotte zugänglich sind. Der ServiceExport wird Services zugeordnet, die denselben Namen und Namespace wie die ServiceExport-Ressource haben, und macht sie verfügbar.

apiVersion: v1
kind: Service
metadata:
  name: store
  namespace: store
spec:
  selector:
    app: store
  ports:
  - port: 8080
    targetPort: 8080
---
kind: ServiceExport
apiVersion: net.gke.io/v1
metadata:
  name: store
  namespace: store

Das folgende Diagramm zeigt, was nach der Bereitstellung eines ServiceExport geschieht. Wenn ein ServiceExport/Service-Paar vorhanden ist, stellt der Multi-Cluster-Service-Controller einen entsprechenden ServiceImport in jedem GKE-Cluster in der Flotte bereit. Der ServiceImport ist die lokale Darstellung des store-Service in jedem Cluster. Dadurch kann der client-Pod in gke-east-1 ClusterIP- oder monitorlose Services verwenden, um die store-Pods in gke-west-1 zu erreichen. Bei dieser Verwendungsart bieten Multi-Cluster-Services ein Ost-West-Load-Balancing zwischen Clustern, ohne einen internen LoadBalancer-Service zu erfordern. Informationen zum Verwenden von Multi-Cluster-Services für Cluster-zu-Cluster-Load-Balancing finden Sie unter Multi-Cluster-Services konfigurieren.

Multi-Cluster-Services exportieren Services über Cluster, wodurch die Cluster-zu-Cluster-Kommunikation ermöglicht wird

Multi-Cluster-Gateways verwenden auch ServiceImports, jedoch nicht für das Cluster-zu-Cluster-Load-Balancing. Stattdessen verwenden Gateways ServiceImports als logische Kennzeichnungen für einen Service, der in einem anderen Cluster vorhanden ist oder sich über mehrere Cluster erstreckt. Die folgende HTTPRoute verweist auf eine ServiceImport-Ressource statt auf eine Service-Ressource. Durch Verweisen auf einen ServiceImport wird angegeben, dass der Traffic an eine Gruppe von Backend-Pods weitergeleitet wird, die in einem oder mehreren Clustern ausgeführt werden.

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
  name: store-route
  namespace: store
  labels:
    gateway: multi-cluster-gateway
spec:
  parentRefs:
  - kind: Gateway
    namespace: store
    name: external-http
  hostnames:
  - "store.example.com"
  rules:
  - backendRefs:
    - group: net.gke.io
      kind: ServiceImport
      name: store
      port: 8080

Das folgende Diagramm zeigt, wie die HTTPRoute store.example.com-Traffic zu store-Pods in gke-west-1 und gke-east-1 weiterleitet. Der Load-Balancer behandelt sie als einen einzigen Pool von Back-Ends. Wenn die Pods aus einem der Cluster fehlerhaft werden, nicht mehr erreichbar sind oder keine Traffic-Kapazität haben, wird die Traffic-Last auf die verbleibenden Pods im anderen Cluster verteilt. Neue Cluster können mit dem store-Service und -ServiceExport hinzugefügt oder entfernt werden. Dadurch werden Backend-Pods transparent ohne explizite Routingkonfigurationsänderungen hinzugefügt oder entfernt.

MCS-Ressource

Services exportieren

An diesem Punkt wird die Anwendung in beiden Clustern ausgeführt. Als Nächstes machen Sie die Anwendungen verfügbar und exportieren sie, wozu Sie Services und ServiceExports in jedem Cluster bereitstellen.

  1. Wenden Sie das folgende Manifest auf den Cluster gke-west-1 an, um die Services und ServiceExports store und store-west-1 zu erstellen.

    cat << EOF | kubectl apply --context gke-west-1 -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store
      namespace: store
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store-west-1
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store-west-1
      namespace: store
    EOF
    
  2. Wenden Sie das folgende Manifest auf den Cluster gke-east-1 an, um die Services und ServiceExports store und store-east-1 zu erstellen.

    cat << EOF | kubectl apply --context gke-east-1 -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store
      namespace: store
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store-east-1
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store-east-1
      namespace: store
    EOF
    
  3. Prüfen Sie, ob im Cluster die richtigen ServiceExports erstellt wurden.

    kubectl get serviceexports --context CLUSTER_NAME --namespace store
    

    Ersetzen Sie CLUSTER_NAME durch gke-west-1 und gke-east-1. Die Ausgabe sollte in etwa so aussehen:

    # gke-west-1
    NAME           AGE
    store          2m40s
    store-west-1   2m40s
    
    # gke-east-1
    NAME           AGE
    store          2m25s
    store-east-1   2m25s
    

    Dies zeigt, dass der store-Service in beiden Clustern store-Pods enthält, während die store-west-1- und store-east-1-Services in den jeweiligen Clustern nur store-Pods enthalten. Diese sich überschneidenden Services werden verwendet, um die Pods auf mehrere Cluster oder eine Teilmenge von Pods in einem einzelnen Cluster auszurichten.

  4. Prüfen Sie nach einigen Minuten, ob die zugehörigen ServiceImports vom Multi-Cluster-Services-Controller automatisch in allen Clustern der Flotte erstellt wurden.

    kubectl get serviceimports --context CLUSTER_NAME --namespace store
    

    Ersetzen Sie CLUSTER_NAME durch gke-west-1 und gke-east-1. Die Ausgabe sollte in etwa so aussehen:

    # gke-west-1
    NAME           TYPE           IP                  AGE
    store          ClusterSetIP   ["10.112.31.15"]    6m54s
    store-east-1   ClusterSetIP   ["10.112.26.235"]   5m49s
    store-west-1   ClusterSetIP   ["10.112.16.112"]   6m54s
    
    # gke-east-1
    NAME           TYPE           IP                  AGE
    store          ClusterSetIP   ["10.72.28.226"]    5d10h
    store-east-1   ClusterSetIP   ["10.72.19.177"]    5d10h
    store-west-1   ClusterSetIP   ["10.72.28.68"]     4h32m
    

    Dies zeigt, dass auf alle drei Services von beiden Clustern in der Flotte aus zugegriffen werden kann. Da es jedoch nur einen aktiven Konfigurationscluster pro Flotte gibt, können Sie nur Gateways und HTTPRoutes bereitstellen, die in gke-west-1 auf diese ServiceImports verweisen. Wenn eine HTTPRoute im Konfigurationscluster auf diese ServiceImports als Back-Ends verweist, kann das Gateway Traffic an diese Services weiterleiten, unabhängig davon, aus welchem Cluster sie exportiert wurden.

Gateway und HTTPRoute bereitstellen

Wenn die Anwendungen bereitgestellt wurden, können Sie ein Gateway mithilfe der GatewayClass gke-l7-global-external-managed-mc konfigurieren. Dieses Gateway erstellt einen externen Application Load Balancer, der so konfiguriert ist, dass der Traffic auf Ihre Zielcluster verteilt wird.

  1. Wenden Sie das folgende Gateway-Manifest auf den Konfigurationscluster an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: external-http
      namespace: store
    spec:
      gatewayClassName: gke-l7-global-external-managed-mc
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          kinds:
          - kind: HTTPRoute
    EOF
    

    Diese Gateway-Konfiguration stellt externe Application-Load-Balancer-Ressourcen mit der folgenden Namenskonvention bereit: gkemcg1-NAMESPACE-GATEWAY_NAME-HASH.

    Die bei dieser Konfiguration erstellten Standardressourcen:

    • 1 Load Balancer: gkemcg1-store-external-http-HASH
    • 1 öffentliche IP-Adresse: gkemcg1-store-external-http-HASH
    • 1 Weiterleitungsregel: gkemcg1-store-external-http-HASH
    • 2 backend services:
      • Standard-Backend-Dienst 404: gkemcg1-store-gw-serve404-HASH
      • Standard-Backend-Dienst 500: gkemcg1-store-gw-serve500-HASH
    • 1 Systemdiagnose:
      • Standard-Systemdiagnose 404: gkemcg1-store-gw-serve404-HASH
    • 0 Routingregeln (URLmap ist leer)

    In dieser Phase führt jede Anfrage an GATEWAY_IP:80 zu einer Standardseite mit der folgenden Meldung: fault filter abort.

  2. Wenden Sie das folgende HTTPRoute-Manifest auf den Konfigurationscluster an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: public-store-route
      namespace: store
      labels:
        gateway: external-http
    spec:
      hostnames:
      - "store.example.com"
      parentRefs:
      - name: external-http
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /west
        backendRefs:
        - group: net.gke.io
          kind: ServiceImport
          name: store-west-1
          port: 8080
      - matches:
        - path:
            type: PathPrefix
            value: /east
        backendRefs:
          - group: net.gke.io
            kind: ServiceImport
            name: store-east-1
            port: 8080
      - backendRefs:
        - group: net.gke.io
          kind: ServiceImport
          name: store
          port: 8080
    EOF
    

    In dieser Phase führt jede Anfrage an GATEWAY_IP:80 zu einer Standardseite mit der folgenden Meldung: fault filter abort.

    Nach der Bereitstellung konfiguriert diese HTTPRoute das folgende Routingverhalten:

    • Anfragen an /west werden an store-Pods im gke-west-1-Cluster weitergeleitet, da Pods, die vom ServiceExport store-west-1 ausgewählt wurden, nur im gke-west-1-Cluster vorhanden sind.
    • Anfragen an /east werden an store-Pods im gke-east-1-Cluster weitergeleitet, da Pods, die vom ServiceExport store-east-1 ausgewählt wurden, nur im gke-east-1-Cluster vorhanden sind.
    • Anfragen an jeden anderen Pfad werden abhängig von ihrem Zustand, ihrer Kapazität und der Nähe zum anfragenden Client an store-Pods in einem der Cluster weitergeleitet.
    • Anfragen an GATEWAY_IP:80 führen zu einer Standardseite mit der folgenden Meldung: fault filter abort.

    HTTPRoute ermöglicht das Routing an verschiedene Teilmengen von Clustern durch den Einsatz von sich überschneidenden Diensten.

    Wenn alle Pods in einem bestimmten Cluster fehlerhaft oder nicht vorhanden sind, wird der Traffic zum store-Service nur an Cluster gesendet, die tatsächlich store-Pods haben. Wenn ein ServiceExport und Service in einem bestimmten Cluster vorhanden sind, wird dadurch nicht garantiert, dass Traffic an diesen Cluster gesendet wird. Pods müssen vorhanden sein und positiv auf die Systemdiagnose des Load-Balancers reagieren. Andernfalls sendet der Load-Balancer Traffic an fehlerfreie store-Pods in anderen Clustern.

    Neue Ressourcen werden mit dieser Konfiguration erstellt:

    • 3 backend services:
      • Der store-Backend-Dienst: gkemcg1-store-store-8080-HASH
      • Der store-east-1-Backend-Dienst: gkemcg1-store-store-east-1-8080-HASH
      • Der store-west-1-Backend-Dienst: gkemcg1-store-store-west-1-8080-HASH
    • 3 Systemdiagnosen:
      • Die store-Systemdiagnose: gkemcg1-store-store-8080-HASH
      • Die store-east-1-Systemdiagnose: gkemcg1-store-store-east-1-8080-HASH
      • Die store-west-1-Systemdiagnose: gkemcg1-store-store-west-1-8080-HASH
    • 1 Routingregel in der URLmap:
      • Die store.example.com-Routingregel:
      • 1 Host: store.example.com
      • Mehrere matchRules zur Weiterleitung an die neuen Backend-Dienste

Das folgende Diagramm zeigt die Ressourcen, die Sie in beiden Clustern bereitgestellt haben. Da gke-west-1 der Gateway-Konfigurationscluster ist, ist er der Cluster, in dem unser Gateway, die HTTPRoutes und die ServiceImports vom Gateway-Controller überwacht werden. Jeder Cluster hat einen store-ServiceImport und einen weiteren ServiceImport, der für diesen Cluster spezifisch ist. Beide verweisen auf dieselben Pods. Damit kann mit der HTTPRoute genau angegeben werden, wohin der Traffic geht – zu den store-Pods in einem bestimmten Cluster oder zu den store-Pods in allen Clustern.

Dies ist das Gateway- und Multi-Cluster-Service-Ressourcenmodell für beide Cluster

Beachten Sie, dass dies ein logisches Ressourcenmodell und keine Darstellung des Trafficflusses ist. Der Trafficpfad führt direkt vom Load-Balancer zu den Back-End-Pods und hat keine direkte Beziehung zu dem Cluster, der der Konfigurationscluster ist.

Bereitstellung prüfen

Sie können nun Anfragen an unser Multi-Cluster-Gateway senden und den Traffic auf beide GKE-Cluster verteilen.

  1. Rufen Sie den Gateway-Status und die Ereignisse auf, um zu prüfen, ob das Gateway und die HTTPRoute erfolgreich bereitgestellt wurden.

    kubectl describe gateways.gateway.networking.k8s.io external-http --context gke-west-1 --namespace store
    

    Die Ausgabe sollte in etwa so aussehen:

    Name:         external-http
    Namespace:    store
    Labels:       <none>
    Annotations:  networking.gke.io/addresses: /projects/PROJECT_NUMBER/global/addresses/gkemcg1-store-external-http-laup24msshu4
                  networking.gke.io/backend-services:
                    /projects/PROJECT_NUMBER/global/backendServices/gkemcg1-store-gw-serve404-80-n65xmts4xvw2, /projects/PROJECT_NUMBER/global/backendServices/gke...
                  networking.gke.io/firewalls: /projects/PROJECT_NUMBER/global/firewalls/gkemcg1-l7-default-global
                  networking.gke.io/forwarding-rules: /projects/PROJECT_NUMBER/global/forwardingRules/gkemcg1-store-external-http-a5et3e3itxsv
                  networking.gke.io/health-checks:
                    /projects/PROJECT_NUMBER/global/healthChecks/gkemcg1-store-gw-serve404-80-n65xmts4xvw2, /projects/PROJECT_NUMBER/global/healthChecks/gkemcg1-s...
                  networking.gke.io/last-reconcile-time: 2023-10-12T17:54:24Z
                  networking.gke.io/ssl-certificates: 
                  networking.gke.io/target-http-proxies: /projects/PROJECT_NUMBER/global/targetHttpProxies/gkemcg1-store-external-http-94oqhkftu5yz
                  networking.gke.io/target-https-proxies: 
                  networking.gke.io/url-maps: /projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-store-external-http-94oqhkftu5yz
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         Gateway
    Metadata:
      Creation Timestamp:  2023-10-12T06:59:32Z
      Finalizers:
        gateway.finalizer.networking.gke.io
      Generation:        1
      Resource Version:  467057
      UID:               1dcb188e-2917-404f-9945-5f3c2e907b4c
    Spec:
      Gateway Class Name:  gke-l7-global-external-managed-mc
      Listeners:
        Allowed Routes:
          Kinds:
            Group:  gateway.networking.k8s.io
            Kind:   HTTPRoute
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
    Status:
      Addresses:
        Type:   IPAddress
        Value:  34.36.127.249
      Conditions:
        Last Transition Time:  2023-10-12T07:00:41Z
        Message:               The OSS Gateway API has deprecated this condition, do not depend on it.
        Observed Generation:   1
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2023-10-12T07:00:41Z
        Message:               
        Observed Generation:   1
        Reason:                Accepted
        Status:                True
        Type:                  Accepted
        Last Transition Time:  2023-10-12T07:00:41Z
        Message:               
        Observed Generation:   1
        Reason:                Programmed
        Status:                True
        Type:                  Programmed
        Last Transition Time:  2023-10-12T07:00:41Z
        Message:               The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
        Observed Generation:   1
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2023-10-12T07:00:41Z
          Message:               
          Observed Generation:   1
          Reason:                Programmed
          Status:                True
          Type:                  Programmed
          Last Transition Time:  2023-10-12T07:00:41Z
          Message:               The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
          Observed Generation:   1
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    http
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
    Events:
      Type    Reason  Age                    From                   Message
      ----    ------  ----                   ----                   -------
      Normal  UPDATE  35m (x4 over 10h)      mc-gateway-controller  store/external-http
      Normal  SYNC    4m22s (x216 over 10h)  mc-gateway-controller  SYNC on store/external-http was a success
    
  2. Sobald das Gateway bereitgestellt wurde, rufen Sie die externe IP-Adresse vom external-http-Gateway ab.

    kubectl get gateways.gateway.networking.k8s.io external-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 Traffic an den Stammpfad der Domain. Dadurch wird der Traffic auf den store-ServiceImport verteilt, der sich in den Clustern gke-west-1 und gke-east-1 befindet. Der Load-Balancer sendet den Traffic an die nächstgelegene Region und Sie sehen möglicherweise keine Antworten aus der anderen Region.

    curl -H "host: store.example.com" http://VIP
    

    Die Ausgabe bestätigt, dass die Anfrage vom Pod aus dem Cluster gke-east-1 bereitgestellt wurde:

    {
      "cluster_name": "gke-east-1",
      "zone": "us-east1-b",
      "host_header": "store.example.com",
      "node_name": "gke-gke-east-1-default-pool-7aa30992-t2lp.c.agmsb-k8s.internal",
      "pod_name": "store-5f5b954888-dg22z",
      "pod_name_emoji": "⏭",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-06-01T17:32:51"
    }
    
  4. Als Nächstes senden Sie Traffic an den Pfad /west. Dadurch wird der Traffic an den ServiceImport store-west-1 weitergeleitet, der nur Pods im Cluster gke-west-1 ausführt. Ein clusterspezifischer ServiceImport wie store-west-1 ermöglicht einem Anwendungsinhaber, Traffic explizit an einen bestimmten Cluster zu senden, statt die Entscheidung dem Load Balancer zu überlassen.

    curl -H "host: store.example.com" http://VIP/west
    

    Die Ausgabe bestätigt, dass die Anfrage vom Pod aus dem Cluster gke-west-1 bereitgestellt wurde:

    {
      "cluster_name": "gke-west-1", 
      "zone": "us-west1-a", 
      "host_header": "store.example.com",
      "node_name": "gke-gke-west-1-default-pool-65059399-2f41.c.agmsb-k8s.internal",
      "pod_name": "store-5f5b954888-d25m5",
      "pod_name_emoji": "🍾",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-06-01T17:39:15",
    }
    
  5. Senden Sie nun Traffic an den Pfad /east.

    curl -H "host: store.example.com" http://VIP/east
    

    Die Ausgabe bestätigt, dass die Anfrage vom Pod aus dem Cluster gke-east-1 bereitgestellt wurde:

    {
      "cluster_name": "gke-east-1",
      "zone": "us-east1-b",
      "host_header": "store.example.com",
      "node_name": "gke-gke-east-1-default-pool-7aa30992-7j7z.c.agmsb-k8s.internal",
      "pod_name": "store-5f5b954888-hz6mw",
      "pod_name_emoji": "🧜🏾",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-06-01T17:40:48"
    }
    

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. Multi-Cluster-Gateways aktivieren

  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 an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    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 an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    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 an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    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 an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    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 an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    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.

Kapazitätsbasiertes Load-Balancing bereitstellen

Die Übung in diesem Abschnitt veranschaulicht die Konzepte für globales Load-Balancing und Service-Kapazität. Dazu wird eine Anwendung in zwei GKE-Clustern in verschiedenen Regionen bereitgestellt. Der generierte Traffic wird mit verschiedenen Werten für die Anfragen pro Sekunde (RPS) gesendet, um zu zeigen, wie das Traffic-Load-Balancing auf Cluster und Regionen erfolgt.

Das folgende Diagramm zeigt die Topologie, die Sie bereitstellen, und veranschaulicht, wie der Traffic zwischen Clustern und Regionen überläuft, wenn er die Service-Kapazität überschreitet:

Traffic, der von einem Cluster zu einem anderen überläuft

Weitere Informationen zur Traffic-Verwaltung finden Sie unter GKE-Traffic-Verwaltung.

Umgebung vorbereiten

  1. Folgen Sie der Anleitung unter Multi-Cluster-Gateways aktivieren, um Ihre Umgebung vorzubereiten.

  2. Prüfen Sie, ob die GatewayClass-Ressourcen im Konfigurationscluster installiert sind:

    kubectl get gatewayclasses --context=gke-west-1
    

    Die Ausgabe sieht in etwa so aus:

    NAME                                  CONTROLLER                  ACCEPTED   AGE
    gke-l7-global-external-managed        networking.gke.io/gateway   True       16h
    gke-l7-global-external-managed-mc     networking.gke.io/gateway   True       14h
    gke-l7-gxlb                           networking.gke.io/gateway   True       16h
    gke-l7-gxlb-mc                        networking.gke.io/gateway   True       14h
    gke-l7-regional-external-managed      networking.gke.io/gateway   True       16h
    gke-l7-regional-external-managed-mc   networking.gke.io/gateway   True       14h
    gke-l7-rilb                           networking.gke.io/gateway   True       16h
    gke-l7-rilb-mc                        networking.gke.io/gateway   True       14h
    

Anwendung bereitstellen

Stellen Sie den Beispielwebanwendungsserver in beiden Clustern bereit:

kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml
kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml

Die Ausgabe sieht in etwa so aus:

namespace/store created
deployment.apps/store created

Service, Gateway und HTTPRoute bereitstellen

  1. Wenden Sie das folgende Service-Manifest auf die Cluster gke-west-1 und gke-east-1 an:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: traffic-test
      annotations:
        networking.gke.io/max-rate-per-endpoint: "10"
    spec:
      ports:
      - port: 8080
        targetPort: 8080
        name: http
      selector:
        app: store
      type: ClusterIP
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store
      namespace: traffic-test
    EOF
    
    cat << EOF | kubectl apply --context gke-east-1 -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: traffic-test
      annotations:
        networking.gke.io/max-rate-per-endpoint: "10"
    spec:
      ports:
      - port: 8080
        targetPort: 8080
        name: http
      selector:
        app: store
      type: ClusterIP
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store
      namespace: traffic-test
    EOF
    

    Der Service wird mit max-rate-per-endpoint auf 10 Anfragen pro Sekunde annotiert. Mit zwei Replikaten pro Cluster hat jeder Service eine Kapazität von 20 RPS pro Cluster.

    Weitere Informationen zur Auswahl einer Service-Kapazitätsstufe für Ihren Service finden Sie unter Kapazität Ihres Service bestimmen.

  2. Wenden Sie das folgende Gateway-Manifest auf den Konfigurationscluster an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store
      namespace: traffic-test
    spec:
      gatewayClassName: gke-l7-global-external-managed-mc
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          kinds:
          - kind: HTTPRoute
    EOF
    

    Das Manifest beschreibt ein externes, globales Multi-Cluster-Gateway, das einen externen Application Load Balancer mit einer öffentlich zugänglichen IP-Adresse bereitstellt.

  3. Wenden Sie das folgende HTTPRoute-Manifest auf den Konfigurationscluster an, in diesem Beispiel gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store
      namespace: traffic-test
      labels:
        gateway: store
    spec:
      parentRefs:
      - kind: Gateway
        namespace: traffic-test
        name: store
      rules:
      - backendRefs:
        - name: store
          group: net.gke.io
          kind: ServiceImport
          port: 8080
    EOF
    

    Das Manifest beschreibt eine HTTPRoute, die das Gateway mit einer Routingregel konfiguriert, die den gesamten Traffic an den Speicher-ServiceImport weiterleitet. Der store-ServiceImport gruppiert die store-Service-Pods in beiden Clustern und ermöglicht ihnen, vom Load Balancer als ein einzelner Service adressiert zu werden.

    Sie können die Ereignisse des Gateways nach einigen Minuten prüfen, um festzustellen, ob die Bereitstellung abgeschlossen ist:

    kubectl describe gateway store -n traffic-test --context gke-west-1
    

    Die Ausgabe sieht in etwa so aus:

    ...
    Status:
      Addresses:
        Type:   IPAddress
        Value:  34.102.159.147
      Conditions:
        Last Transition Time:  2023-10-12T21:40:59Z
        Message:               The OSS Gateway API has deprecated this condition, do not depend on it.
        Observed Generation:   1
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2023-10-12T21:40:59Z
        Message:               
        Observed Generation:   1
        Reason:                Accepted
        Status:                True
        Type:                  Accepted
        Last Transition Time:  2023-10-12T21:40:59Z
        Message:               
        Observed Generation:   1
        Reason:                Programmed
        Status:                True
        Type:                  Programmed
        Last Transition Time:  2023-10-12T21:40:59Z
        Message:               The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
        Observed Generation:   1
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2023-10-12T21:40:59Z
          Message:               
          Observed Generation:   1
          Reason:                Programmed
          Status:                True
          Type:                  Programmed
          Last Transition Time:  2023-10-12T21:40:59Z
          Message:               The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
          Observed Generation:   1
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    http
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
    Events:
      Type    Reason  Age                  From                   Message
      ----    ------  ----                 ----                   -------
      Normal  ADD     12m                  mc-gateway-controller  traffic-test/store
      Normal  SYNC    6m43s                mc-gateway-controller  traffic-test/store
      Normal  UPDATE  5m40s (x4 over 12m)  mc-gateway-controller  traffic-test/store
      Normal  SYNC    118s (x6 over 10m)   mc-gateway-controller  SYNC on traffic-test/store was a success
    

    Diese Ausgabe zeigt, dass das Gateway erfolgreich bereitgestellt wurde. Nach der Bereitstellung des Gateways kann es einige Minuten dauern, bis der Traffic weitergeleitet wird. Notieren Sie sich die IP-Adresse in dieser Ausgabe, da sie in einem folgenden Schritt verwendet wird.

Traffic bestätigen

Testen Sie, ob der Traffic an die Anwendung weitergeleitet wird. Testen Sie dazu die Gateway-IP-Adresse mit einem curl-Befehl:

curl GATEWAY_IP_ADDRESS

Die Ausgabe sieht in etwa so aus:

{
  "cluster_name": "gke-west-1",
  "host_header": "34.117.182.69",
  "pod_name": "store-54785664b5-mxstv",
  "pod_name_emoji": "👳🏿",
  "project_id": "project",
  "timestamp": "2021-11-01T14:06:38",
  "zone": "us-west1-a"
}

Diese Ausgabe zeigt die Pod-Metadaten. Diese geben die Region an, in der die Anfrage verarbeitet wurde.

Traffic mithilfe von Lasttests prüfen

Wenn Sie prüfen möchten, ob der Load-Balancer funktioniert, können Sie in Ihrem gke-west-1-Cluster einen Traffic-Generator bereitstellen. Der Traffic-Generator generiert Traffic auf verschiedenen Laststufen, um die Kapazitäts- und Überlauffunktionen des Load-Balancers zu demonstrieren. Die folgenden Schritte demonstrieren drei Laststufen:

  • 10 RPS, was unter der Kapazität des Speicher-Service in gke-west-1 liegt.
  • 30 RPS, was die Kapazität für den gke-west-1-Speicher-Service überschreitet und einen Traffic-Überlauf zu gke-east-1 verursacht.
  • 60 RPS, was die Kapazität für die Services in beiden Clustern übersteigt.

Dashboard konfigurieren

  1. Rufen Sie den Namen der zugrunde liegenden URL-Zuordnung für Ihr Gateway ab:

    kubectl get gateway store -n traffic-test --context=gke-west-1 -o=jsonpath="{.metadata.annotations.networking\.gke\.io/url-maps}"
    

    Die Ausgabe sieht in etwa so aus:

    /projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-traffic-test-store-armvfyupay1t
    
  2. Rufen Sie in der Google Cloud Console die Seite Metrics Explorer auf.

    Zu Metrics Explorer

  3. Klicken Sie unter Messwert auswählen auf CODE: MQL.

  4. Geben Sie die folgende Abfrage ein, um die Traffic-Messwerte für den Speicher-Service in den beiden Clustern zu beobachten:

    fetch https_lb_rule
    | metric 'loadbalancing.googleapis.com/https/backend_request_count'
    | filter (resource.url_map_name == 'GATEWAY_URL_MAP')
    | align rate(1m)
    | every 1m
    | group_by [resource.backend_scope],
        [value_backend_request_count_aggregate:
            aggregate(value.backend_request_count)]
    

    Ersetzen Sie GATEWAY_URL_MAP durch den URL-Zuordnungsnamen aus dem vorherigen Schritt.

  5. Klicken Sie auf Abfrage ausführen. Warten Sie nach der Bereitstellung des Lastgenerators im nächsten Abschnitt mindestens fünf Minuten, bis die Messwerte im Diagramm angezeigt werden.

Mit 10 RPS testen

  1. Stellen Sie einen Pod in Ihrem gke-west-1-Cluster bereit:

    kubectl run --context gke-west-1 -i --tty --rm loadgen  \
        --image=cyrilbkr/httperf  \
        --restart=Never  \
        -- /bin/sh -c 'httperf  \
        --server=GATEWAY_IP_ADDRESS  \
        --hog --uri="/zone" --port 80  --wsess=100000,1,1 --rate 10'
    

    Ersetzen Sie GATEWAY_IP_ADDRESS durch die Gateway-IP-Adresse aus dem vorherigen Schritt.

    Die Ausgabe sieht etwa so aus, was darauf hinweist, dass der Traffic-Generator Traffic sendet:

    If you don't see a command prompt, try pressing enter.
    

    Der Lastgenerator sendet kontinuierlich 10 RPS an das Gateway. Obwohl der Traffic aus einer Google Cloud-Region stammt, behandelt der Load-Balancer ihn als Client-Traffic von der US-Westküste. Zur Simulation einer realistischen Client-Diversität sendet der Lastgenerator jede HTTP-Anfrage als neue TCP-Verbindung. Dies bedeutet, dass der Traffic gleichmäßiger auf die Backend-Pods verteilt wird.

    Es dauert bis zu fünf Minuten, bis der Generator Traffic für das Dashboard generiert.

  2. Sehen Sie sich das Metrics Explorer-Dashboard an. Es werden zwei Zeilen angezeigt, die angeben, wie viel Traffic per Load-Balancing auf jeden Cluster verteilt wird:

    Grafik mit Traffic-Load-Balancing zu Clustern

    Sie sollten sehen, dass us-west1-a etwa 10 RPS an Traffic empfängt, während us-east1-b keinen Traffic empfängt. Da der Traffic-Generator in us-west1 ausgeführt wird, wird der gesamte Traffic an den Service im gke-west-1-Cluster gesendet.

  3. Beenden Sie den Lastgenerator mit Strg + C und löschen Sie dann den Pod:

    kubectl delete pod loadgen --context gke-west-1
    

Mit 30 RPS testen

  1. Stellen Sie den Lastgenerator noch einmal bereit, aber konfigurieren Sie ihn zum Senden von 30 RPS:

    kubectl run --context gke-west-1 -i --tty --rm loadgen  \
        --image=cyrilbkr/httperf  \
        --restart=Never  \
        -- /bin/sh -c 'httperf  \
        --server=GATEWAY_IP_ADDRESS  \
        --hog --uri="/zone" --port 80  --wsess=100000,1,1 --rate 30'
    

    Es dauert bis zu fünf Minuten, bis der Generator Traffic für das Dashboard generiert.

  2. Rufen Sie das Cloud Ops-Dashboard auf.

    Grafik, die den Traffic-Überlauf zu gke-east-1 zeigt

    Sie sollten sehen, dass etwa 20 RPS an us-west1-a und 10 RPS an us-east1-b gesendet werden. Dies gibt an, dass der Service in gke-west-1 vollständig genutzt wird und 10 RPS an Traffic zum Service in gke-east-1 überlaufen.

  3. Beenden Sie den Lastgenerator mit Strg + C und löschen Sie dann den Pod:

    kubectl delete pod loadgen --context gke-west-1
    

Mit 60 RPS testen

  1. Stellen Sie den Lastgenerator bereit, der zum Senden von 60 RPS konfiguriert ist:

    kubectl run --context gke-west-1 -i --tty --rm loadgen  \
        --image=cyrilbkr/httperf  \
        --restart=Never  \
        -- /bin/sh -c 'httperf  \
        --server=GATEWAY_IP_ADDRESS  \
        --hog --uri="/zone" --port 80  --wsess=100000,1,1 --rate 60'
    
  2. Warten Sie fünf Minuten und sehen Sie sich Ihr Cloud Ops-Dashboard an. Es sollte nun zeigen, dass beide Cluster etwa 30 RPS erhalten. Da alle Services global überlastet sind, gibt es keinen Traffic-Überlauf und Services verarbeiten so viel Traffic wie möglich.

    Grafik: Services mit Überlastung

  3. Beenden Sie den Lastgenerator mit Strg + C und löschen Sie dann den Pod:

    kubectl delete pod loadgen --context gke-west-1
    

Bereinigen

Wenn Sie mit den Übungen auf dieser Seite 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
    

Multi-Cluster-Gateway mit freigegebener VPC verwenden

Ein Multi-Cluster-Gateway kann auch in einer Umgebung mit freigegebener VPC bereitgestellt werden, mit unterschiedlichen Topologien, je nach Anwendungsfall.

In der folgenden Tabelle werden die unterstützten Multi-Cluster-Gateway-Topologien innerhalb einer Umgebung mit freigegebener VPC beschrieben:

Szenario Flotten-Hostprojekt Konfigurationscluster Arbeitslastcluster
1 Hostprojekt mit freigegebener VPC Hostprojekt mit freigegebener VPC Hostprojekt mit freigegebener VPC
2 Dienstprojekt mit freigegebener VPC Dienstprojekt mit freigegebener VPC
(wie Flotten-Dienstprojekt)
Dienstprojekt mit freigegebener VPC
(wie Flotten-Dienstprojekt)

Führen Sie die folgenden Schritte aus, um Multi-Cluster-Gateways in einer Umgebung mit freigegebener VPC zu erstellen:

  1. Folgen Sie der Anleitung zum Einrichten von Multi-Cluster-Diensten mit freigegebener VPC.

  2. Dienste erstellen und in den Konfigurationscluster exportieren

  3. Wenn Sie ein internes Multi-Cluster-Gateway verwenden möchten, erstellen Sie ein Nur-Proxy-Subnetz.

  4. Erstellen Sie ein externes oder internes Multi-Cluster-Gateway und HTTPRoutes.

Wenn Sie diese Schritte ausgeführt haben, können Sie Ihre Bereitstellung je nach Topologie validieren.

Fehlerbehebung

Nur-Proxy-Subnetz für internes Gateway ist nicht vorhanden

Wenn das folgende Ereignis auf Ihrem internen Gateway angezeigt wird, ist für diese Region kein Nur-Proxy-Subnetz vorhanden. Stellen Sie ein Nur-Proxy-Subnetz bereit, um dieses Problem zu beheben.

generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/us-west1/targetHttpProxies/gkegw-x5vt-default-internal-http-2jzr7e3xclhj'. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.

Kein fehlerfreier 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 weist darauf hin, dass der Systemdiagnose-Prober keine fehlerfreien Back-End-Dienste finden kann. Es ist möglich, dass Ihre Back-End-Dienste fehlerfrei sind, aber möglicherweise müssen Sie die Systemdiagnosen 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