In dieser Anleitung wird gezeigt, wie mehrere gRPC-Dienste, die in Google Kubernetes Engine (GKE) über eine einzelne externe IP-Adresse bereitgestellt wurden, mithilfe eines externen Passthrough-Network-Load-Balancers und eines Envoy-Proxys verfügbar gemacht werden. Es werden einige der erweiterten Features vorgestellt, die Envoy für gRPC bietet.
Einführung
gRPC ein sprachunabhängiges Open-Source-RPC-Framework auf der Basis von HTTP/2, das für eine effiziente Repräsentation bei der Übertragung und eine schnelle Serialisierung Protokollzwischenspeicher nutzt. Ausgehend von Stubby, dem internen Google-RPC-Framework, ermöglicht gRPC zwischen Mikrodiensten sowie zwischen mobilen Clients und APIs eine Kommunikation mit geringer Latenz.
gRPC wird über HTTP/2 ausgeführt und bietet gegenüber HTTP/1.1 verschiedene Vorteile, z. B. eine effiziente binäre Codierung, Multiplexing von Anfragen und Antworten über eine einzelne Verbindung sowie automatische Ablaufsteuerung. Außerdem bietet gRPC verschiedene Optionen für das Load-Balancing. Der Schwerpunkt dieser Anleitung liegt auf Situationen, in denen Clients nicht vertrauenswürdig sind, z. B. bei mobilen Clients sowie Clients, die außerhalb der Vertrauensgrenze des Dienstanbieters ausgeführt werden. Von den Load-Balancing-Optionen, die gRPC bietet, verwenden Sie in dieser Anleitung das proxybasierte Load-Balancing.
In dieser Anleitung stellen Sie einen Kubernetes-Dienst mit TYPE=LoadBalancer
bereit, der als Transportebene (Ebene 4) für den externen Passthrough-Network-Load-Balancer in Google Cloud verfügbar gemacht wird. Dieser Dienst stellt eine einzelne öffentliche IP-Adresse bereit und leitet TCP-Verbindungen direkt an die konfigurierten Back-Ends weiter. Das Back-End in der Anleitung ist ein Kubernetes-Deployment von Envoy-Instanzen.
Envoy ist ein Open-Source-Proxy für die Anwendungsschicht (Schicht 7), der viele erweiterte Features bietet. In dieser Anleitung werden damit TLS-Verbindungen beendet und gRPC-Traffic an den entsprechenden Kubernetes-Dienst weitergeleitet. Im Vergleich zu anderen Lösungen für die Anwendungsschicht wie Kubernetes Ingress bietet die direkte Verwendung von Envoy mehrere Anpassungsoptionen, wie etwa die folgenden:
- Diensterkennung
- Load-Balancing-Algorithmen
- Umwandlung von Anfragen und Antworten – zum Beispiel in JSON oder gRPC-Web
- Authentifizierung von Anfragen durch Validierung von JWT-Tokens
- gRPC-Systemdiagnosen
Durch Kombination eines externen Passthrough-Network-Load-Balancers mit Envoy können Sie einen Endpunkt einrichten (externe IP-Adresse), der den Traffic an eine Reihe von Envoy-Instanzen weiterleitet, die in einem Google Kubernetes Engine-Cluster ausgeführt werden. Diese Instanzen verwenden dann Informationen aus der Anwendungsschicht, um Anfragen über den Proxy an verschiedene gRPC-Dienste weiterzuleiten, die im Cluster ausgeführt werden. Die Envoy-Instanzen verwenden das Cluster-DNS, um eingehende gRPC-Anfragen an die fehlerfreien, ausgeführten Pods für jeden Dienst zu identifizieren und per Load-Balancing zu verteilen. Das bedeutet, dass der Traffic nach der RPC-Anfrage und nicht nach der TCP-Verbindung vom Client per Load-Balancing an die Pods verteilt wird.
Architektur
In dieser Anleitung stellen Sie zwei gRPC-Dienste, echo-grpc
und reverse-grpc
, in einem Google Kubernetes Engine(GKE)-Cluster bereit und machen sie über eine öffentliche IP-Adresse im Internet verfügbar. Das folgende Diagramm zeigt die Architektur, mit der diese beiden Dienste über einen einzelnen Endpunkt verfügbar gemacht werden:
Ein externer Passthrough-Network-Load-Balancer akzeptiert eingehende Anfragen aus dem Internet (z. B. von mobilen Clients oder Dienstnutzern außerhalb Ihres Unternehmens). Der externe Passthrough-Network-Load-Balancer führt die folgenden Aufgaben aus:
- Load-Balancing für eingehende Verbindungen zu den Knoten im Pool. Der Traffic wird an den Kubernetes-Dienst
envoy
weitergeleitet, der auf allen Knoten im Cluster verfügbar gemacht wird. Der Kubernetes-Netzwerkproxy leitet diese Verbindungen an Pods weiter, auf denen Envoy ausgeführt wird. - HTTP-Systemdiagnosen für die Knoten im Cluster.
Envoy führt die folgenden Aufgaben aus:
- Beenden der TLS-Verbindungen.
- Erkennung von Pods, auf denen die gRPC-Dienste ausgeführt werden, durch Abfrage des internen DNS-Dienstes des Clusters.
- Weiterleitung des Traffics an die gRPC-Dienst-Pods und damit verbundenes Load-Balancing.
- Systemdiagnosen der gRPC-Dienste gemäß gRPC-Systemdiagnoseprotokoll.
- Bereitstellung eines Endpunkts für die Systemdiagnose von Envoy-Instanzen durch den externen Passthrough-Network-Load-Balancer.
Die gRPC-Dienste (echo-grpc
und reverse-grpc
) werden als monitorlose Kubernetes-Dienste verfügbar gemacht.
Das bedeutet, dass keine clusterIP
-Adresse zugewiesen wird und der Kubernetes-Netzwerkproxy kein Load-Balancing für den Traffic zu den Pods vornimmt. Stattdessen wird im DNS-Dienst des Clusters ein DNS-A-Eintrag erstellt, der die IP-Adressen der Pods enthält. Envoy ermittelt aus diesem DNS-Eintrag die IP-Adressen der Pods und nimmt entsprechend der in Envoy konfigurierten Richtlinie das Load-Balancing vor.
Im folgenden Diagramm sind die Kubernetes-Objekte dargestellt, die in dieser Anleitung eine Rolle spielen:
Kosten
In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:
Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen.
Nach Abschluss der in diesem Dokument beschriebenen Aufgaben können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.
Hinweis
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Umgebung vorbereiten
Legen Sie in Cloud Shell das Google Cloud-Projekt fest, das Sie für diese Anleitung verwenden möchten:
gcloud config set project PROJECT_ID
Ersetzen Sie
PROJECT_ID
durch Ihre Google Cloud-Projekt-ID.Aktivieren Sie die Artifact Registry und GKE APIs:
gcloud services enable artifactregistry.googleapis.com \ container.googleapis.com
GKE-Cluster erstellen
Erstellen Sie in Cloud Shell einen GKE-Cluster zum Ausführen Ihrer gRPC-Dienste:
gcloud container clusters create envoy-grpc-tutorial \ --enable-ip-alias \ --release-channel rapid \ --scopes cloud-platform \ --workload-pool PROJECT_ID.svc.id.goog \ --zone us-central1-f
In dieser Anleitung wird die Zone
us-central1-f
verwendet. Sie können eine andere Zone oder Region verwenden.Prüfen Sie, ob der
kubectl
-Kontext eingerichtet wurde, indem Sie die Knoten in Ihrem Cluster auflisten:kubectl get nodes --output name
Die Ausgabe sieht etwa so aus:
node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-1kpt node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-qn92 node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-wf2h
Artifact Registry-Repository erstellen
Erstellen Sie in Cloud Shell ein neues Repository zum Speichern von Container-Images:
gcloud artifacts repositories create envoy-grpc-tutorial-images \ --repository-format docker \ --location us-central1
Das Repository wird in derselben Region wie der GKE-Cluster erstellt, um die Latenz und die Netzwerkbandbreite zu optimieren, wenn Knoten Container-Images abrufen.
Weisen Sie dem Google-Dienstkonto, das von den Knoten-VMs des GKE-Clusters verwendet wird, die Rolle Artifact Registry-Leser im Repository zu:
PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format 'value(projectNumber)') gcloud artifacts repositories add-iam-policy-binding envoy-grpc-tutorial-images \ --location us-central1 \ --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --role roles/artifactregistry.reader
Fügen Sie einen Credential Helper-Eintrag für den Repository-Hostnamen in die Docker-Konfigurationsdatei in Ihrem Cloud Shell-Basisverzeichnis ein:
gcloud auth configure-docker us-central1-docker.pkg.dev
Der Credential Helper-Eintrag ermöglicht die Ausführung von Container-Image-Tools in Cloud Shell beim Speicherort des Artifact Registry-Repositorys, um Images abzurufen und zu übertragen.
gRPC-Dienste bereitstellen
Wenn Sie mit einem Load-Balancer Traffic an mehrere gRPC-Dienste weiterleiten möchten, stellen Sie zwei Beispiel-gRPC-Dienste bereit: echo-grpc
und reverse-grpc
. Von beiden Diensten wird eine unäre Methode verfügbar gemacht, bei der im Feld für die content
-Anfrage ein String verwendet wird. echo-grpc
reagiert mit unverändertem Inhalt, während reverse-grpc
mit dem umgekehrten Inhaltsstring antwortet.
Klonen Sie in Cloud Shell das Repository mit den gRPC-Diensten und wechseln Sie zum Repository-Verzeichnis:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples cd kubernetes-engine-samples/networking/grpc-gke-nlb-tutorial/
Erstellen Sie ein selbst signiertes TLS-Zertifikat und einen privaten Schlüssel:
openssl req -x509 -newkey rsa:4096 -nodes -sha256 -days 365 \ -keyout privkey.pem -out cert.pem -extensions san \ -config \ <(echo "[req]"; echo distinguished_name=req; echo "[san]"; echo subjectAltName=DNS:grpc.example.com ) \ -subj '/CN=grpc.example.com'
Erstellen Sie ein Kubernetes-Secret mit dem Namen
envoy-certs
, das das selbstsignierte TLS-Zertifikat und den privaten Schlüssel enthält:kubectl create secret tls envoy-certs \ --key privkey.pem --cert cert.pem \ --dry-run=client --output yaml | kubectl apply --filename -
Envoy verwendet dieses TLS-Zertifikat und diesen privaten Schlüssel, wenn TLS-Verbindungen beendet werden.
Erstellen Sie die Container-Images für die Beispielanwendungen
echo-grpc
undreverse-grpc
, übertragen Sie die Images per Push in Artifact Registry und stellen Sie die Anwendungen mithilfe von Skaffold im GKE-Cluster bereit:skaffold run \ --default-repo=us-central1-docker.pkg.dev/PROJECT_ID/envoy-grpc-tutorial-images \ --module=echo-grpc,reverse-grpc \ --skip-tests
Skaffold ist ein Open-Source-Tool von Google, das Workflows zum Entwickeln, Erstellen, Übertragen und Bereitstellen von Anwendungen als Container automatisiert.
Stellen Sie Envoy mit Skaffold im GKE-Cluster bereit:
skaffold run \ --digest-source=none \ --module=envoy \ --skip-tests
Überprüfen Sie, ob für jede Bereitstellung zwei Pods bereit sind:
kubectl get deployments
Die Ausgabe sieht ungefähr so aus: Die Werte für
READY
sollten für alle Bereitstellungen2/2
sein.NAME READY UP-TO-DATE AVAILABLE AGE echo-grpc 2/2 2 2 1m envoy 2/2 2 2 1m reverse-grpc 2/2 2 2 1m
Prüfen Sie, ob
echo-grpc
,envoy
undreverse-grpc
als Kubernetes-Dienste vorhanden sind:kubectl get services --selector skaffold.dev/run-id
Die Ausgabe sieht ungefähr so aus: Sowohl für
echo-grpc
als auch fürreverse-grpc
solltenTYPE=ClusterIP
undCLUSTER-IP=None
festgelegt sein.NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo-grpc ClusterIP None <none> 8081/TCP 2m envoy LoadBalancer 10.40.2.203 203.0.113.1 443:31516/TCP 2m reverse-grpc ClusterIP None <none> 8082/TCP 2m
gRPC-Dienste testen
Zum Testen der Dienste verwenden Sie das grpcurl
-Befehlszeilentool.
Installieren Sie
grpcurl
in Cloud Shell:go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
Rufen Sie die externe IP-Adresse des Kubernetes Service
envoy
ab und speichern Sie sie in einer Umgebungsvariablen:EXTERNAL_IP=$(kubectl get service envoy \ --output=jsonpath='{.status.loadBalancer.ingress[0].ip}')
Senden Sie eine Anfrage an die Beispielanwendung
echo-grpc
:grpcurl -v -d '{"content": "echo"}' \ -proto echo-grpc/api/echo.proto \ -authority grpc.example.com -cacert cert.pem \ $EXTERNAL_IP:443 api.Echo/Echo
Die Ausgabe sieht etwa so aus:
Resolved method descriptor: rpc Echo ( .api.EchoRequest ) returns ( .api.EchoResponse ); Request metadata to send: (empty) Response headers received: content-type: application/grpc date: Wed, 02 Jun 2021 07:18:22 GMT hostname: echo-grpc-75947768c9-jkdcw server: envoy x-envoy-upstream-service-time: 3 Response contents: { "content": "echo" } Response trailers received: (empty) Sent 1 request and received 1 response
Im Antwortheader
hostname
ist der Name des Podsecho-grpc
zu sehen, der die Anfrage verarbeitet hat. Wenn Sie den Befehl einige Male wiederholen, sollten Sie zwei unterschiedliche Werte für den Antwortheaderhostname
sehen, die den Namen derecho-grpc
-Pods entsprechen.Überprüfen Sie das entsprechende Verhalten für den Reverse-gRPC-Dienst:
grpcurl -v -d '{"content": "reverse"}' \ -proto reverse-grpc/api/reverse.proto \ -authority grpc.example.com -cacert cert.pem \ $EXTERNAL_IP:443 api.Reverse/Reverse
Die Ausgabe sieht etwa so aus:
Resolved method descriptor: rpc Reverse ( .api.ReverseRequest ) returns ( .api.ReverseResponse ); Request metadata to send: (empty) Response headers received: content-type: application/grpc date: Wed, 02 Jun 2021 07:20:15 GMT hostname: reverse-grpc-5c9b974f54-wlfwt server: envoy x-envoy-upstream-service-time: 1 Response contents: { "content": "esrever" } Response trailers received: (empty) Sent 1 request and received 1 response
Envoy-Konfiguration
Um die Envoy-Konfiguration besser zu verstehen, können Sie sich die Konfigurationsdatei envoy/k8s/envoy.yaml
im Git-Repository ansehen.
Im Abschnitt route_config
wird angegeben, wie eingehende Anfragen an die Beispielanwendungen echo-grpc
und reverse-grpc
weitergeleitet werden.
Die Beispielanwendungen sind als Envoy-Cluster definiert.
Die Felder type: STRICT_DNS
und lb_policy: ROUND_ROBIN
in der Cluster-Definition legen fest, dass Envoy DNS-Lookups des im Feld address
angegebenen Hostnamens durchführt und ein Load-Balancing über die IP-Adressen in der Antwort auf den DNS-Lookup vornimmt. Die Antwort enthält mehrere IP-Adressen, da die Kubernetes-Dienstobjekte, die die Beispielanwendungen definieren, monitorlose Dienste angeben.
Das Feld http2_protocol_options
gibt an, dass Envoy das HTTP/2-Protokoll für die Beispielanwendungen verwendet.
Das Feld grpc_health_check
im Abschnitt health_checks
gibt an, dass Envoy das gRPC-Systemdiagnoseprotokoll verwendet, um den Status der Beispielanwendungen zu ermitteln.
Fehlerbehebung
Wenn Sie Probleme mit dieser Anleitung haben, empfehlen wir Ihnen, die folgenden Dokumente zu lesen:
- Fehlerbehebung für GKE
- Fehlerbehebung für Kubernetes-Cluster
- Fehlerbehebung für Anwendungen, die auf Kubernetes bereitgestellt wurden
Außerdem können Sie die Verwaltungsoberfläche von Envoy nutzen, um Probleme mit der Envoy-Konfiguration zu diagnostizieren.
Stellen Sie zum Öffnen der Verwaltungsoberfläche die Portweiterleitung von Cloud Shell auf den
admin
-Port eines der Envoy-Pods ein:kubectl port-forward \ $(kubectl get pods -o name | grep envoy | head -n1) 8080:8090
Warten Sie, bis Sie in der Console diese Ausgabe sehen:
Forwarding from 127.0.0.1:8080 -> 8090
Klicken Sie in Cloud Shell auf die Schaltfläche Webvorschau und wählen Sie Preview on port 8080 (Vorschau auf Port 8080) aus. Es wird ein neues Browserfenster mit der Verwaltungsoberfläche angezeigt.
Wenn Sie fertig sind, wechseln Sie zu Cloud Shell zurück und drücken Sie
Control+C
, um die Portweiterleitung zu beenden.
Alternative Möglichkeiten zur Weiterleitung von gRPC-Traffic
Diese Lösung können Sie auf verschiedene Arten an Ihre Umgebung anpassen.
Alternative Load-Balancer für die Anwendungsschicht
Einige der Funktionen, die Envoy für die Anwendungsschicht bietet, können auch von anderen Load-Balancing-Lösungen ausgeführt werden:
Sie können einen globalen externen Application Load Balancer oder einen regionalen externen Application Load Balancer anstelle eines externen Passthrough-Network-Load-Balancers und eines selbstverwalteten Envoys verwenden. Die Verwendung eines externen Application Load Balancers bietet im Vergleich zu einem externen Passthrough-Network-Load-Balancer mehrere Vorteile, z. B. erweiterte Funktionen zur Traffic-Verwaltung, verwaltete TLS-Zertifikate und Integration in andere Google Cloud-Produkte wie Cloud CDN, Google Cloud Armor und IAP.
Wir empfehlen die Verwendung eines globalen externen Application Load Balancers oder eines regionalen externen Application Load Balancers, wenn die von ihnen gebotenen Funktionen zur Verwaltung des Traffics Ihren Anwendungsfällen entsprechen und wenn Sie keine Unterstützung für die auf Client-Zertifikaten basierende Authentifizierung, auch bekannt als gegenseitige TLS-Authentifizierung (mTLS), benötigen. Weitere Informationen finden Sie in folgenden Dokumenten:
Wenn Sie Cloud Service Mesh oder Istio verwenden, können Sie die darin enthaltenen Features verwenden, um gRPC-Traffic weiterzuleiten und das zugehörige Load-Balancing vorzunehmen. Sowohl Cloud Service Mesh als auch Istio bieten ein Ingress-Gateway, das als externer Passthrough-Network-Load-Balancer mit einem Envoy-Backend bereitgestellt wird, ähnlich wie bei der Architektur in dieser Anleitung. Der Hauptunterschied besteht darin, dass Envoy über die Traffic-Routingobjekte von Istio konfiguriert wird.
Damit die Beispieldienste in dieser Anleitung im Cloud Service Mesh oder Istio Service Mesh weitergeleitet werden können, müssen Sie die Zeile
clusterIP: None
aus den Kubernetes-Dienstmanifestenecho-service.yaml
undreverse-service.yaml
entfernen. Dies bedeutet, dass die Diensterkennungs- und Load-Balancing-Funktionalität von Cloud Service Mesh oder Istio anstelle der ähnlichen Funktionalität in Envoy verwendet wird.Wenn Sie bereits Cloud Service Mesh oder Istio verwenden, empfehlen wir zur Weiterleitung an Ihre gRPC-Dienste die Verwendung des Ingress-Gateways.
Sie können NGINX anstelle von Envoy verwenden, entweder als Deployment oder mit dem NGINX-Ingress-Controller für Kubernetes. In dieser Anleitung wird Envoy verwendet, da es fortschrittliche gRPC-Funktionen bietet, z. B. Unterstützung für das gRPC-Systemdiagnoseprotokoll.
Interne VPC-Netzwerkverbindung
Wenn Sie die Dienste außerhalb Ihres GKE-Clusters, aber nur innerhalb Ihres VPC-Netzwerks bereitstellen möchten, können Sie entweder einen internen Passthrough-Network-Load-Balancer oder einen internen Application Load Balancer verwenden.
Wenn Sie einen internen Passthrough-Network-Load-Balancer anstelle eines externen Passthrough-Network-Load-Balancers verwenden möchten, fügen Sie dem Manifest envoy-service.yaml
die Annotation cloud.google.com/load-balancer-type: "Internal"
hinzu.
Informationen zur Verwendung eines internen Application Load Balancers finden Sie in der Dokumentation Ingress für interne Application Load Balancer konfigurieren.
Bereinigen
Nachdem Sie die Anleitung abgeschlossen haben, können Sie die erstellten Ressourcen bereinigen, damit sie keine Kontingente mehr nutzen und keine Gebühren mehr anfallen. In den folgenden Abschnitten erfahren Sie, wie Sie diese Ressourcen löschen oder deaktivieren.
Projekt löschen
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Ressourcen löschen
Wenn Sie das in dieser Anleitung verwendete Google Cloud-Projekt beibehalten möchten, löschen Sie die einzelnen Ressourcen:
Löschen Sie den lokalen Git-Repository-Klon in Cloud Shell:
cd ; rm -rf kubernetes-engine-samples/networking/grpc-gke-nlb-tutorial/
Löschen Sie den GKE-Cluster:
gcloud container clusters delete envoy-grpc-tutorial \ --zone us-central1-f --async --quiet
Löschen Sie das Repository in Artifact Registry:
gcloud artifacts repositories delete envoy-grpc-tutorial-images \ --location us-central1 --async --quiet
Nächste Schritte
- GKE-Netzwerk
- Beispiele dafür ansehen, wie gRPC-Dienste in Ihrem Kubernetes-Cluster für Clients verfügbar gemacht werden
Optionen für gRPC-Load-Balancing kennenlernen
Referenzarchitekturen, Diagramme und Best Practices zu Google Cloud kennenlernen. Weitere Informationen zu Cloud Architecture Center