Externes HTTP(S)-Load-Balancing für verwaltetes Anthos Service Mesh konfigurieren

Überblick

Cloud Load Balancing bietet viele von der Cloud verwaltete Edge-Funktionen, darunter globales Anycast-Load-Balancing, von Google verwaltete Zertifikate, Identitäts- und Zugriffsverwaltung sowie Cloud-Firewall oder IDS. Anthos Service Mesh kann diese Edge-Funktionen nahtlos in das folgende Mesh-Ingress-Modell einbinden. Das Service Mesh-Cloud-Gateway bietet eine einheitliche Möglichkeit, das Anthos Service Mesh-Ingress-Gateway mit Cloud Load Balancing gleichzeitig über die Kubernetes Gateway API zu konfigurieren.

Diagramm zum Veranschaulichen des Cloud-Load-Balancers mit Anthos Service Mesh

Im Vergleich zum vorherigen Nutzerhandbuch Von Edge zu Mesh: Service Mesh-Anwendungen über GKE Ingress verfügbar machen mit einem Service Mesh-Cloud-Gateway kann dieses Modell jetzt über eine Kubernetes-Gateway-Ressource bereitgestellt werden. Dadurch wird die gemeinsame Bereitstellung von Cloud- und clustergehostetem Load-Balancing vereinfacht.

Vorschau Einschränkungen

Für die Vorabversion dieser Funktion gelten die folgenden Einschränkungen:

  • Multi-Cluster-Gateways werden nicht unterstützt.
  • Autopilot-Cluster werden nicht unterstützt.
  • Nur der klassische Application Load Balancer wird unterstützt. Der erweiterte und interne HTTP(S)-Load-Balancer werden nicht unterstützt.
  • Traffic zwischen dem externen HTTP(S)-Load-Balancer und dem Anthos Service Mesh-Ingress-Gateway wird mit TLS verschlüsselt. Der externe HTTP(S)-Load-Balancer prüft jedoch nicht das vom Anthos Service Mesh-Ingress-Gateway bereitgestellte Zertifikat. Diese Einschränkung gilt für alle Nutzer des Google Cloud HTTP(S)-Load-Balancers.
  • Wenn Anthos Service Mesh-GatewayClasses aus einem Cluster gelöscht werden, werden sie nicht automatisch neu installiert. Dies wirkt sich jedoch nicht auf die Nutzung der Funktion aus.
  • Die Logik für den Routenabgleich entspricht nicht den Gateway API-Spezifikationen und erfolgt in der Reihenfolge der HTTPRoute. Dies wird in zukünftigen Versionen geändert, sodass die Gateway API-Spezifikationen eingehalten werden.

Voraussetzungen

  • Verwaltetes Anthos Service Mesh, das in einem GKE-Cluster (Google Kubernetes Engine) mit Version 1.24 oder höher installiert ist. Andere GKE Enterprise-Cluster werden nicht unterstützt.
  • Nur Kubernetes Gateway API v1beta1.

Vorbereitung

  • Aktivieren Sie die folgenden APIs in Ihrem Projekt:

    • compute.googleapis.com
    • container.googleapis.com
    • certificatemanager.googleapis.com
    • serviceusage.googleapis.com
    gcloud services enable \
       compute.googleapis.com \
       container.googleapis.com \
       certificatemanager.googleapis.com \
       serviceusage.googleapis.com
    

Service Mesh-Cloud-Gateway für ein Single-Cluster-Mesh bereitstellen

In diesem Abschnitt wird beschrieben, wie Sie eine Kubernetes-Gateway-Ressource bereitstellen, die einen globalen externen HTTP(S)-Load-Balancer (klassisch) und ein Anthos Service Mesh-Ingress-Gateway bereitstellt.

Gateway API mit verwaltetem Anthos Service Mesh aktivieren

  1. Aktivieren Sie die Gateway API in Ihrem Cluster. Der GKE-Cluster muss die Version 1.24 oder höher haben.

  2. Installieren Sie das verwaltete Anthos Service Mesh mit rapid oder regular als Release-Version.

Gateway-Ressource bereitstellen

Beim Bereitstellen des Service Mesh-Cloud-Gateways werden die Kubernetes-Gateway-Ressourcen verwendet, um sowohl Cloud Load Balancing als auch das Anthos Service Mesh-Ingress-Gateway in einem Schritt bereitzustellen. Beachten Sie, dass sich Kubernetes Gateway-Ressourcen von Istio Gateway-Ressourcen unterscheiden.

Weitere Informationen zu den Unterschieden finden Sie unter Kubernetes-Gateways und Istio-Gateways. Jedes Kubernetes-Gateway hat eine GatewayClass, die seinen Typ und inhärente Funktionen angibt. Das Service-Mesh-Cloud-Gateway hat eine GatewayClass, die sowohl Cloud Load Balancing als auch das Anthos Service Mesh-Ingress-Gateway bereitstellen kann.

  1. Speichern Sie das folgende GatewayClass-Manifest in einer Datei mit dem Namen l7-gateway-class.yaml:

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: GatewayClass
    metadata:
      name: asm-l7-gxlb
    spec:
      controllerName: mesh.cloud.google.com/gateway
    
  2. Stellen Sie GatewayClass in Ihrem Cluster bereit:

    kubectl apply -f l7-gateway-class.yaml
    
  3. Prüfen Sie, ob GatewayClass nach der Installation vorhanden ist:

    kubectl get gatewayclasses.gateway.networking.k8s.io
    

    Die Ausgabe sieht etwa so aus:

    NAME          CONTROLLER
    asm-l7-gxlb   mesh.cloud.google.com/gateway
    gke-l7-rilb   networking.gke.io/gateway
    gke-l7-gxlb   networking.gke.io/gateway
    

    Es kann einige Minuten dauern, bis alle Ressourcen bereitgestellt sind. Wenn die erwartete Ausgabe nicht angezeigt wird, prüfen Sie, ob die Voraussetzungen korrekt erfüllt sind.

    Außerdem wird die folgende GatewayClass angezeigt:

    gke-l7-gxlb   networking.gke.io/gateway
    

    Damit wird der zugrunde liegende globale externe HTTP(S)-Load-Balancer von Google Cloud bereitgestellt.

  4. Erstellen Sie einen dedizierten Namespace für Ihr Service Mesh-Cloud-Gateway:

    kubectl create namespace istio-ingress
    
  5. Speichern Sie folgendes Gateway-Manifest in einer Datei mit dem Namen gateway.yaml.

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: servicemesh-cloud-gw
      namespace: istio-ingress
    spec:
      gatewayClassName: asm-l7-gxlb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: All
    
  6. Stellen Sie das Gateway in Ihrem Cluster im istio-Ingress-Namespace bereit:

    kubectl apply -f gateway.yaml
    
  7. Prüfen Sie, ob die Kubernetes Gateway API-Objekte erstellt wurden:

    kubectl get gateways.gateway.networking.k8s.io -n istio-ingress
    

    Die Ausgabe sieht etwa so aus:

    NAME                                CLASS         ADDRESS         READY   AGE
    asm-gw-gke-servicemesh-cloud-gw     gke-l7-gxlb   34.111.114.64   True    9m40s
    asm-gw-istio-servicemesh-cloud-gw   istio                                 9m44s
    servicemesh-cloud-gw                asm-l7-gxlb                           9m44s
    

Bei der Bereitstellung dieses Kubernetes Gateway API-Objekts geschieht Folgendes:

  • Ein externer HTTP(S)-Load-Balancer wird bereitgestellt und konfiguriert. Es kann einige Minuten dauern, bis er angezeigt wird. Wenn er angezeigt wird, gibt das Gateway die IP-Adresse und die Namen der erstellten Ressourcen des Compute Engine-Load-Balancers an.
  • Ein Anthos Service Mesh-Ingress-Gateway-Deployment wird im istio-Ingress-Namespace erstellt. Dadurch werden die Envoy-Proxy-Instanzen erstellt, die Traffic vom Cloud Load Balancer erhalten.
  • Der Cloud-Load-Balancer verschlüsselt und leitet den gesamten Traffic an das Anthos Service Mesh-Ingress-Gateway weiter.

Sie haben jetzt die vollständige Infrastruktur, die erforderlich ist, um Internet-Traffic in Ihr Mesh-Netzwerk aufzunehmen. Beachten Sie, dass dies die einfachste Gateway-Bereitstellung ist. In den folgenden Abschnitten fügen Sie zusätzliche Richtlinien und Funktionen hinzu, um das Produkt produktionsreif zu machen.

Anwendungs- und Routingbereitstellung

Um die Funktionen vollständig zu demonstrieren, stellen Sie beispielsweise eine Anwendung in Anthos Service Mesh bereit und empfangen Internet-Traffic über Ihr Gateway.

  1. Fügen Sie dem Namespace default Labels hinzu, um die Sidecar-Injektion zu aktivieren.

    kubectl label namespace default istio-injection=enabled istio.io/rev- --overwrite
    
  2. Speichern Sie folgendes Gateway-Manifest in einer Datei mit dem Namen whereami.yaml.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-v1
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whereami-v1
      template:
        metadata:
          labels:
            app: whereami-v1
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
              - containerPort: 8080
            env:
            - name: METADATA
              value: "whereami-v1"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: whereami-v1
    spec:
      selector:
        app: whereami-v1
      ports:
      - port: 8080
        targetPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-v2
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whereami-v2
      template:
        metadata:
          labels:
            app: whereami-v2
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
              - containerPort: 8080
            env:
            - name: METADATA
              value: "whereami-v2"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: whereami-v2
    spec:
      selector:
        app: whereami-v2
      ports:
      - port: 8080
        targetPort: 8080
    

    Dieses Manifest erstellt Service/whereami-v1, Service/whereami-v2, Deployment/whereami-v1 und Deployment/whereami-v2 für whereami, eine einfache Anwendung, die JSON ausgibt, um ihre Identität und ihren Standort anzugeben. Sie werden zwei verschiedene Versionen davon bereitstellen.

  3. Erstellen Sie die Dienste und Bereitstellungen:

    kubectl apply -f whereami.yaml
    

    Sobald es betriebsbereit ist, werden vier Pods in Ihrem Cluster ausgeführt.

  4. Prüfen Sie, ob alle vier Pods ausgeführt werden:

    kubectl get pods
    

    Die Ausgabe sieht etwa so aus:

    whereami-v1-7c76d89d55-qg6vs       2/2     Running   0          28s
    whereami-v1-7c76d89d55-vx9nm       2/2     Running   0          28s
    whereami-v2-67f6b9c987-p9kqm       2/2     Running   0          27s
    whereami-v2-67f6b9c987-qhj76       2/2     Running   0          27s
    
  5. Speichern Sie das folgende HTTPRoute-Manifest in einer Datei mit dem Namen http-route.yaml.

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: where-route
    spec:
     parentRefs:
     - kind: Gateway
       name: servicemesh-cloud-gw
       namespace: istio-ingress
     hostnames:
     - "where.example.com"
     rules:
     - matches:
       - headers:
         - name: version
           value: v2
       backendRefs:
       - name: whereami-v2
         port: 8080
     - backendRefs:
       - name: whereami-v1
         port: 8080
    
  6. Stellen Sie http-route.yaml in Ihrem Cluster bereit:

    kubectl apply -f http-route.yaml
    

    Diese HTTP-Route verweist auf servicemesh-cloud-gw. Das bedeutet, dass das Service Mesh-Cloud-Gateway so konfiguriert wird, dass das zugrunde liegende Anthos Service Mesh-Ingress-Gateway mit diesen Routingregeln konfiguriert wird. Die HTTPRoute führt dieselbe Funktion wie der Istio VirtualService aus, verwendet dazu jedoch die Kubernetes Gateway API. Da die Gateway API eine OSS-Spezifikation mit vielen zugrunde liegenden Implementierungen ist, eignet sie sich am besten für die Definition des Routings über eine Kombination verschiedener Load-Balancer (z. B. Anthos Service Mesh-Proxys und Cloud Load Balancer).

  7. Rufen Sie die IP-Adresse aus dem Gateway ab, damit Sie Traffic an Ihre Anwendung senden können:

    VIP=$(kubectl get gateways.gateway.networking.k8s.io asm-gw-gke-servicemesh-cloud-gw -o=jsonpath="{.status.addresses[0].value}" -n istio-ingress)
    

    Die Ausgabe ist eine IP-Adresse.

    echo $VIP
    
    34.111.61.135
    
  8. Senden Sie Traffic an die Gateway-IP-Adresse, um zu prüfen, ob diese Einrichtung korrekt funktioniert. Senden Sie eine Anfrage mit dem Header version: v2 und eine ohne, um festzustellen, ob das Routing über die beiden Anwendungsversionen hinweg korrekt erfolgt.

    curl ${VIP} -H "host: where.example.com"
    
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "whereami-v1",
      "node_name": "gke-gke1-default-pool-9b3b5b18-hw5z.c.church-243723.internal",
      "pod_name": "whereami-v1-67d9c5d48b-zhr4l",
      "pod_name_emoji": "⚒",
      "project_id": "church-243723",
      "timestamp": "2021-02-08T18:55:01",
      "zone": "us-central1-a"
    }
    
    curl ${VIP} -H "host: where.example.com" -H "version: v2"
    
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "whereami-v2",
      "node_name": "gke-gke1-default-pool-9b3b5b18-hw5z.c.church-243723.internal",
      "pod_name": "whereami-v2-67d9c5d48b-zhr4l",
      "pod_name_emoji": "⚒",
      "project_id": "church-243723",
      "timestamp": "2021-02-08T18:55:01",
      "zone": "us-central1-a"
    }
    

Bereitstellung des Produktionsgateways

Im vorherigen Abschnitt wurde ein sehr einfaches Beispiel für ein Service Mesh-Cloud-Gateway gezeigt. Die folgenden Schritte bauen auf dem einfachen Beispiel auf und zeigen eine produktionsreife Einrichtung, die die Vorteile des Delegierens eines Teils der Funktionen für das Routing von eingehendem Traffic an den Cloud-Load-Balancer veranschaulicht.

Im folgenden Beispiel verwenden Sie servicemesh-cloud-gw aus dem vorherigen Abschnitt und fügen die folgenden Funktionen hinzu, um ein sichereres und besser zu verwaltendes Gateway zu erstellen:

  • Stellen Sie das Gateway mit einer statischen IP-Adresse bereit, die auch dann beibehalten wird, wenn sich die zugrunde liegende Infrastruktur ändert.
  • Konvertieren Sie das Gateway so, dass es HTTPS-Traffic mit einem selbst signierten Zertifikat empfängt.
  1. Erstellen Sie eine statische externe IP-Adresse. Eine statische IP-Adresse ist nützlich, da sich die zugrunde liegende Infrastruktur in Zukunft ändern kann, die IP-Adresse jedoch beibehalten werden kann.

    gcloud compute addresses create whereami-ip \
        --global \
        --project PROJECT_ID
    
  2. Erstellen Sie ein selbst signiertes Zertifikat für die Domain where-example-com:

    openssl genrsa -out key.pem 2048
    cat <<EOF >ca.conf
    [req]
    default_bits              = 2048
    req_extensions            = extension_requirements
    distinguished_name        = dn_requirements
    prompt                    = no
    [extension_requirements]
    basicConstraints          = CA:FALSE
    keyUsage                  = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName            = @sans_list
    [dn_requirements]
    0.organizationName        = example
    commonName                = where.example.com
    [sans_list]
    DNS.1                     = where.example.com
    EOF
    
    openssl req -new -key key.pem \
        -out csr.pem \
        -config ca.conf
    
    openssl x509 -req \
        -signkey key.pem \
        -in csr.pem \
        -out cert.pem \
        -extfile ca.conf \
        -extensions extension_requirements \
        -days 365
    
    gcloud compute ssl-certificates create where-example-com \
        --certificate=cert.pem \
        --private-key=key.pem \
        --global \
        --project PROJECT_ID
    

    Es gibt viele Möglichkeiten, TLS-Zertifikate zu generieren. Sie können manuell in der Befehlszeile oder mit von Google verwalteten Zertifikaten generiert werden oder intern über die Public-Key-Infrastruktur (PKI) Ihres Unternehmens generiert werden. In diesem Beispiel generieren Sie manuell ein selbst signiertes Zertifikat. Selbstsignierte Zertifikate werden normalerweise nicht für öffentliche Dienste verwendet, können diese Konzepte aber leichter demonstriert werden.

    Weitere Informationen zum Erstellen eines selbst signierten Zertifikats mit Kubernetes-Secret finden Sie unter Gateway sichern.

  3. Aktualisieren Sie gateway.yaml mit dem folgenden Manifest:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: servicemesh-cloud-gw
      namespace: istio-ingress
    spec:
      gatewayClassName: asm-l7-gxlb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: All
      - name: https
        protocol: HTTPS
        port: 443
        allowedRoutes:
          namespaces:
            from: All
        tls:
          mode: Terminate
          options:
            networking.gke.io/pre-shared-certs: where-example-com
      addresses:
      - type: NamedAddress
        value: whereami-ip
    
  4. Stellen Sie das Gateway noch einmal in Ihrem Cluster bereit:

    kubectl apply -f gateway.yaml
    
  5. Rufen Sie die IP-Adresse der statischen IP-Adresse ab:

    VIP=$(gcloud compute addresses describe whereami-ip --global --format="value(address)")
    
  6. Verwenden Sie curl, um auf die Domain des Gateways zuzugreifen. Da DNS für diese Domain nicht konfiguriert ist, können Sie curl mit der Option "--resolve" anweisen, den Domainnamen in die IP-Adresse des Gateways aufzulösen:

    curl https://where.example.com --resolve where.example.com:443:${VIP} --cacert cert.pem -v
    

    Nach Abschluss sieht die Ausgabe in etwa so aus:

    ...
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=where.example.com
    *  start date: Apr 19 15:54:50 2021 GMT
    *  expire date: Apr 19 15:54:50 2022 GMT
    *  common name: where.example.com (matched)
    *  issuer: O=example; CN=where.example.com
    *  SSL certificate verify ok.
    ...
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "where-v1",
      "node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal",
      "pod_name": "where-v1-84b47c7f58-tj5mn",
      "pod_name_emoji": "😍",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-04-19T16:30:08",
      "zone": "us-west1-a"
    }
    

Die ausführliche Ausgabe enthält einen erfolgreichen TLS-Handshake, gefolgt von einer Antwort der Anwendung, wie in der folgenden Ausgabe. Dadurch wird bestätigt, dass TLS am Gateway korrekt beendet wird und dass die Anwendung sicher auf dem Client reagiert.

Sie haben die folgende Architektur bereitgestellt:

ASM-Architektur

Das servicemesh-cloud-gw und seine asm-l7-gxlb GatewayClass haben einige interne Infrastrukturkomponenten abstrahiert, um die Nutzung zu vereinfachen. Cloud Load Balancing beendet TLS-Traffic mit einem internen Zertifikat und seine Systemdiagnose auf der Proxyebene des Anthos Service Mesh-Ingress-Gateways. Die in der App- und Routing-Bereitstellung bereitgestellte whereami-route konfiguriert die Ingress-Gateway-Proxys von Anthos Service Mesh so, dass Traffic an den richtigen, vom Mesh gehosteten Dienst weitergeleitet wird.

Nächste Schritte