Istio für das Load-Balancing interner gRPC-Dienste verwenden

In dieser Anleitung wird beschrieben, wie Sie das interne TCP/UDP-Load-Balancing mit Istio für gRPC-Dienste einrichten, die auf Google Kubernetes Engine (GKE) ausgeführt werden. Diese Konfiguration ermöglicht anderen Ressourcen in Ihrem VPC-Netzwerk, durch die Verwendung einer privaten, internen IP-Adresse (RFC 1918) mit gRPC-Diensten zu kommunizieren. Dabei übernimmt Istio die Routing- und Load-Balancing-Anfragen aller Kubernetes-Pods, die die gRPC-Dienste ausführen.

Diese Anleitung setzt Grundkenntnisse in gRPC und GKE oder Kubernetes voraus.

Einführung

Istio bietet Gateways für die Verwaltung von Traffic, der in das Service Mesh eintritt und dieses verlässt. Das Gateway des internen Load-Balancers (ILB) von Istio leitet eingehenden Traffic von Quellen im internen VPC-Netzwerk an Kubernetes-Pods im Service Mesh weiter. In dieser Architektur führt das interne TCP/UDP-Load-Balancing von Google Cloud ein Layer-4-Load-Balancing (Transportebene) zwischen den Knoten im GKE-Cluster aus. Das Istio-ILB-Gateway empfängt den Traffic und führt ein Layer-7-Load-Balancing (Anwendungsebene) aus, wodurch der Traffic auf Dienste im Service Mesh von Istio verteilt wird. Dabei werden Regeln angewendet, die unter virtuelle Dienste und Zielregeln definiert sind.

Der in dieser Anleitung verwendete Beispiel-gRPC-Dienst gibt einen Antwort-Header zurück, in dem der Name des Kubernetes-Pods enthalten ist, der die Anfrage verarbeitet hat. Anhand dieser Information können Sie sehen, dass das Load-Balancing des Istio-ILB-Gateways Anfragen von einem Client über eine einzelne Verbindung an mehrere Kubernetes-Pods im GKE-Cluster verteilt.

Ziele

  • GKE-Cluster mit Istio und dem Istio-ILB-Gateway erstellen
  • Beispiel-gRPC-Dienst bereitstellen
  • Interne Konnektivität überprüfen

Kosten

In dieser Anleitung werden die folgenden kostenpflichtigen Komponenten von Google Cloud verwendet:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Nach Abschluss dieser Anleitung können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Vorbereitung

  1. Melden Sie sich in Ihrem Google-Konto an oder, falls Sie noch keines haben, registrieren Sie sich für ein neues Konto.
  2. Rufen Sie in der Cloud Console die Seite für die Projektauswahl auf.

    Zur Projektauswahl

  3. Wählen Sie ein Cloud-Projekt aus oder erstellen Sie eines.

  4. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für Ihr Projekt aktiviert ist.

Umgebung initialisieren

  1. Wählen Sie in der Cloud Console aus dem Drop-down-Menü Projekt auswählen das Projekt aus, das Sie verwenden möchten.

  2. Öffnen Sie Cloud Shell:

    Zu Cloud Shell

    Für alle Befehle in dieser Anleitung wird Cloud Shell verwendet.

  3. Aktivieren Sie die Cloud Build API, die Google Kubernetes Engine API, die Container Analysis API und die Cloud APIs:

    gcloud services enable \
        cloudapis.googleapis.com \
        cloudbuild.googleapis.com \
        container.googleapis.com \
        containeranalysis.googleapis.com
    
  4. Legen Sie den Standardwert gcloud für die Compute Engine-Zone fest, die Sie für diese Anleitung verwenden möchten:

    gcloud config set compute/zone us-central1-b
    

    In dieser Anleitung wird die Zone us-central1-b verwendet. Sie können die Zone Ihren Anforderungen entsprechend ändern.

  5. Klonen Sie das Git-Repository mit dem Beispiel-gRPC-Dienst und wechseln Sie zum Arbeitsverzeichnis:

    git clone https://github.com/GoogleCloudPlatform/istio-samples.git
    cd istio-samples/sample-apps/grpc-greeter-go
    

GKE-Cluster mit Istio erstellen

  1. Erstellen Sie in Cloud Shell einen GKE-Cluster:

    gcloud beta container clusters create grpc-istio-ilb-tutorial \
        --machine-type n1-standard-2 \
        --enable-ip-alias
    
  2. Erteilen Sie sich die Rechte eines Clusteradministrators:

    kubectl create clusterrolebinding cluster-admin-binding \
        --clusterrole cluster-admin \
        --user $(gcloud config get-value account)
    

    Sie müssen die in der Kubernetes-Clusterrolle cluster-admin definierten Berechtigungen haben, um Istio installieren zu können.

  3. Erstellen Sie einen Kubernetes-Namespace mit dem Namen istio-system:

    kubectl create namespace istio-system
    
  4. Laden Sie Istio herunter und extrahieren Sie es:

    ISTIO_VERSION=1.2.7
    curl -L https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istio-$ISTIO_VERSION-linux.tar.gz | tar -zxf -
    
  5. Verwenden Sie das lokale Vorlagen-Rendering von Helm, um die benutzerdefinierten Ressourcendefinitionen (Custom Resource Definitions, CRDs) von Istio zu installieren:

    helm template \
        istio-$ISTIO_VERSION/install/kubernetes/helm/istio-init \
        --namespace istio-system | kubectl apply -f -
    
  6. Verwenden Sie Helm, um Istio mit dem ILB-Gateway (istio-ilbgateway) zu installieren:

    ISTIO_PACKAGE=$ISTIO_VERSION-gke.0
    
    helm template \
        istio-$ISTIO_VERSION/install/kubernetes/helm/istio \
        --set gateways.istio-ingressgateway.enabled=false \
        --set gateways.istio-ilbgateway.enabled=true \
        --set gateways.istio-ilbgateway.ports[0].name=grpc-pilot-mtls \
        --set gateways.istio-ilbgateway.ports[0].port=15011 \
        --set gateways.istio-ilbgateway.ports[1].name=grpc \
        --set gateways.istio-ilbgateway.ports[1].port=443 \
        --set gateways.istio-ilbgateway.ports[2].name=tcp-citadel-grpc-tls \
        --set gateways.istio-ilbgateway.ports[2].port=8060 \
        --set gateways.istio-ilbgateway.ports[2].targetPort=8060 \
        --set gateways.istio-ilbgateway.ports[3].name=tcp-dns \
        --set gateways.istio-ilbgateway.ports[3].port=5353 \
        --set global.hub=gcr.io/gke-release/istio \
        --set global.tag=$ISTIO_PACKAGE \
        --namespace istio-system | kubectl apply -f -
    
  7. Prüfen Sie den Status der Erstellung einer externen IP-Adresse für den Kubernetes-Dienst istio-ilbgateway:

    kubectl get services istio-ilbgateway -n istio-system --watch
    

    Warten Sie, bis sich der Wert für EXTERNAL-IP von <pending> in eine IP-Adresse ändert. Drücken Sie Strg + C, wenn Sie nicht mehr warten möchten.

TLS-Zertifikat für das Istio-ILB-Gateway erstellen

  1. Erstellen Sie in Cloud Shell ein TLS-Zertifikat und einen privaten Schlüssel, um die Beendigung von TLS-Verbindungen durch das Istio-ILB-Gateway zu ermöglichen:

    openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
        -keyout privkey.pem -out cert.pem -subj "/CN=grpc.example.com"
    
  2. Erstellen Sie ein Kubernetes-Secret, um das TLS-Zertifikat und den privaten Schlüssel zu speichern:

    kubectl -n istio-system create secret tls istio-ilbgateway-certs \
        --key privkey.pem --cert cert.pem \
        --dry-run -o yaml | kubectl apply -f -
    

Beispielanwendung installieren

Im nächsten Schritt erstellen Sie ein Container-Image für den Beispiel-gRPC-Dienst und stellen es in Ihrem GKE-Cluster bereit. Der Beispiel-gRPC-Dienst besteht aus einer Clientkomponente, die als gRPC-Client bezeichnet wird, und einer Serverkomponente, die als gRPC-Server bezeichnet wird.

  1. Aktivieren Sie in Cloud Shell das automatische Einfügen des Istio-Sidecars in den Namespace default:

    kubectl label namespace default istio-injection=enabled
    
  2. Erstellen Sie mit Cloud Build ein Container-Image für den gRPC-Server:

    gcloud builds submit server -t gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-server
    
  3. Erstellen Sie die Kubernetes-Deployment- und -Dienstobjekte für den gRPC-Server:

    envsubst < manifests/greeter-k8s.template.yaml | kubectl apply -f -
    
  4. Prüfen Sie, ob der Kubernetes-Dienst ClusterIP erstellt wurde und die Pods ausgeführt werden:

    kubectl get services,pods
    

    Die Ausgabe sieht etwa so aus:

    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
    service/greeter      ClusterIP   10.0.18.67   <none>        8080/TCP   11s
    service/kubernetes   ClusterIP   10.0.16.1    <none>        443/TCP    1h
    NAME READY STATUS RESTARTS AGE pod/greeter-844cffd75-7hpcb 2/2 Running 0 56s pod/greeter-844cffd75-ffccl 2/2 Running 0 56s pod/greeter-844cffd75-zww6h 2/2 Running 0 56s

    Die Pods zeigen 2/2 in der Spalte READY an. Diese Ausgabe bedeutet, dass für jeden Pod sowohl der gRPC-Servercontainer als auch der Envoy-Sidecar-Container ausgeführt werden.

  5. Erstellen Sie die Objekte Istio-Gateway, virtueller Dienst und Zielregel für den gRPC-Server:

    kubectl apply -f manifests/greeter-istio-ilbgateway.yaml \
        -f manifests/greeter-istio-virtualservice.yaml \
        -f manifests/greeter-istio-destinationrule.yaml
    
  6. Überprüfen Sie, ob alle drei Objekte erfolgreich erstellt wurden:

    kubectl get gateway,virtualservice,destinationrule
    

    Die Ausgabe sieht etwa so aus:

    NAME                                  AGE
    gateway.networking.istio.io/greeter   1m
    NAME GATEWAYS HOSTS AGE virtualservice.networking.istio.io/greeter [greeter] [*] 1m
    NAME HOST AGE destinationrule.networking.istio.io/greeter greeter 1m

Interne Konnektivität überprüfen

Das interne TCP-/UDP-Load-Balancing erfolgt regional, sodass Sie die Konnektivität von einer VM in derselben Zone oder Region aus testen können.

  1. Erstellen Sie in Cloud Shell mit Cloud Build ein Container-Image für den gRPC-Client:

    gcloud builds submit client \
        -t gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-client
    
  2. Erstellen Sie eine Compute Engine-Instanz in derselben Zone oder Region, in der sich auch der GKE-Cluster befindet:

    gcloud compute instances create grpc-istio-ilb-tutorial-client-vm \
        --scopes https://www.googleapis.com/auth/devstorage.read_only \
        --image-project cos-cloud \
        --image-family cos-stable
    

    Der Bereich devstorage.read_only ist erforderlich, um Images aus Container Registry herunterzuladen.

  3. Speichern Sie die IP-Adresse des Istio-ILB-Gateways in einer Datei mit dem Namen ilb-ip.txt:

    kubectl -n istio-system get services istio-ilbgateway \
        -o jsonpath='{.status.loadBalancer.ingress[0].ip}' > ilb-ip.txt
    
  4. Kopieren Sie das selbstsignierte TLS-Zertifikat und die Datei mit der IP-Adresse des Istio-ILB-Gateways auf die VM:

    gcloud compute scp cert.pem ilb-ip.txt grpc-istio-ilb-tutorial-client-vm:~
    
    
  5. Stellen Sie über SSH eine Verbindung zu der VM her:

    gcloud compute ssh grpc-istio-ilb-tutorial-client-vm
    
  6. Fragen Sie auf der VM den Compute Engine-Metadatenserver nach der Projekt-ID ab und speichern Sie sie in der Umgebungsvariablen GOOGLE_CLOUD_PROJECT.

    GOOGLE_CLOUD_PROJECT=$(curl -sH "Metadata-Flavor: Google" \
        http://metadata.google.internal/computeMetadata/v1/project/project-id)
    

    In Cloud Shell ist die Umgebungsvariable GOOGLE_CLOUD_PROJECT standardmäßig festgelegt, bei VMs ist das jedoch nicht der Fall.

  7. Rufen Sie Container Registry-Anmeldedaten zur Verwendung mit dem Befehl docker ab:

    docker-credential-gcr configure-docker
    
  8. Führen Sie das Container-Image des gRPC-Clients aus:

    docker run --rm -v $(pwd)/cert.pem:/data/cert.pem \
        --add-host grpc.example.com:$(cat ilb-ip.txt) \
        gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-client \
        --address=grpc.example.com:443
    

    Die Ausgabe sieht etwa so aus:

    2019/03/27 15:12:53 Hello world from greeter-844cffd75-ffccl
    2019/03/27 15:12:53 Hello world from greeter-844cffd75-zww6h
    2019/03/27 15:12:53 Hello world from greeter-844cffd75-7hpcb
    2019/03/27 15:12:53 Hello world from greeter-844cffd75-ffccl
    2019/03/27 15:12:53 Hello world from greeter-844cffd75-zww6h
    2019/03/27 15:12:53 Hello world from greeter-844cffd75-7hpcb
    2019/03/27 15:12:53 Hello world from greeter-844cffd75-ffccl
    2019/03/27 15:12:53 Hello world from greeter-844cffd75-zww6h
    2019/03/27 15:12:53 Hello world from greeter-844cffd75-7hpcb

    Diese Ausgabe zeigt, dass unäre gRPC-Anfragen von den gRPC-Server-Pods (mit dem Namen greeter-*) gemäß der loadBalancer-Konfiguration in der Istio-Zielregel verarbeitet werden – in diesem Fall ROUND_ROBIN.

  9. Verlassen Sie die SSH-Sitzung:

    exit
    

Quellcode untersuchen

Sie können sich den Quellcode der Beispielanwendung ansehen, um die Konfiguration des Load-Balancings besser zu verstehen.

Wenn Sie beispielsweise die vom gRPC-Client ausgegebenen Meldungen verstehen möchten, sehen Sie sich den Go-Quellcode für den Server und den Client an. Wenn der gRPC-Server eine Anfrage verarbeitet, sucht er den Hostnamen und fügt ihn als Antwort-Header namens hostname hinzu. Da der Server in einem Kubernetes-Pod ausgeführt wird, ist der Hostname der Name des Pods.

hostname, err := os.Hostname()
if err != nil {
	log.Printf("Unable to get hostname %v", err)
}
if hostname != "" {
	grpc.SendHeader(ctx, metadata.Pairs("hostname", hostname))
}

Wenn der gRPC-Client eine Antwort vom Server empfängt, erhält er den hostname-Header und gibt ihn an die Console aus.

if len(header["hostname"]) > 0 {
	hostname = header["hostname"][0]
}
log.Printf("%s from %s", r.Message, hostname)

Sehen Sie sich die Istio-Konfiguration für den gRPC-Server an, um die vom gRPC-Client an die Console ausgegebenen Kubernetes-Pod-Namen zu verstehen. Beachten Sie, dass das Objekt DestinationRule ROUND_ROBIN als loadBalancer-Algorithmus angibt. Dieser Algorithmus ist der Grund dafür, dass eingehende Anfragen zwischen den Pods im Kubernetes-Deployment rotieren.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: greeter
spec:
  host: greeter
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
    tls:
      mode: ISTIO_MUTUAL

Fehlerbehebung

Wenn Sie Probleme mit dieser Anleitung haben, empfehlen wir Ihnen, die folgenden Dokumente zu lesen:

Bereinigen

So vermeiden Sie, dass Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen in Rechnung gestellt werden:

  1. Löschen Sie den GKE-Cluster in Cloud Shell:

    gcloud container clusters delete grpc-istio-ilb-tutorial --quiet --async
    
  2. Löschen Sie die Images in Container Registry:

    gcloud container images delete gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-client \
        --force-delete-tags --quiet
    gcloud container images delete gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-server \
        --force-delete-tags --quiet
    
  3. Löschen Sie die Compute Engine-Instanz:

    gcloud compute instances delete grpc-istio-ilb-tutorial-client-vm --quiet
    

Weitere Informationen