Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Cómo configurar Load Balancing multi-cluster con GKE

By StepanAug 17, 202010 min read

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

Conoce los componentes de GCP Load Balancing y aprende, paso a paso, a configurar un load balancer multi-cluster con GKE disponible a nivel global.

Una de las funcionalidades que más me gustan de GCP es el HTTP(S) Load Balancing externo. Es un load balancer global que entrega una única dirección IP anycast (sin necesidad de DNS load balancing, ¡genial!). Las solicitudes ingresan a la red global de Google a través de uno de los puntos de presencia (POPs) más cercanos al usuario¹ y se enrutan vía proxy hacia la región más cercana con capacidad disponible. El resultado es una configuración de load balancing altamente disponible, distribuida globalmente, escalable y totalmente administrada. Además, puedes complementarla con protección DDoS y WAF mediante Cloud Armor, Cloud CDN o Identity-Aware Proxy (IAP) para asegurar el acceso a tus aplicaciones web.

Con esto, el load balancing multi-cluster con GKE viene a la mente de inmediato y suele ser un tema que despierta el interés de nuestros clientes. Y aunque por ahora no hay soporte nativo en GKE/Kubernetes,² GCP ofrece todos los componentes necesarios para armarlo por tu cuenta.

En la primera parte vamos a familiarizarnos con los componentes de GCP Load Balancing. Seguiremos el recorrido de una solicitud desde que entra al sistema y entenderemos qué representa cada uno de los bloques del load balancing. En la segunda parte, configuraremos paso a paso el load balancing entre dos clusters de GKE.

Visión general de GCP Load Balancing

Fig. 1: Visión general de GCP Load Balancing

Empecemos con un resumen de alto nivel del flujo de Load Balancing. La conexión HTTP(S) del cliente se termina en la edge location mediante Google Front Ends (GFEs),³ según la configuración del Target Proxy HTTP(S) y la Forwarding Rule. El Target Proxy consulta las definiciones asociadas de URL Map y Backend Service para determinar cómo enrutar el tráfico. Desde los GFEs se establece una nueva conexión y el tráfico fluye por la red de Google hacia el Backend sano más cercano con capacidad disponible. Dentro de la región, el tráfico se distribuye entre los Backend Endpoints individuales según su capacidad.

Componentes de GCP Load Balancing

Fig. 2: Componentes de GCP Load Balancing

  • Forwarding Rule — cada regla está asociada a una IP y un puerto específicos. Como hablamos de HTTP(S) load balancing global, será una dirección IP anycast global (opcionalmente, una IP estática reservada). El puerto asociado es aquel en el que el load balancer está listo para recibir tráfico de clientes externos.⁴
  • Target HTTP(S) Proxy — el tráfico se termina según la configuración del Target Proxy. Cada Target Proxy se vincula con exactamente un URL Map (relación N:1). En el caso del proxy HTTPS, también deberás adjuntar al menos un certificado SSL y configurar la SSL Policy.
  • URL Map — es el componente central de gestión de tráfico y permite enrutar el tráfico entrante entre distintos Backend Services (incluidos buckets de GCS). El enrutamiento básico se hace por hostname y por path, pero también es posible una gestión de tráfico más avanzada: redirecciones de URL, reescritura de URL y enrutamiento basado en headers y query parameters. Cada regla dirige el tráfico hacia un Backend Service.
  • Backend Service — es una agrupación lógica de backends para un mismo servicio, junto con sus opciones de configuración relevantes, como la distribución de tráfico entre Backends individuales, protocolos, session affinity o funcionalidades como Cloud CDN, Cloud Armor o IAP. Cada Backend Service también está asociado a un Health Check.
  • Health Check — define cómo se verifica que los endpoints individuales de backend estén vivos, y se usa para calcular el estado de salud general de cada Backend. Al crearlo hay que especificar el protocolo y el puerto, junto con algunos parámetros opcionales como el intervalo de chequeo, los umbrales de salud y de fallo, o el timeout. Algo importante a tener en cuenta es que se requieren reglas de firewall que permitan el tráfico de health-check desde un conjunto de rangos de IP internos.⁵
  • Backend — representa un grupo de endpoints individuales en una ubicación dada. En el caso de GKE, los backends serán Network Endpoint Groups (NEGs),⁶ uno por cada zona del cluster de GKE (en GKE los NEGs son zonales, pero algunos tipos de backend son regionales).
  • Backend Endpoint — es la combinación de una dirección IP y un puerto, en el caso de GKE con container-native load balancing⁷ apuntando a Pods individuales.

Configuración

Vamos a configurar un load balancing multi-cluster para dos servicios — Foo y Bar — desplegados en dos clusters (fig. 3). Usaremos reglas simples basadas en path: enrutaremos cualquier solicitud a /foo/* al servicio Foo, y a /bar/* al servicio Bar.

Fig. 3: GKE Multi-Cluster Foo Bar

Requisitos previos

git clone https://github.com/stepanstipl/gke-multi-cluster-native.gitcd gke-multi-cluster-native

Despliega aplicaciones y servicios en los clusters de GKE

Fig. 4: K8s Demo App

Empecemos por desplegar aplicaciones de demo simples en cada uno de los clusters. La aplicación muestra detalles del cluster y de la región que la sirven, y el código fuente está disponible en stepanstipl/k8s-demo-app.

Repite los siguientes pasos en cada uno de tus clusters.

Obtén las credenciales para kubectl

gcloud container clusters get-credentials [cluster] \
  --region [cluster-region]

Despliega las aplicaciones Foo y Bar

kubectl apply -f deploy-foo.yaml
kubectl apply -f deploy-bar.yaml

Puedes verificar que los Pods de ambos servicios están en ejecución con kubectl get pods.

Crea los Services de K8s para ambas aplicaciones

kubectl apply -f svc-foo.yaml kubectl apply -f svc-bar.yaml

Fíjate en la anotación cloud.google.com/neg: '{"exposed_ports": {"80":{}}}' en los servicios, que le indica a GKE que cree un NEG para el Service.

Puedes verificar que los servicios están bien configurados redirigiendo un puerto local con kubectl port-forward service/foo 8888:80 y entrando al servicio en http://localhost:8888/.

No olvides repetir lo anterior en todos tus clusters.

Configura los componentes de Load Balancing (GCLB)

Crea un Health Check

gcloud compute health-checks create http health-check-foobar \
  --use-serving-port \
  --request-path="/healthz"

Crea los Backend Services

Crea un backend service para cada servicio, más uno adicional que sirva como backend por defecto para el tráfico que no coincida con las reglas basadas en path.

gcloud compute backend-services create backend-service-default \
  --globalgcloud compute backend-services create backend-service-foo \
  --global \
  --health-checks health-check-foobargcloud compute backend-services create backend-service-bar \
  --global \
  --health-checks health-check-foobar

Crea el URL Map

gcloud compute url-maps create foobar-url-map \
 --global \
 --default-service backend-service-default

Agrega las reglas de path al URL Map

gcloud compute url-maps add-path-matcher foobar-url-map \
  --global \
  --path-matcher-name=foo-bar-matcher \
  --default-service=backend-service-default \
  --backend-service-path-rules='/foo/*=backend-service-foo,/bar/*=backend-service-bar'

Reserva una dirección IP estática

gcloud compute addresses create foobar-ipv4 \
  --ip-version=IPV4 \
  --global

Configura el DNS

Apunta tu DNS a la dirección IP estática que reservaste antes. Anota la IP que solicitaste:

gcloud compute addresses list --global

Crea un registro A foobar.[your_domain_name] que apunte a esta IP. Puedes usar Cloud DNS para gestionar el registro o cualquier otro servicio de tu preferencia. Este paso debe completarse antes de continuar.¹⁰

Crea el certificado SSL gestionado

gcloud beta compute ssl-certificates create foobar-cert \
 --domains "foobar.[your_domain_name]"

Crea el Target HTTPS Proxy

gcloud compute target-https-proxies create foobar-https-proxy \
  --ssl-certificates=foobar-cert \
  --url-map=foobar-url-map

Crea la Forwarding Rule

gcloud compute forwarding-rules create foobar-fw-rule \
  --target-https-proxy=foobar-https-proxy \
  --global \
  --ports=443 \
  --address=foobar-ipv4

Verifica el certificado TLS

Todo el proceso de aprovisionamiento del certificado puede demorar un rato. Puedes verificar su estado con:

gcloud beta compute ssl-certificates describe foobar-cert

El campo managed.status debería pasar a ACTIVE en los siguientes 60 minutos aproximadamente, normalmente antes, si todo se configuró correctamente.

Conecta los Services de K8s al Load Balancer

GKE ya aprovisionó NEGs para cada uno de los Services de K8s desplegados con la anotación cloud.google.com/neg. Ahora hay que agregar estos NEGs como backends a los backend services correspondientes.

Obtén los nombres de los NEGs aprovisionados

kubectl get svc \
  -o custom-columns='NAME:.metadata.name,NEG:.metadata.annotations.cloud\.google\.com/neg-status'

Anota el nombre del NEG y las zonas para cada servicio.

Repítelo en todos tus clusters de GKE.

Agrega los NEGs a los Backend Services

Repite lo siguiente para cada NEG y zona de ambos clusters. Asegúrate de usar únicamente los NEGs que pertenezcan al servicio Foo.

gcloud compute backend-services add-backend backend-service-foo \
 --global \
 --network-endpoint-group [neg_name] \
 --network-endpoint-group-zone=[neg_zone] \
 --balancing-mode=RATE \
 --max-rate-per-endpoint=100

Y lo mismo para el servicio Bar; nuevamente, repite para ambos clusters, cada NEG y cada zona:

gcloud compute backend-services add-backend backend-service-bar \
 --global \
 --network-endpoint-group [neg_name] \
 --network-endpoint-group-zone=[neg_zone] \
 --balancing-mode=RATE \
 --max-rate-per-endpoint=100

Permite el tráfico del GCLB

gcloud compute firewall-rules create fw-allow-gclb \
  --network=[vpc_name] \
  --action=allow \
  --direction=ingress \
  --source-ranges=130.211.0.0/22,35.191.0.0/16 \
  --rules=tcp:8080

Verifica que los backends estén sanos

gcloud compute backend-services get-health \
  --global backend-service-foo gcloud compute backend-services get-health \
  --global backend-service-bar

Normalmente deberías ver 6 backends (3 por cluster,¹¹ 1 por cada zona) para cada backend service, con healthState: HEALTHY. Puede demorar un rato hasta que todos los backends estén sanos después de agregar las reglas de firewall.

Comprueba que todo funciona

Haz curl a tu nombre DNS https://foobar.[your-domain] (o ábrelo en el navegador). Para la raíz deberías obtener un 502, ya que no agregamos ningún backend al servicio por defecto.

curl -v "https://foobar.[your-domain]"

Ahora haz curl a los paths de los servicios individuales https://foobar.[your-domain]/foo/ o https://foobar.[your-domain]/bar/ y deberías recibir 200 con el contenido del servicio correspondiente.

curl -v "https://foobar.[your-domain]/foo/"
curl -v "https://foobar.[your-domain]/bar/"

Si lo intentas varias veces, deberías ver el tráfico atendido por distintos Pods y Clusters.¹²

Si simulas algo de tráfico, por ejemplo con una de mis herramientas CLI favoritas, vegeta, puedes observar muy bien la distribución del tráfico entre los backends desde la GCP Console. Ve a Network services -> sección Load balancing -> selecciona tu load balancer -> pestaña Monitoring y elige el backend correspondiente. Deberías ver un dashboard parecido al de la fig. 5.

Fig. 5: Consola de GKE — Load Balancing (ambos clusters estaban en la misma región, por lo que el tráfico se distribuye de forma equitativa entre todos los backends)

Es buen momento para experimentar un poco. Mira qué pasa si tienes los clusters en la misma región y qué ocurre si están en regiones distintas. Aumenta la carga y observa cómo el tráfico se desborda hacia otra región (pista: ¿recuerdas el --max-rate-per-endpoint que usamos antes?). Mira qué pasa si tumbas uno de los clusters. ¿Y si sumas un tercer cluster a la mezcla?

(opcional) `gke-autoneg-controller`

Fíjate en la anotación anthos.cft.dev/autoneg en los Services de K8s. No es necesaria para nuestra configuración, pero opcionalmente puedes desplegar gke-autoneg-controller ¹³ en tu cluster y usarlo para asociar automáticamente los NEGs creados por GKE con los backend services correspondientes. Te ahorrará bastante trabajo manual tedioso.

¡Buen trabajo!

Y eso es todo. Explicamos el propósito de cada componente del GCLB y mostramos cómo configurar load balancing multi-cluster entre servicios desplegados en 2 o más clusters de GKE en distintas regiones. Para uso real, recomiendo automatizar esta configuración con una herramienta de gestión de configuración como Terraform.

Esta configuración aumenta la disponibilidad de tu servicio, ya que varios clusters de GKE independientes atienden el tráfico, y además reduce la latencia. En el caso de HTTPS, el tiempo hasta el primer byte es menor, ya que la negociación TLS inicial ocurre en el servidor GFE más cercano al usuario. Y con varios clusters, la solicitud se atiende desde el más cercano al usuario.

Cuéntame si te resulta útil y cualquier otra duda que tengas, ya sea aquí o en @stepanstipl. 🚀🚀🚀 ¡Sirve rápido y prospera!

  • [1] Más de 90 ubicaciones en el mundo — Load Balancing — Locations y se enrutan vía proxy a la región más cercana con capacidad disponible.
  • [2] Dejando Anthos de lado por ahora. Anthos es una plataforma de gestión de aplicaciones que permite ejecutar clusters de K8s on-prem y en otras nubes, y además extiende la funcionalidad de los clusters de GKE, incluyendo el multi-cluster ingress controller .)
  • [3] Los GFEs son sistemas distribuidos escalables y definidos por software, ubicados en los Edge POPs.
  • [4] El puerto puede ser 80 u 8080 si el target es un proxy HTTP, o 443 en el caso de un proxy HTTPS.
  • [5] Para External HTTP(S) Load Balancing estos rangos son35.191.0.0/16 y130.211.0.0/22 .
  • [6] Network endpoint groups overview
  • [7] Container-native load balancing requiere un cluster en modo VPC-native y permite que los load balancers apunten directamente a Pods individuales (en lugar de apuntar a los nodos del cluster).
  • [8] Tener clusters en regiones distintas es más interesante.
  • [9] Todos los archivos referenciados en los comandos de este post son relativos a la raíz de este repositorio.
  • [10] El registro DNS debe estar listo para que el aprovisionamiento del certificado SSL gestionado por Google funcione. De lo contrario, el certificado podría marcarse como permanentemente fallido (ya que la Autoridad Certificadora no podrá firmarlo) y habría que recrearlo.
  • [11] Asumiendo que usaste clusters regionales, cada uno desplegado en 3 zonas; de lo contrario, ajusta según corresponda.
  • [12] Si tienes clusters en regiones distintas, el GCLB preferirá servir el tráfico desde el más cercano al cliente, así que no esperes que se distribuya equitativamente entre regiones.
  • [13] No entraré aquí en los detalles de cómo desplegarlo y usarlo; sigue el readme , pero básicamente agrega una anotación con el nombre del NEG a tu servicio, p. ej.anthos.cft.dev/autoneg: '{"name":"autoneg_test", "max_rate_per_endpoint":1000}'.