En este tutorial se muestra cómo exponer varios servicios de gRPC desplegados en Google Kubernetes Engine (GKE) en una única dirección IP externa mediante un balanceador de carga de red de pases externo y Envoy Proxy. En el tutorial se destacan algunas de las funciones avanzadas que proporciona Envoy para gRPC.
Introducción
gRPC es un framework de RPC de código abierto e independiente del lenguaje basado en HTTP/2 que usa búferes de protocolo para una representación eficiente en la conexión y una serialización rápida. Inspirado en Stubby, el framework interno de RPC de Google, gRPC permite la comunicación de baja latencia entre microservicios y entre clientes móviles y APIs.
gRPC se ejecuta a través de HTTP/2 y ofrece varias ventajas con respecto a HTTP/1.1, como la codificación binaria eficiente, la multiplexación de solicitudes y respuestas a través de una sola conexión y el control de flujo automático. gRPC también ofrece varias opciones para el balanceo de carga. Este tutorial se centra en situaciones en las que los clientes no son de confianza, como los clientes móviles y los clientes que se ejecutan fuera del límite de confianza del proveedor de servicios. De las opciones de balanceo de carga que ofrece gRPC, en este tutorial se utiliza el balanceo de carga basado en proxy.
En el tutorial, implementas un servicio de Kubernetes de TYPE=LoadBalancer
, que se expone como un balanceador de carga de red de paso a través externo de capa de transporte (capa 4) enGoogle Cloud. Este servicio proporciona una única dirección IP pública y transfiere las conexiones TCP directamente a los backends configurados. En el tutorial, el backend es un Deployment de Kubernetes de 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 tutorial, lo usarás para finalizar las conexiones TLS y enrutar el tráfico de gRPC al servicio de Kubernetes adecuado. En comparación con otras soluciones de capa de aplicación, como Kubernetes Ingress, el uso directo de Envoy ofrece varias opciones de personalización, como las siguientes:
- Descubrimiento de servicios
- Algoritmos de balanceo de carga
- Transformar solicitudes y respuestas (por ejemplo, a JSON o gRPC-Web)
- Autenticar solicitudes validando tokens JWT
- Comprobaciones del estado de gRPC
Si combinas un balanceador de carga de red con paso a través externo con Envoy, puedes configurar un endpoint (dirección IP externa) que reenvíe el tráfico a un conjunto de instancias de Envoy que se ejecuten en un clúster de Google Kubernetes Engine. Estas instancias usan información de la capa de aplicación para proxy las solicitudes a diferentes servicios gRPC que se ejecutan en el clúster. Las instancias de Envoy usan el DNS del clúster para identificar y balancear la carga de las solicitudes gRPC entrantes a los pods en buen estado y en ejecución de cada servicio. Esto significa que el tráfico se balancea entre los pods por solicitud RPC en lugar de por conexión TCP del cliente.
Arquitectura
En este tutorial, desplegará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 único endpoint:
Un balanceador de carga de red de paso a través externo acepta solicitudes entrantes de Internet (por ejemplo, de clientes móviles o consumidores de servicios que no pertenecen a tu empresa). El balanceador de carga de red de paso a través externo realiza las siguientes tareas:
- Balancea la carga de las conexiones entrantes a los nodos del grupo. El tráfico se reenvía al servicio 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 comprobaciones del estado HTTP en los nodos del clúster.
Envoy realiza las siguientes tareas:
- Finaliza las conexiones TLS.
- Descubre los pods que ejecutan los servicios gRPC consultando el servicio DNS del clúster interno.
- Enruta y balancea la carga del tráfico a los pods del servicio gRPC.
- Realiza comprobaciones del estado de los servicios gRPC según el protocolo de comprobación del estado de gRPC.
- Expone un endpoint para comprobar el estado de las instancias de Envoy mediante el balanceador de carga de red de paso a través externo.
Los servicios de gRPC (echo-grpc
y reverse-grpc
) se exponen como servicios sin encabezado de Kubernetes.
Esto significa que no se asigna ninguna dirección clusterIP
y que el proxy de red de Kubernetes no equilibra la carga 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 de los pods a partir de esta entrada DNS y equilibra la carga entre ellos según la política configurada en Envoy.
En el siguiente diagrama se muestran los objetos de Kubernetes que se usan en este tutorial:
Costes
En este documento, se utilizan los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costes basada en el uso previsto,
utiliza la calculadora de precios.
Cuando termines las tareas que se describen en este documento, puedes evitar que se te siga facturando eliminando los recursos que has creado. Para obtener más información, consulta la sección Limpiar.
Antes de empezar
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator
(
roles/resourcemanager.projectCreator
), which contains theresourcemanager.projects.create
permission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Preparar el entorno
En Cloud Shell, define el proyecto de Google Cloud que quieras usar en este tutorial:
gcloud config set project PROJECT_ID
Sustituye
PROJECT_ID
por elGoogle Cloud ID de tu proyecto.Habilita las APIs 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 tus servicios gRPC:
gcloud container clusters create envoy-grpc-tutorial \ --enable-ip-alias \ --release-channel rapid \ --scopes cloud-platform \ --workload-pool PROJECT_ID.svc.id.goog \ --location us-central1-f
En este tutorial se usa la zona
us-central1-f
. Puedes usar una zona o región diferente.Verifica que se ha configurado el contexto
kubectl
enumerando los nodos de tu clúster:kubectl get nodes --output name
El resultado debe ser similar a este:
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
Crear el repositorio de Artifact Registry
En Cloud Shell, crea un repositorio para almacenar imágenes de contenedor:
gcloud artifacts repositories create envoy-grpc-tutorial-images \ --repository-format docker \ --location us-central1
Crea el repositorio en la misma región que el clúster de GKE para optimizar la latencia y el ancho de banda de la red cuando los nodos extraigan imágenes de contenedor.
Asigna el rol Lector de Artifact Registry al repositorio a la cuenta de servicio de Google que usan las VMs de 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
Añade una entrada de asistente 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 del asistente de credenciales permite que las herramientas de imágenes de contenedor que se ejecutan en Cloud Shell se autentiquen en la ubicación del repositorio de Artifact Registry para extraer e insertar imágenes.
Desplegar los servicios gRPC
Para dirigir el tráfico a varios servicios gRPC que se encuentran detrás de un balanceador de carga, implementa dos servicios gRPC de ejemplo:
echo-grpc
yreverse-grpc
. Ambos servicios exponen un método unario que toma una cadena en el campo de solicitudcontent
.echo-grpc
responde con el contenido sin modificar, mientras quereverse-grpc
responde con la cadena de contenido invertida.En Cloud Shell, clona el repositorio que contiene los servicios 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 un certificado TLS con firma automática y una clave privada:
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 esta clave privada cuando finaliza las conexiones TLS.
Crea las imágenes de contenedor de las aplicaciones de ejemplo
echo-grpc
yreverse-grpc
, sube las imágenes a Artifact Registry y despliega las aplicaciones en el clúster de GKE con 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.
Despliega Envoy en el clúster de GKE con Skaffold:
skaffold run \ --digest-source=none \ --module=envoy \ --skip-tests
Comprueba que haya dos pods listos para cada implementación:
kubectl get deployments
La salida tiene un aspecto similar al siguiente. Los valores de
READY
deben ser2/2
en 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 servicios de Kubernetes:kubectl get services --selector skaffold.dev/run-id
La salida tiene un aspecto similar al siguiente. Tanto
echo-grpc
comoreverse-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
Probar los servicios gRPC
Para probar los servicios, utiliza la herramienta de línea de comandos
grpcurl
.En Cloud Shell, instala
grpcurl
:go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
Obtén la dirección IP externa del servicio de Kubernetes
envoy
y guárdala en una variable de entorno:EXTERNAL_IP=$(kubectl get service envoy \ --output=jsonpath='{.status.loadBalancer.ingress[0].ip}')
Envía una solicitud a la aplicación de ejemplo de
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
El resultado debe ser similar a este:
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 ha gestionado 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 gRPC inverso:
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 debe ser similar a este:
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 entender 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 dirigen las solicitudes entrantes a las aplicaciones de ejemploecho-grpc
yreverse-grpc
.Las aplicaciones de ejemplo se definen como clústeres de Envoy.
Los campos
type: STRICT_DNS
ylb_policy: ROUND_ROBIN
de la definición del clúster especifican que Envoy realiza búsquedas de DNS del nombre de host especificado en el campoaddress
y equilibra la carga entre las direcciones IP de la respuesta a la búsqueda de DNS. La respuesta contiene varias direcciones IP porque los objetos de servicio de Kubernetes que definen las aplicaciones de ejemplo especifican servicios sin encabezado.El campo
http2_protocol_options
especifica que Envoy usa el protocolo HTTP/2 en las aplicaciones de muestra.El campo
grpc_health_check
de la secciónhealth_checks
especifica que Envoy usa el protocolo de comprobación de estado de gRPC para determinar el estado de las aplicaciones de ejemplo.Solucionar problemas
Si tienes problemas con este tutorial, te recomendamos que consultes estos documentos:
- Solucionar problemas de clústeres de Kubernetes
- Solucionar problemas de aplicaciones desplegadas en Kubernetes
También puedes consultar 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 desde 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 este resultado en la consola:
Forwarding from 127.0.0.1:8080 -> 8090
En Cloud Shell, haz clic en el botón Vista previa web y selecciona Obtener vista previa en el puerto 8080. Se abrirá una nueva ventana del navegador con la interfaz de administración.
Cuando hayas terminado, vuelve a Cloud Shell y pulsa
Control+C
para finalizar el reenvío de puertos.
Formas alternativas de enrutar el tráfico de gRPC
Puedes modificar esta solución de varias formas para adaptarla a tu entorno.
Balanceadores de carga de capa de aplicación alternativos
Algunas de las funciones de la capa de aplicación que ofrece Envoy también pueden proporcionarse mediante otras soluciones de balanceo de carga:
Puedes usar un balanceador de carga de aplicación externo global o un balanceador de carga de aplicación externo regional en lugar de un balanceador de carga de red con paso a través externo y Envoy autogestionado. Usar un balanceador de carga de aplicaciones externo ofrece varias ventajas en comparación con un balanceador de carga de red de transferencia externo, como funciones avanzadas de gestión del tráfico, certificados TLS gestionados e integración con otros productos, como Cloud CDN, Google Cloud Armor e IAP. Google Cloud
Te recomendamos que uses un balanceador de carga de aplicación externo global o regional si las funciones de gestión del tráfico que ofrecen se ajustan a tus casos prácticos y si no necesitas compatibilidad con la autenticación basada en certificados de cliente, también conocida como autenticación TLS mutua (mTLS). Para obtener más información, consulte los documentos siguientes:
Si utilizas Cloud Service Mesh o Istio, puedes usar sus funciones para enrutar y balancear la carga del tráfico de gRPC. Tanto Cloud Service Mesh como Istio proporcionan una puerta de enlace de entrada que se implementa como un balanceador de carga de red de transferencia externo con un backend de Envoy, de forma similar a la arquitectura de este tutorial. La principal diferencia es que Envoy se configura a través de los objetos de enrutamiento del tráfico de Istio.
Para que los servicios de ejemplo de este tutorial se puedan enrutar en la malla de servicios de Cloud o en la de Istio, debes quitar la línea
clusterIP: None
de los manifiestos de servicio de Kubernetes (echo-service.yaml
yreverse-service.yaml
). Esto significa que debes usar las funciones de descubrimiento de servicios y de balanceo de carga de la malla de servicios de Cloud o de Istio en lugar de las funciones similares de Envoy.Si ya usas Cloud Service Mesh o Istio, te recomendamos que uses la puerta de enlace de entrada para enrutar a tus servicios gRPC.
Puedes usar NGINX en lugar de Envoy, ya sea como un Deployment o con el controlador de entradas NGINX para Kubernetes. En este tutorial se usa Envoy porque proporciona funciones de gRPC más avanzadas, como la compatibilidad con el protocolo de comprobación de estado de gRPC.
Conectividad de red VPC interna
Si quieres exponer los servicios fuera de tu clúster de GKE, pero solo dentro de tu red de VPC, puedes usar un balanceador de carga de red de transferencia interno o un balanceador de carga de aplicaciones interno.
Para usar un balanceador de carga de red de paso a través interno en lugar de uno externo, añade la anotación
cloud.google.com/load-balancer-type: "Internal"
al manifiestoenvoy-service.yaml
.Para usar un balanceador de carga de aplicación interno, consulta la documentación sobre cómo configurar objetos Ingress para balanceadores de carga de aplicación internos.
Limpieza
Cuando hayas terminado el tutorial, puedes eliminar los recursos que has creado para que dejen de usar cuota y generar cargos. En las siguientes secciones se explica cómo eliminar o desactivar dichos recursos.
Eliminar 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.
Eliminar los recursos
Si quieres conservar el Google Cloud proyecto que has usado en este tutorial, elimina los recursos:
En Cloud Shell, elimina la clonación del repositorio de Git local:
cd ; rm -rf kubernetes-engine-samples/networking/grpc-gke-nlb-tutorial/
Elimina el clúster de GKE:
gcloud container clusters delete envoy-grpc-tutorial \ --location us-central1-f --async --quiet
Elimina el repositorio en Artifact Registry:
gcloud artifacts repositories delete envoy-grpc-tutorial-images \ --location us-central1 --async --quiet
Siguientes pasos
- Consulta información sobre las redes de GKE.
- Consulta ejemplos sobre cómo exponer servicios gRPC a clientes dentro de tu clúster de Kubernetes.
Consulta las opciones de balanceo de carga de gRPC.
Consulta arquitecturas de referencia, diagramas y prácticas recomendadas sobre Google Cloud. Consulta nuestro Centro de arquitectura de Cloud.