Balanceo de cargas TCP/UDP interno

En esta página, se explica cómo crear un balanceador de cargas TCP/UDP interno de Compute Engine en Google Kubernetes Engine.

Descripción general

El balanceo de cargas TCP/UDP interno permite que las aplicaciones ajenas a tu clúster que usan la misma red de VPC y se encuentran en la misma región de GCP tengan acceso a los servicios del clúster. Por ejemplo, supongamos que tienes un clúster en la región us-west1 y necesitas que las instancias de VM de Compute Engine que se ejecutan en esa región en la misma red de VPC tengan acceso a uno de sus servicios.

Puedes crear un balanceador de cargas TCP/UDP interno si creas un recurso de Servicio con la anotación cloud.google.com/load-balancer-type: "Internal" y la especificación type: LoadBalancer. Las instrucciones y el ejemplo a continuación destacan cómo hacer esto.

Sin el balanceo de cargas TCP/UDP interno, tendrías que configurar un balanceador de cargas externo y reglas de firewall para que se pueda acceder a la aplicación fuera del clúster.

El balanceo de cargas TCP/UDP interno crea una dirección IP privada (RFC 1918) para el clúster que recibe tráfico en la red dentro de la misma región de procesamiento.

Precios

Se te cobrará por el modelo de precios de Compute Engine. Para obtener más información, consulta la página de precios de balanceo de cargas TCP/UDP interno.

Antes de comenzar

Sigue estos pasos a fin de prepararte para esta tarea:

  • Asegúrate de que habilitaste la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Asegúrate de que instalaste el SDK de Cloud.
  • Establece tu ID del proyecto predeterminado:
    gcloud config set project [PROJECT_ID]
  • Si trabajas con clústeres zonales, establece tu zona de procesamiento predeterminada:
    gcloud config set compute/zone [COMPUTE_ZONE]
  • Si trabajas con clústeres regionales, establece tu región de procesamiento predeterminada:
    gcloud config set compute/region [COMPUTE_REGION]
  • Actualiza gcloud a la versión más reciente:
    gcloud components update

Crea una implementación

En el siguiente manifiesto, se describe una implementación que ejecuta 3 réplicas de una aplicación de Hello World.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app
spec:
  selector:
    matchLabels:
      app: hello
  replicas: 3
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
      - name: hello
        image: "gcr.io/google-samples/hello-app:2.0"

El código fuente y Dockerfile para esta aplicación de muestra están disponibles en GitHub. Como no se especifica ninguna variable de entorno PORT, los contenedores escuchan en el puerto 8080 predeterminado.

Para crear la implementación, crea el archivo my-deployment.yaml desde el manifiesto y, luego, ejecuta el siguiente comando en tu shell o ventana de la terminal:

kubectl apply -f my-deployment.yaml

Crea un balanceador de cargas TCP interno

En las siguientes secciones, se explica cómo crear un balanceador de cargas TCP interno mediante el uso de un servicio.

Escribe el archivo de configuración del servicio

A continuación, se muestra un ejemplo de un servicio que crea un balanceador de cargas TCP interno:

apiVersion: v1
kind: Service
metadata:
  name: ilb-service
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
  labels:
    app: hello
spec:
  type: LoadBalancer
  selector:
    app: hello
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

Requisitos mínimos de servicio

El manifiesto debe contener las siguientes características:

  • Un name para el servicio, en este caso ilb-service.
  • La anotación cloud.google.com/load-balancer-type: "Internal", que especifica que se debe configurar un balanceador de cargas TCP/UDP interno.
  • El tipo type: LoadBalancer.
  • Un campo spec: selector para especificar los pods a los que se orientará el servicio, por ejemplo, app: hello.
  • El port, que es el puerto sobre el que se expone el servicio, y targetPort, el que es puerto en el que los contenedores están escuchando.

Implementa el servicio

Para crear el balanceador de cargas TCP interno, crea el archivo my-service.yaml desde el manifiesto y, luego, ejecuta el siguiente comando en tu shell o ventana de la terminal:

kubectl apply -f my-service.yaml

Inspecciona el servicio

Después de la implementación, inspecciona el servicio para verificar que se haya configurado correctamente.

Obtén información detallada sobre el servicio:

kubectl get service ilb-service --output yaml

En el resultado, puedes ver la dirección IP del balanceador de cargas interno en status.loadBalancer.ingress. Ten en cuenta que esto es diferente del valor clusterIP. En este ejemplo, la dirección IP del balanceador de cargas es 10.128.15.193:

apiVersion: v1
kind: Service
metadata:
  ...
  labels:
    app: hello
  name: ilb-service
  ...
spec:
  clusterIP: 10.0.9.121
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 30835
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 10.128.15.193

Cualquier pod que tenga la etiqueta app: hello será miembro de este servicio. Estos son los pods que pueden ser los destinatarios finales de las solicitudes enviadas a tu balanceador de cargas interno.

Los clientes llaman al servicio mediante la dirección IP loadBalancer y el puerto TCP especificado en el campo port del manifiesto del servicio. La solicitud se reenvía a uno de los pods miembros en el puerto TCP especificado en el campo targetPort. En el ejemplo anterior, un cliente llama al servicio a la dirección IP 10.128.15.193 en el puerto TCP 80. La solicitud se reenvía a uno de los pods miembros en el puerto TCP 8080. Ten en cuenta que el pod miembro debe tener un contenedor que escuche en el puerto 8080.

El valor nodePort de 30835 es extraño. No es relevante para tu balanceador de cargas interno.

Visualiza la regla de reenvío del balanceador de cargas

Un balanceador de cargas interno se implementa como una regla de reenvío. La regla de reenvío tiene un servicio de backend, que tiene un grupo de instancias.

La dirección del balanceador de cargas interno, 10.128.15.193 en el ejemplo anterior, es la misma que la dirección de la regla de reenvío. Para ver la regla de reenvío que implementa tu balanceador de cargas interno, obtiene una lista de todas las reglas de reenvío en tu proyecto:

gcloud compute forwarding-rules list --filter="loadBalancingScheme=INTERNAL"

En el resultado, busca la regla de reenvío que tiene la misma dirección que tu balanceador de cargas interno, 10.128.15.193 en este ejemplo.

NAME                          ... IP_ADDRESS  ... TARGET
...
aae3e263abe0911e9b32a42010a80008  10.128.15.193   us-central1/backendServices/aae3e263abe0911e9b32a42010a80008

El resultado muestra el servicio de backend asociado, ae3e263abe0911e9b32a42010a80008 en este ejemplo.

Describe el servicio de backend:

gcloud compute backend-services describe aae3e263abe0911e9b32a42010a80008 --region us-central1

El resultado muestra el grupo de instancias asociado, k8s-ig--2328fa39f4dc1b75 en este ejemplo:

backends:
- balancingMode: CONNECTION
  group: .../us-central1-a/instanceGroups/k8s-ig--2328fa39f4dc1b75
...
kind: compute#backendService
loadBalancingScheme: INTERNAL
name: aae3e263abe0911e9b32a42010a80008
...

Cómo funciona la abstracción del servicio

Cuando una regla de reenvío maneja un paquete, este se reenvía a uno de los nodos del clúster. Estas son las direcciones y el puerto cuando el paquete lleva al nodo del clúster:

Dirección IP de destinoRegla de reenvío, 10.128.15.193 en este ejemplo
Puerto TCP de destinoCampo port del servicio, puerto 80 en este ejemplo

Ten en cuenta que la regla de reenvío (es decir, tu balanceador de cargas interno) no cambia la dirección IP o el puerto de destino. En cambio, las reglas iptables en el nodo del clúster enrutan el paquete a un pod apropiado. Las reglas iptables cambian la dirección IP de destino a una dirección IP del pod y el puerto de destino al valor targetPort del servicio, puerto 8080 en este ejemplo.

Verifica el balanceador de cargas TCP interno

SSH en una instancia de VM, y ejecuta el siguiente comando:

curl [LOAD_BALANCER_IP]

Donde [LOAD_BALANCER_IP] es la dirección IP LoadBalancer Ingress.

La respuesta mostrará el resultado hello-app:

Hello, world!
Version: 2.0.0
Hostname: hello-app-77b45987f7-pw54n

Ejecutar el comando desde fuera de la misma red de VPC o fuera de la misma región genera un error de tiempo de espera agotado.

Paquetes enviados desde un nodo de clúster a un balanceador de cargas interno

Supongamos que un proceso que se ejecuta en un nodo del clúster envía un paquete a un balanceador de cargas TCP/UDP interno. La forma en que se reenvíe ese paquete depende de la política de tráfico externalTrafficPolicy del servicio que usaste para crear el balanceador de cargas. El comportamiento de reenvío también depende de si el nodo tiene un pod miembro para ese servicio.

La siguiente tabla resume el comportamiento de reenvío:

externalTrafficPolicy¿Ejecuta el nodo un pod miembro?Comportamiento de los paquetes enviados desde un proceso que se ejecuta en el nodo
ClústerLos paquetes se entregan a cualquier pod miembro, ya sea en el nodo o en otro diferente.
ClústerNoLos paquetes se entregan a cualquier pod miembro, que debe estar en un nodo diferente.
LocalLos paquetes se entregan a cualquier pod miembro en el mismo nodo.
LocalNo

Kubernetes versión 1.14 y anteriores: los paquetes se descartan.

Kubernetes versión 1.15 y posterior: los paquetes se entregan a cualquier pod miembro, que debe estar en un nodo diferente.

Limpia

Puedes borrar la implementación y el servicio con kubectl delete o GCP Console.

kubectl

Borra la implementación

Para borrar la implementación, ejecuta el siguiente comando:

kubectl delete deployment hello-app

Borra el servicio

Para borrar el servicio, ejecuta el siguiente comando:

kubectl delete service ilb-service

Console

Borra la implementación

Para borrar la implementación, sigue estos pasos:

  1. Visita el menú Cargas de trabajo de Google Kubernetes Engine en GCP Console.

    Visitar el menú de cargas de trabajo

  2. En el menú, selecciona la carga de trabajo deseada.

  3. Haz clic en Borrar.

  4. Haz clic en Borrar en el menú de diálogo de confirmación.

Borra el servicio

Para borrar el servicio, sigue estos pasos:

  1. Visita el menú de Servicios de Google Kubernetes Engine en GCP Console.

    Visitar el menú Servicios

  2. En el menú, selecciona el servicio deseado.

  3. Haz clic en Borrar.

  4. Haz clic en Borrar en el menú de diálogo de confirmación.

Consideraciones para los Ingress existentes

No puedes tener un balanceador de cargas TCP/UDP interno ni un Ingress que use el modo de balanceo UTILIZATION. Para usar tanto un Ingress como un balanceo de cargas TCP/UDP interno, el Ingress debe usar el modo de balanceo RATE.

Si tu clúster tiene un recurso de Ingress existente creado con Kubernetes versión 1.7.1 o una anterior, no es compatible con balanceadores de cargas TCP/UDP internos. Los recursos BackendService anteriores que crearon los objetos de recurso Ingress de Kubernetes se crearon sin un modo de balanceo especificado. Según la configuración predeterminada, la API usó el modo de balanceo UTILIZATION para los balanceadores de cargas de HTTP. Sin embargo, los balanceadores de cargas internos TCP/UDP no se pueden apuntar a grupos de instancias con otros balanceadores de carga mediante UTILIZATION.

Determina tu modo de balanceo de Ingress

Para determinar cuál es tu modo de balanceo de Ingress, ejecuta los siguientes comandos desde tu shell o ventana de la terminal:

GROUPNAME=`kubectl get configmaps ingress-uid -o jsonpath='k8s-ig--{.data.uid}' --namespace=kube-system`
gcloud compute backend-services list --format="table(name,backends[].balancingMode,backends[].group)" | grep $GROUPNAME

Estos comandos exportan una variable de shell, GROUPNAME, que recupera el nombre del grupo de instancias de tu clúster. Luego, los recursos backend service de Compute Engine de tu proyecto se sondean, y los resultados se reducen en función de los contenidos de $GROUPNAME.

El resultado es similar a este:

k8s-be-31210--...  [u'RATE']       us-central1-b/instanceGroups/k8s-ig--...
k8s-be-32125--...  [u'RATE']       us-central1-b/instanceGroups/k8s-ig--...

Si el resultado muestra entradas RATE o no se muestra ninguna, los balanceadores de cargas internos son compatibles y no se necesita ninguna acción adicional.

Si el resultado muestra entradas marcadas con UTILIZATION, tus Ingress no son compatibles.

Para actualizar los recursos de Ingress y que sean compatibles con un balanceador de cargas TCP/UDP interno, puedes crear un clúster nuevo que ejecute la versión 1.7.2 de Kubernetes o superior y, luego, migrar tus servicios a ese clúster.

Parámetros de servicio adicionales

Los balanceadores de cargas TCP/UDP internos admiten parámetros de servicio, como loadBalancerSourceRanges.

  • Un arreglo spec: loadBalancerSourceRanges para especificar uno o más rangos RFC 1918 con tus redes de VPC, subredes o puertas de enlace de VPN. loadBalancerSourceRanges restringe el tráfico a través del balanceador de cargas a las IP especificadas en este campo. Si no configuras este campo manualmente, el campo toma como valor predeterminado 0.0.0.0, lo que permite que todo el tráfico IPv4 llegue a los nodos.

  • spec: loadBalancerIP habilita la opción de elegir una dirección IP específica para el balanceador de cargas. Otro balanceador de cargas TCP/UDP interno o servicio no deben usar la dirección IP. Si se omite, se asigna una IP efímera. Para obtener más información, consulta cómo reservar una dirección IP interna estática.

A fin de obtener más información sobre cómo configurar loadBalancerSourceRanges para restringir el acceso al balanceador de cargas TCP/UDP interno, consulta cómo configurar los firewall de tu proveedor de servicios en la nube. Para obtener más información sobre la especificación del servicio, consulta la referencia de la API de servicio.

Usa todos los puertos

Si creas un balanceador de cargas TCP/UDP interno mediante un servicio anotado, no hay manera de configurar una regla de reenvío que utilice todos los puertos. Sin embargo, si creas un balanceador de cargas TCP/UDP interno de forma manual, puedes elegir el grupo de instancias de los nodos de Google Kubernetes Engine como backend. Los servicios de Kubernetes de type: NodePort están disponibles a través de ILB.

Restricciones para balanceadores de cargas TCP/UDP internos

  • Para los clústeres que ejecutan Kubernetes versión 1.7.3 y anteriores, solo puedes usar balanceadores de cargas TCP/UDP internos con subredes de modo automático, pero con Kubernetes versión 1.7.4 y posterior, también puedes usar balanceadores de cargas internos con subredes de modo personalizado, además de las subredes de modo automático.
  • Para clústeres que ejecutan Kubernetes versión 1.7.X o posterior, mientras el clusterIP permanece sin cambios, los balanceadores de cargas TCP/UDP internos no pueden usar direcciones IP reservadas. El campo spec.loadBalancerIP aún se puede definir con una dirección IP no utilizada para asignar una IP interna específica. Los cambios realizados en los puertos, los protocolos o la afinidad de sesión pueden hacer que estas direcciones IP cambien.

Restricciones para balanceadores de cargas UDP internos

  • Los balanceadores de cargas UDP internos no admiten el uso de sessionAffinity: ClientIP.

Límites

Un servicio de Kubernetes con el tipo type: Loadbalancer y la anotación cloud.google.com/load-balancer-type: Internal crean un ILB que apunta al servicio de Kubernetes. La cantidad de esos servicios está limitada por la cantidad de reglas de reenvío internas que puedes crear en una red de VPC. Para obtener más información, consulta los límites por red.

En un clúster de GKE, una regla de reenvío interno apunta a todos los nodos del clúster. Cada nodo en el clúster es un backend VM para el ILB. El número máximo de backend VM en un ILB es 250, independientemente de cómo se asocian las VM con los grupos de instancias. Por lo tanto, el número máximo de nodos en un clúster GKE con un ILB es 250. Si habilitaste el ajuste de escala automático para tu clúster, debes asegurarte de que el ajuste de escala automático no escala tu clúster más allá de los 250 nodos.

Para obtener más información sobre estos límites, consulta Cuotas de recursos de VPC.

¿Qué sigue?

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Documentación de Kubernetes Engine