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 balanceo de cargas de red 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 Servicio de Kubernetes de TYPE=LoadBalancer
, que se expone como balanceo de cargas de red 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 SSL/TLS y enrutar el tráfico de gRPC al Servicio 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 el balanceo de cargas de red mediante 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 GKE. 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.
Costos
En este instructivo, se usan 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. Es posible que los usuarios nuevos de Google Cloud sean aptos para obtener una prueba gratuita.
Cuando finalices este instructivo, podrás borrar los recursos creados para evitar que se te siga facturando. Para obtener más información, consulta cómo hacer una limpieza.
Antes de comenzar
- Accede a tu Cuenta de Google.
Si todavía no tienes una cuenta, regístrate para obtener una nueva.
-
En la página del selector de proyectos de Google Cloud Console, selecciona o crea un proyecto de Google Cloud.
-
Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Descubre cómo confirmar que tienes habilitada la facturación en un proyecto.
- Habilita las API de Cloud Build, Container Registry, and Container Analysis.
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:
El balanceo de cargas de red acepta solicitudes entrantes de Internet (por ejemplo, de clientes móviles o consumidores de servicios externos). El balanceo de cargas de red realiza las siguientes tareas:
- Balancea las cargas de las conexiones entrantes a los nodos trabajadores en el grupo. El tráfico se reenvía al Servicio de Kubernetes
envoy
, que se expone en todos los nodos trabajadores 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 trabajadores del clúster.
Envoy realiza las siguientes tareas:
- Finaliza las conexiones SSL/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 mediante el balanceo de cargas de red.
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:
Inicializa el entorno
En esta sección, debes establecer variables de entorno que se usarán más adelante en el instructivo.
Abre Cloud Shell:
Usa Cloud Shell para ejecutar todos los comandos de este instructivo.
En Cloud Shell, muestra el ID del proyecto actual:
gcloud config list --format 'value(core.project)'
Si mediante el comando no se muestra el ID del proyecto que seleccionaste, configura Cloud Shell para usar tu proyecto y reemplaza project-id por el nombre de tu proyecto:
gcloud config set project project-id
Define las variables de entorno para la región y la zona que deseas usar en este instructivo:
REGION=us-central1 ZONE=$REGION-b
En este instructivo, se usa la región
us-central1
y la zonaus-central1-b
. Sin embargo, puedes cambiar la región y la zona para que se adapten a tus necesidades.
Crea el clúster de GKE
Crea un clúster de GKE para ejecutar los servicios de gRPC:
gcloud container clusters create grpc-cluster --zone $ZONE
Genera una lista de los nodos trabajados en el clúster para verificar que se haya configurado el contexto
kubectl
:kubectl get nodes -o name
El resultado es similar al siguiente:
node/gke-grpc-cluster-default-pool-c9a3c791-1kpt node/gke-grpc-cluster-default-pool-c9a3c791-qn92 node/gke-grpc-cluster-default-pool-c9a3c791-wf2h
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 simples: echo-grpc
y reverse-grpc
. Ambos servicios exponen un método unario que toma una string en el campo de la solicitud de contenido. echo-grpc
responde con el contenido sin alteraciones, mientras que reverse-grpc
responde con la string de contenido invertida.
Clona el repositorio que contiene los servicios de gRPC y cambia al directorio de trabajo:
git clone https://github.com/GoogleCloudPlatform/grpc-gke-nlb-tutorial cd grpc-gke-nlb-tutorial
Mediante Cloud Build, crea las imágenes del contenedor para los servicios de gRPC de Echo y Reverse, y almacénalas en Container Registry:
gcloud builds submit -t gcr.io/$GOOGLE_CLOUD_PROJECT/echo-grpc echo-grpc gcloud builds submit -t gcr.io/$GOOGLE_CLOUD_PROJECT/reverse-grpc reverse-grpc
Verifica que las imágenes existan en Container Registry:
gcloud container images list --repository gcr.io/$GOOGLE_CLOUD_PROJECT
El resultado es similar al siguiente:
NAME gcr.io/grpc-gke-nlb-tutorial/echo-grpc gcr.io/grpc-gke-nlb-tutorial/reverse-grpc
Crea implementaciones de Kubernetes para
echo-grpc
yreverse-grpc
:sed s/GOOGLE_CLOUD_PROJECT/$GOOGLE_CLOUD_PROJECT/ \ k8s/echo-deployment.yaml | kubectl apply -f - sed s/GOOGLE_CLOUD_PROJECT/$GOOGLE_CLOUD_PROJECT/ \ k8s/reverse-deployment.yaml | kubectl apply -f -
Verifica que haya dos Pods disponibles para cada implementación:
kubectl get deployments
El resultado es similar al siguiente. Los valores de
DESIRED
,CURRENT
,UP-TO-DATE
yAVAILABLE
deben ser2
para ambas implementaciones.NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE echo-grpc 2 2 2 2 1m reverse-grpc 2 2 2 2 1m
Crea Servicios sin interfaz gráfica de Kubernetes para
echo-grpc
yreverse-grpc
. Estos comandos crean registros A de DNS en el servicio de DNS del clúster, pero no asignan direcciones IP virtuales.kubectl apply -f k8s/echo-service.yaml kubectl apply -f k8s/reverse-service.yaml
Comprueba que
echo-grpc
yreverse-grpc
existan como Servicios de Kubernetes:kubectl get services
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 35s kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 47m reverse-grpc ClusterIP None <none> 8082/TCP 21s
Configura el balanceo de cargas de red
Crea un Servicio de Kubernetes de tipo
LoadBalancer
en el clúster:kubectl apply -f k8s/envoy-service.yaml
Mediante este comando, se aprovisionan los recursos necesarios para el balanceo de cargas de red y se asigna una dirección IP pública efímera. La asignación de la dirección IP pública puede tomar unos minutos.
Ejecuta el siguiente comando y espera hasta que el valor de
EXTERNAL-IP
para el servicioenvoy
cambie de<pending>
a una dirección IP pública:kubectl get services envoy --watch
Presiona
Control+C
para dejar de esperar.
Crea un certificado SSL/TLS autofirmado
Envoy usa un certificado y una clave cuando finaliza las conexiones SSL/TLS. Para comenzar, crea un certificado SSL/TLS autofirmado.
Crea una variable de entorno para almacenar la dirección IP pública del servicio de Envoy que creaste en la sección anterior:
EXTERNAL_IP=$(kubectl get service envoy -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
Crea una clave y un certificado SSL/TLS autofirmado:
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \ -keyout privkey.pem -out cert.pem -subj "/CN=$EXTERNAL_IP"
Crea un secreto TLS de Kubernetes llamado
envoy-certs
que contenga la clave y el certificado SSL/TLS autofirmado:kubectl create secret tls envoy-certs \ --key privkey.pem --cert cert.pem \ --dry-run -o yaml | kubectl apply -f -
Implementa Envoy
Crea un ConfigMap de Kubernetes para almacenar el archivo de configuración de Envoy (
envoy.yaml
):kubectl apply -f k8s/envoy-configmap.yaml
Crea una implementación de Kubernetes para Envoy:
kubectl apply -f k8s/envoy-deployment.yaml
Verifica que haya dos Pods
envoy
en ejecución:kubectl get deployment envoy
El resultado es similar al siguiente:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE envoy 2 2 2 2 1m
Ya estás listo para probar los servicios de gRPC.
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 get github.com/fullstorydev/grpcurl go install github.com/fullstorydev/grpcurl/cmd/grpcurl
Envía una solicitud al servicio Echo de gRPC:
grpcurl -d '{"content": "echo"}' -proto echo-grpc/api/echo.proto \ -insecure -v $EXTERNAL_IP:443 api.Echo/Echo
El resultado es similar al 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, 27 Feb 2019 04:40:19 GMT hostname: echo-grpc-5c4f59c578-wcsvr server: envoy x-envoy-upstream-service-time: 0 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 -d '{"content": "reverse"}' -proto reverse-grpc/api/reverse.proto \ -insecure -v $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, 27 Feb 2019 04:45:56 GMT hostname: reverse-grpc-74cdc4849f-tvsfb server: envoy x-envoy-upstream-service-time: 2 Response contents: { "content": "esrever" } Response trailers received: (empty) Sent 1 request and received 1 response
Soluciona 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 configurar el balanceo de cargas de HTTP(S) mediante un objeto Ingress de Kubernetes y usarlo en lugar del balanceo de cargas de red y Envoy. El uso del balanceo de cargas de HTTP(S) proporciona varios beneficios en comparación con el balanceo de cargas de red, como los certificados SSL/TLS administrados y la integración con otros productos de Google Cloud, como IAP y Cloud CDN.
Recomendamos que uses el balanceo de cargas de HTTP(S) cuando no necesites asistencia para realizar las siguientes tareas:
- Verificaciones de estado de gRPC
- Control detallado del algoritmo de balanceo de cargas
- Exposición de más de 50 servicios
Para obtener más información sobre cómo implementar el balanceo de cargas de HTTP(S) mediante un servicio de gRPC de muestra, consulta la Documentación de Google Kubernetes Engine sobre Ingress y el Instructivo de balanceo de cargas del Ingress de gRPC de GKE en GitHub.
Si usas Istio, puedes usar sus funciones para enrutar y balancear la carga del tráfico de gRPC. La puerta de enlace de Ingress de Istio se implementa como balanceo de cargas de red mediante un backend de Envoy, similar a la arquitectura de este instructivo. La diferencia principal es que el proxy de 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 la malla de servicios de Istio, debes quitar la línea
clusterIP: None
de los manifiestos del Servicio 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 Istio en lugar de la función similar en Envoy. Si ya usas Istio, te recomendamos usar la puerta de enlace de Ingress para enrutar 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.
Puedes usar Ambassador y Contour, que proporcionan controladores de Ingress de Kubernetes y se basan en Envoy.
Puedes usar Voyager, que es un controlador de Ingress de Kubernetes basado en HAProxy.
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 el balanceo de cargas TCP/UDP interno en lugar del balanceo de cargas de red. Para hacerlo, agrega la anotación cloud.google.com/load-balancer-type: "Internal"
al manifiesto envoy-service.yaml
.
Implementación de Envoy en comparación con DaemonSet
En este instructivo, Envoy está configurado como una implementación de Kubernetes.
Esta configuración significa que la configuración replica
en el manifiesto de implementación determina la cantidad de Pods de Envoy. Si el balanceador de cargas reenvía las solicitudes entrantes a un nodo trabajador que no ejecuta un Pod de Envoy, el proxy de red de Kubernetes reenvía la solicitud a un nodo trabajador que sí ejecuta un Pod de Envoy.
DaemonSet es una alternativa a la implementación de Envoy. Con un DaemonSet, un Pod de Envoy se ejecuta en cada nodo trabajador en el clúster de GKE. Esta alternativa supone un mayor uso de recursos en clústeres grandes (más Pods de Envoy), pero también supone que las solicitudes entrantes siempre llegan a un nodo trabajador que ejecuta un Pod de Envoy. El resultado es menos tráfico de red en el clúster y menor latencia promedio, ya que las solicitudes no se reenvían entre los nodos trabajadores para alcanzar un Pod de Envoy.
Realiza una limpieza
Una vez que termines este instructivo, podrás limpiar los recursos que creaste en Google Cloud para que no consuman la cuota y no se te cobre por ellos en el futuro. En las siguientes secciones, se describe cómo borrar o desactivar estos recursos.
Borra el proyecto
- En Cloud Console, ve a la página Administrar recursos.
- En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
- En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.
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 ~/grpc-gke-nlb-tutorial
Borra las imágenes en Container Registry.
gcloud container images list-tags gcr.io/$GOOGLE_CLOUD_PROJECT/echo-grpc \ --format 'value(digest)' | xargs -I {} gcloud container images delete \ --force-delete-tags --quiet gcr.io/$GOOGLE_CLOUD_PROJECT/echo-grpc@sha256:{} gcloud container images list-tags gcr.io/$GOOGLE_CLOUD_PROJECT/reverse-grpc \ --format 'value(digest)' | xargs -I {} gcloud container images delete \ --force-delete-tags --quiet gcr.io/$GOOGLE_CLOUD_PROJECT/reverse-grpc@sha256:{}
Borra el clúster de Google Kubernetes Engine:
gcloud container clusters delete grpc-cluster --zone $ZONE --quiet --async
¿Qué sigue?
- Lee acerca de las Herramientas de redes de Google Kubernetes Engine.
- 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.
- Obtén información sobre cómo preparar un entorno de Google Kubernetes Engine para la producción.
- Explora las guías prácticas de Google Kubernetes Engine.
- Obtén información sobre cómo crear una canalización de entrega continua de estilo GitOps mediante Google Cloud.
- Obtén información sobre cómo implementar un servicio de gRPC mediante el proxy de servicio extensible de Cloud Endpoints y Google Kubernetes Engine.
- Prueba otras funciones de Google Cloud. Consulta nuestros instructivos.