En este instructivo, se explica cómo exponer varios servicios de gRPC implementados en Google Kubernetes Engine (GKE) en una sola dirección IP externa mediante el balanceador de cargas de red de transferencia externo y el proxy Envoy. En este instructivo, se destacan algunas de las funciones avanzadas que Envoy proporciona a gRPC.
Introducción
gRPC es un framework de RPC independiente del lenguaje y de código abierto basado en HTTP/2 que usa búferes de protocolo para una representación en línea eficiente y una serialización rápida. gRPC, inspirado en Stubby, el framework interno de Google RPC, permite la comunicación de baja latencia entre microservicios y entre API y clientes móviles.
gRPC se ejecuta en HTTP/2 y ofrece varias ventajas respecto de HTTP/1.1, como codificación binaria eficiente, multiplexación de solicitudes y respuestas en una sola conexión, y control de flujo automático. gRPC también ofrece varias opciones para el balanceo de cargas. En este instructivo, nos enfocaremos en situaciones en las que los clientes no son de confianza, como clientes móviles y clientes que se ejecutan fuera del límite de confianza del proveedor de servicios. De las opciones de balanceo de cargas que proporciona gRPC, en este instructivo, se usa el balanceo de cargas basado en proxy.
En el instructivo, debes implementar un Service de Kubernetes de TYPE=LoadBalancer
, que se expone como balanceador de cargas de red de transferencia externo de la capa de transporte (capa 4) en Google Cloud. Este servicio proporciona una única dirección IP pública y pasa las conexiones TCP directamente a los backends configurados. En el instructivo, el backend es una implementación de Kubernetes de las instancias de Envoy.
Envoy es un proxy de capa de aplicación (capa 7) de código abierto que ofrece muchas funciones avanzadas. En este instructivo, lo usarás para finalizar las conexiones TLS y enrutar el tráfico de gRPC al Service de Kubernetes correspondiente. En comparación con otras soluciones de capa de aplicación, como Ingress de Kubernetes, el uso de Envoy proporciona varias opciones de personalización, como las siguientes:
- Descubrimiento de servicios
- Algoritmos de balanceo de cargas
- Transformación de solicitudes y respuestas (por ejemplo, a JSON o gRPC-Web)
- Autenticación de solicitudes mediante la validación de tokens JWT
- Verificaciones de estado de gRPC
Si combinas un balanceador de cargas de red de transferencia externo con Envoy, puedes configurar un extremo (dirección IP externa) que reenvíe tráfico a un conjunto de instancias de Envoy que se ejecutan en un clúster de Google Kubernetes Engine. Estas instancias usan la información de la capa de aplicación para enviar solicitudes de proxy a diferentes servicios de gRPC que se ejecutan en el clúster. Las instancias de Envoy usan DNS del clúster a fin de identificar y balancear las cargas de las solicitudes de gRPC entrantes a los Pods en buen estado y en ejecución para cada servicio. Esto significa que las cargas del tráfico se balancean a los Pods por solicitud de RPC en lugar de por conexión TCP del cliente.
Arquitectura
En este instructivo, implementarás dos servicios de gRPC, echo-grpc
y reverse-grpc
, en un clúster de Google Kubernetes Engine (GKE) y los expondrás a Internet en una dirección IP pública. En el siguiente diagrama, se muestra la arquitectura para exponer estos dos servicios a través de un extremo único:
Un balanceador de cargas de red de transferencia externo acepta solicitudes entrantes de Internet (por ejemplo, de clientes de dispositivos móviles o de usuarios de servicios ajenos a su empresa). El balanceador de cargas de red de transferencia externo realiza las siguientes tareas:
- Balancea las cargas de las conexiones entrantes a los nodos en el grupo. El tráfico se reenvía al Service de Kubernetes
envoy
, que se expone en todos los nodos del clúster. El proxy de red de Kubernetes reenvía estas conexiones a los Pods que ejecutan Envoy. - Realiza verificaciones de estado HTTP en los nodos del clúster.
Envoy realiza las siguientes tareas:
- Finaliza las conexiones TLS.
- Descubre los Pods que ejecutan los servicios de gRPC mediante una consulta al servicio DNS del clúster interno.
- Enruta y balancea las cargas del tráfico a los Pods de servicio de gRPC.
- Realiza verificaciones de estado de los servicios de gRPC de acuerdo con el Protocolo de verificación de estado de gRPC.
- Expone un extremo para la verificación de estado de las instancias de Envoy balanceador de cargas de red de transferencia externo.
Los servicios de gRPC (echo-grpc
y reverse-grpc
) se exponen como Servicios sin interfaz gráfica de Kubernetes.
Esto significa que no se asigna ninguna dirección clusterIP
, y que el proxy de red de Kubernetes no balancea las cargas del tráfico a los Pods. En su lugar, se crea un registro A de DNS que contiene las direcciones IP del Pod en el servicio DNS del clúster. Envoy descubre las direcciones IP del Pod de esta entrada de DNS y balancea las cargas entre ellas de acuerdo con la política configurada en Envoy.
En el siguiente diagrama, se muestran los objetos de Kubernetes involucrados en este instructivo:
Costos
En este documento, usarás los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.
Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.
Antes de comenzar
-
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.
Prepare el entorno
En Cloud Shell, configura el proyecto de Google Cloud que deseas usar para este instructivo:
gcloud config set project PROJECT_ID
Reemplaza
PROJECT_ID
con tu ID del proyecto de Google Cloud.Habilita las APIs de Artifact Registry y GKE:
gcloud services enable artifactregistry.googleapis.com \ container.googleapis.com
Crea el clúster de GKE
En Cloud Shell, crea un clúster de GKE para ejecutar los servicios de gRPC:
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
En este instructivo, se usa la zona
us-central1-f
. Puedes usar una zona o región diferente.Genera una lista de los nodos en el clúster para verificar que se haya configurado el contexto
kubectl
:kubectl get nodes --output name
El resultado es similar al siguiente:
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
Crea el repositorio de Artifact Registry
En Cloud Shell, crea un repositorio nuevo para almacenar imágenes de contenedor:
gcloud artifacts repositories create envoy-grpc-tutorial-images \ --repository-format docker \ --location us-central1
El repositorio se crea en la misma región que el clúster de GKE para ayudar a optimizar la latencia y el ancho de banda de la red cuando los nodos extraen imágenes de contenedor.
Otorga el rol Lector de Artifact Registry en el repositorio a la cuenta de servicio de Google que usan las VMs del nodo del clúster de GKE:
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
Agrega una entrada auxiliar de credenciales para el nombre de host del repositorio al archivo de configuración de Docker en tu directorio principal de Cloud Shell:
gcloud auth configure-docker us-central1-docker.pkg.dev
La entrada auxiliar de credenciales permite que las herramientas de imagen de contenedor que se ejecutan en Cloud Shell se autentiquen en la ubicación del repositorio de Artifact Registry para extraer y enviar imágenes.
Implementa los servicios de gRPC
Para enrutar el tráfico a varios servicios de gRPC detrás de un balanceador de cargas, implementa dos servicios de gRPC de muestra: echo-grpc
y reverse-grpc
. Ambos servicios exponen un método unario que toma una string en el campo de la solicitud content
. echo-grpc
responde con el contenido sin alteraciones, mientras que reverse-grpc
responde con la string de contenido invertida.
En Cloud Shell, clona el repositorio que contiene los servicios de gRPC y cambia al directorio del repositorio:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples cd kubernetes-engine-samples/networking/grpc-gke-nlb-tutorial/
Crea una clave privada y un certificado TLS autofirmado:
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'
Crea un secreto de Kubernetes llamado
envoy-certs
que contenga el certificado TLS autofirmado y la clave privada:kubectl create secret tls envoy-certs \ --key privkey.pem --cert cert.pem \ --dry-run=client --output yaml | kubectl apply --filename -
Envoy usa este certificado TLS y la clave privada cuando finaliza las conexiones TLS.
Compila las imágenes del contenedor para las apps de muestra
echo-grpc
yreverse-grpc
, envía las imágenes a Artifact Registry e implementa las apps en el clúster de GKE mediante Skaffold:skaffold run \ --default-repo=us-central1-docker.pkg.dev/PROJECT_ID/envoy-grpc-tutorial-images \ --module=echo-grpc,reverse-grpc \ --skip-tests
Skaffold es una herramienta de código abierto de Google que automatiza los flujos de trabajo para desarrollar, compilar, enviar e implementar aplicaciones como contenedores.
Implementa Envoy en el clúster de GKE con Skaffold:
skaffold run \ --digest-source=none \ --module=envoy \ --skip-tests
Verifica que haya dos Pods listos para cada implementación:
kubectl get deployments
El resultado es similar al siguiente. Los valores de
READY
deben ser2/2
para todas las implementaciones.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
Verifica que
echo-grpc
,envoy
yreverse-grpc
existan como Services de Kubernetes:kubectl get services --selector skaffold.dev/run-id
El resultado es similar al siguiente.
echo-grpc
yreverse-grpc
deben tenerTYPE=ClusterIP
yCLUSTER-IP=None
.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
Prueba los servicios de gRPC
Para probar los servicios, usa la herramienta de línea de comandos de grpcurl
.
En Cloud Shell, instala
grpcurl
:go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
Obtén la dirección IP externa del Service de Kubernetes
envoy
y almacénala en una variable de entorno:EXTERNAL_IP=$(kubectl get service envoy \ --output=jsonpath='{.status.loadBalancer.ingress[0].ip}')
Envía una solicitud a la app de muestra
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
La salida es similar a la siguiente:
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
El encabezado de respuesta
hostname
muestra el nombre del Podecho-grpc
que controló la solicitud. Si repites el comando varias veces, deberías ver dos valores diferentes para el encabezado de respuestahostname
, que corresponden a los nombres de los Podsecho-grpc
.Verifica el mismo comportamiento con el servicio Reverse de gRPC:
grpcurl -v -d '{"content": "reverse"}' \ -proto reverse-grpc/api/reverse.proto \ -authority grpc.example.com -cacert cert.pem \ $EXTERNAL_IP:443 api.Reverse/Reverse
El resultado es similar al siguiente:
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
Configuración de Envoy
Para comprender mejor la configuración de Envoy, puedes consultar el archivo de configuración envoy/k8s/envoy.yaml
en el repositorio de Git.
En la sección route_config
, se especifica cómo se enrutan las solicitudes entrantes a las apps de muestra echo-grpc
y reverse-grpc
.
Las apps de muestra se definen como clústeres de Envoy.
Los campos type: STRICT_DNS
y lb_policy: ROUND_ROBIN
en la definición del clúster especifican que Envoy realiza búsquedas de DNS del nombre de host especificado en el campo address
y balancea las cargas en las direcciones IP de la respuesta a la búsqueda de DNS. La respuesta contiene varias direcciones IP porque los objetos Service de Kubernetes que definen las apps de muestra especifican servicios sin interfaz gráfica.
En el campo http2_protocol_options
, se especifica que Envoy usa el protocolo HTTP/2 en las apps de muestra.
En el campo grpc_health_check
de la sección health_checks
, se especifica que Envoy usa el protocolo de verificación de estado de gRPC para determinar el estado de las apps de muestra.
Solucionar problemas
Si tienes problemas con este instructivo, te recomendamos que revises los siguientes documentos:
- Solución de problemas de GKE
- Solución de problemas de los clústeres de Kubernetes
- Solución de problemas de aplicaciones implementadas en Kubernetes
También puedes explorar la interfaz de administración de Envoy para diagnosticar problemas con la configuración de Envoy.
Para abrir la interfaz de administración, configura la redirección de puertos de Cloud Shell al puerto
admin
de uno de los Pods de Envoy:kubectl port-forward \ $(kubectl get pods -o name | grep envoy | head -n1) 8080:8090
Espera hasta que veas el siguiente resultado en la consola:
Forwarding from 127.0.0.1:8080 -> 8090
Haz clic en el botón Vista previa en la Web en Cloud Shell y selecciona Vista previa en el puerto 8080 (Preview on port 8080). Se abrirá una nueva ventana del navegador que mostrará la interfaz de administración.
Cuando termines, vuelve a Cloud Shell y presiona
Control+C
para finalizar la redirección de puertos.
Formas alternativas de enrutar el tráfico de gRPC
Puedes modificar esta solución de varias maneras para adaptarla al entorno.
Balanceadores de cargas alternativos de la capa de aplicación
Algunas de las funciones de la capa de aplicación que proporciona Envoy también se pueden proporcionar con las siguientes soluciones de balanceo de cargas:
Puedes usar un Balanceador de cargas de aplicaciones externo global o balanceador de cargas de aplicaciones externo regional en lugar de un balanceador de cargas de red de transferencia externo y Envoy autoadministrado. El uso de un balanceador de cargas de aplicaciones externo proporciona varios beneficios en comparación con un balanceador de cargas de red de transferencia externo, como la capacidad avanzada de administración de tráfico, los certificados TLS administrados y la integración con otros productos de Google Cloud, como Cloud CDN, Google Cloud Armor e IAP.
Recomendamos que uses un balanceador de cargas aplicaciones externo global o un balanceador de cargas de aplicaciones externo regional si las funciones de administración del tráfico que ofrecen satisfacen tus casos de uso y si no necesitas asistencia para la autenticación de clientes basada en certificados, también conocida como autenticación TLS mutua (mTLS). Para obtener más información, consulta los siguientes documentos:
Si usas Cloud Service Mesh o Istio, puedes usar sus funciones para enrutar el tráfico de gRPC y balancear sus cargas. Istio y Cloud Service Mesh proporcionan una puerta de enlace de entrada que se implementa como balanceador de cargas de red de transferencia externo con un backend de Envoy, similar a la arquitectura de este instructivo. La diferencia principal es que Envoy se configura a través de los objetos de enrutamiento de tráfico de Istio.
Para que los servicios de ejemplo de este instructivo se puedan enrutar en Cloud Service Mesh o Istio, debes quitar la línea
clusterIP: None
de los manifiestos del Service de Kubernetes (echo-service.yaml
yreverse-service.yaml
). Esto significa que debes usar la función de descubrimiento de servicios y balanceo de cargas de Cloud Service Mesh o Istio en lugar de la función similar en Envoy.Si ya usas Cloud Service Mesh o Istio, te recomendamos usar la puerta de enlace de entrada para enrutar a los servicios de gRPC.
Puedes usar NGINX en lugar de Envoy, ya sea como una implementación o mediante el Controlador de Ingress de NGINX para Kubernetes. Envoy se usa en este instructivo porque proporciona una función de gRPC más avanzada, como la compatibilidad con el protocolo de verificación de estado de gRPC.
Conectividad de red de VPC interna
Si deseas exponer los servicios fuera del clúster de GKE, pero solo dentro de la red de VPC, puedes usar un balanceador de cargas de red de transferencia interno o un balanceador de cargas de aplicaciones interno.
Para usar un balanceador de cargas de red de transferencia interno en lugar de uno externo, agrega la anotación cloud.google.com/load-balancer-type: "Internal"
al manifiesto envoy-service.yaml
.
Si deseas usar un balanceador de cargas de aplicaciones interno, consulta la documentación sobre cómo configurar Ingress para balanceadores de cargas de aplicaciones internos.
Limpia
Una vez que completes el instructivo, puedes limpiar los recursos que creaste para que dejen de usar la cuota y generar cargos. En las siguientes secciones, se describe cómo borrar o desactivar estos recursos.
Borra el proyecto
- 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.
Borra recursos
Si deseas conservar el proyecto Google Cloud que usaste en este instructivo, borra los recursos individuales:
En Cloud Shell, borra la clonación del repositorio de Git local:
cd ; rm -rf kubernetes-engine-samples/networking/grpc-gke-nlb-tutorial/
Borra el clúster de GKE:
gcloud container clusters delete envoy-grpc-tutorial \ --zone us-central1-f --async --quiet
Borra el repositorio en Artifact Registry:
gcloud artifacts repositories delete envoy-grpc-tutorial-images \ --location us-central1 --async --quiet
¿Qué sigue?
- Lee acerca de las herramientas de redes de GKE.
- Busca ejemplos sobre cómo exponer los servicios de gRPC a los clientes dentro de tu clúster de Kubernetes.
Explora las opciones para el balanceo de cargas de gRPC.
Explora arquitecturas de referencia, diagramas y prácticas recomendadas sobre Google Cloud. Consulta nuestro Cloud Architecture Center.