“Balanceo de carga con Kubernetes” es un término bastante amplio que se refiere a varias cosas. En este artículo, veremos dos tipos de balanceadores de carga: uno que se usa para exponer los servicios de Kubernetes al mundo exterior y otro que usan los ingenieros para equilibrar las cargas de tráfico de la red a esos servicios.

Siga leyendo para conocer las mejores prácticas comprobadas para manejar un balanceador de carga de Kubernetes.

¿Qué es un equilibrador de carga de Kubernetes?

En Kubernetes, los contenedores se agrupan en pods con almacenamiento compartido y recursos de red, así como especificaciones sobre cómo ejecutar estos contenedores. Un grupo de pods relacionados puede formar un servicio de Kubernetes.

Dado que los pods no son persistentes (Kubernetes los crea y los destruye automáticamente), sus direcciones IP tampoco son persistentes. Para exponer los pods, debe usar un recurso de Kubernetes llamado Servicio.

Un servicio de Kubernetes le permite exponer un grupo de pods para uso externo o interno. Puede elegir entre algunos tipos de servicios, así que aquí hay una descripción general rápida para comenzar.

Descripción general de los servicios de Kubernetes

ClusterIP: este es un tipo predeterminado de servicio K8s que expone un conjunto de pods solo internamente. Aquí hay un ejemplo de definición YAML para el servicio ClusterIP:

apiVersion: v1
kind: Service
metadata: 
 name: servicio-interno
spec:
 selector:   
   app: aplicacion
 type: ClusterIP
 ports: 
 - name: http
   port: 80
   targetPort: 80
   protocol: TCP

ClusterIP se utiliza para la comunicación de aplicaciones internas y no está disponible fuera del clúster.

NodePort: el servicio expone un puerto determinado en cada IP de nodo en el clúster.

apiVersion: v1
kind: Service
metadata: 
 name: servicio-nodo
spec:
 selector:   
   app: aplicacion
 type: NodePort
 ports: 
 - name: http
   port: 80
   targetPort: 80
   nodePort: 30000
   protocol: TCP

Tenga en cuenta que el servicio NodePort tiene muchas desventajas:

  • solo puedes tener un servicio por puerto
  • solo puede usar los puertos 30000–32767,
  • si su dirección IP de Nodo/VM cambia, debe lidiar con eso.

Es por eso que no se recomienda para casos de uso de producción.

LoadBalancer: este servicio expone un conjunto de pods mediante un equilibrador de carga externo. Todas las ofertas administradas de Kubernetes tienen su propia implementación (para EKS puede usar NLB, ALB, etc.)

En la mayoría de los casos, los crea el proveedor de la nube. Pero también hay algunos proyectos que tienen como objetivo exponerlo en clústeres de metal desnudo: metallb es un buen ejemplo (comparto más ejemplos al final de este artículo).

Pero ese no es el final de la historia.

Kubernetes también tiene un objeto API llamado Ingress. Ingress se basa en el servicio de Kubernetes (para exponer Ingress, debe usar el servicio de Kubernetes). La responsabilidad principal de Ingress es distribuir el tráfico de red a los servicios de acuerdo con reglas o algoritmos de enrutamiento predeterminados.

También expone los pods al tráfico externo, generalmente a través de HTTP. Dependiendo de sus objetivos comerciales y las especificaciones del entorno, puede usar diferentes estrategias de distribución de carga.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: minimal-ingress
 annotations:
   nginx.ingress.kubernetes.io/rewrite-target: /
spec:
 ingressClassName: ejemplo-nginx
 rules:
 - http:
     paths:
     - path: /test
       pathType: Prefix
       backend:
         service:
           name: test
           port:
             number: 80

Estrategias de distribución de tráfico del balanceador de carga

La distribución eficiente del tráfico de red entre varios servicios backend es clave para maximizar la escalabilidad y la disponibilidad.

Tiene mucha libertad para equilibrar la carga del tráfico externo a los pods, pero cada estrategia tiene sus ventajas y desventajas. Todo depende de su carga, requisitos y preferencias.

La elección del algoritmo de balanceo de carga es algo que debe hacer con cuidado; de lo contrario, terminará con una distribución de carga desequilibrada o un solo servidor web que se calienta.

Aquí hay una selección de algoritmos de equilibrio de carga que debe considerar.

Round Robin

Usando este algoritmo de programación, sigue una secuencia de servidores elegibles que obtienen nuevas conexiones. Tenga en cuenta que esta solución es estática; en realidad, no tiene en cuenta las variaciones de velocidad o rendimiento entre estos servidores individuales. Simplemente se asegura de que las solicitudes lleguen a los servidores en orden.

Round robin no puede diferenciar entre servidores lentos y rápidos, por lo que asigna el mismo número de conexiones a cada uno de ellos. Si espera tráfico de producción de alto rendimiento, es posible que no sea la mejor opción.

Equilibrador de carga L4 Round Robin

Una de las tácticas básicas de equilibrio de carga en Kubernetes. Atiende todas las solicitudes enviadas al servicio y las enruta. El kube-proxy implementa direcciones IP virtuales para servicios con la ayuda de las reglas de iptables, lo que agrega cierta complejidad al proceso. También agrega latencia adicional con cada solicitud, lo que podría convertirse en un problema si la cantidad de servicios sigue creciendo.

Equilibrio de carga L7 Round Robin

El proxy L7 dirige el tráfico a los pods de Kubernetes omitiendo el kube-proxy a través de una puerta de enlace API y administrando las solicitudes de pods disponibles. El balanceador de carga también realiza un seguimiento de los pods, que están disponibles con la API de Kubernetes Endpoints. Cuando recibe una solicitud para un servicio de Kubernetes determinado, hace un round robin de la solicitud entre los pods relevantes para encontrar uno disponible.

Proxy kube L4 e IPVS

De forma predeterminada, kube-proxy usa iptables para el enrutamiento, pero también puede usar un servidor virtual IP (IPVS). La ventaja de IPVS es la escalabilidad: se ejecuta en tiempo O(1) sin verse influenciado por la cantidad de reglas de enrutamiento requeridas. Este número es directamente proporcional al número de servicios.

Si está ejecutando un enorme clúster de Kubernetes con miles de servicios, IPVS es una buena opción. Aún así, IPVS es un enrutamiento de nivel L4, por lo que está sujeto a algunas limitaciones.

Ring hash

Este algoritmo de programación se basa en un hash, que se deriva de una clave específica. Un hash permite la distribución de nuevas conexiones entre servidores. Ring hash es una buena solución para una gran cantidad de servidores y contenido dinámico, ya que aúna equilibrio de carga y persistencia. Muchas aplicaciones o servicios de comercio electrónico que necesitan un estado por cliente lo utilizan.

Cuando es necesario agregar o quitar un servidor, el hashing consistente no tiene que volver a calcular toda la tabla hash. Por lo tanto, no afecta a otras conexiones. Tenga en cuenta que el hash de anillo puede agregar algo de latencia a las solicitudes cuando se ejecuta a escala. Además, el algoritmo genera tablas de búsqueda relativamente grandes que pueden no caber en la memoria caché del procesador de su CPU.

Maglev

De manera similar al hash de anillo, Maglev es un algoritmo hash consistente que fue desarrollado originalmente por Google. La idea detrás de esto fue aumentar la velocidad sobre el hash de anillo en las búsquedas de tablas hash. El otro objetivo de sus creadores era minimizar la huella de memoria del algoritmo.

Si decide usar Maglev para microservicios, espere altos costos derivados de generar una tabla de búsqueda cuando falla un nodo. Dado que las cápsulas K8 son de naturaleza relativamente transitoria, usar Maglev podría no ser la mejor idea.

Menor cantindad de conexiones (Least Connection)

Este algoritmo de balanceo de carga dinámico distribuye las solicitudes de los clientes a los pods con la cantidad más baja de conexiones activas y la carga de conexión más pequeña. Gracias a esto, se adapta a servidores más lentos o en mal estado. Pero cuando todos sus pods estén igualmente saludables, la carga se distribuirá por igual.

Mejores prácticas para manejar un balanceador de carga de Kubernetes

Cuando implemente los balanceadores de carga de Kubernetes, siga algunos pasos de configuración para asegurarse de que su implementación de K8s use los balanceadores de carga que elija al máximo.

Estas son algunas de las mejores prácticas para trabajar con balanceadores de carga en Kubernetes.

Comprobar si el equilibrador de carga está habilitado

Este parece demasiado obvio para ser incluido en esta lista, pero es un paso clave. Debe tener habilitado el balanceador de carga de servicios en su sistema K8s. Su equilibrador de carga debe ser compatible con entornos contenidos y detección de servicios. Además, su aplicación debe estar diseñada para contenerización.

Cada proveedor de servicios en la nube tiene su propia implementación de balanceador de carga; la mayoría de ellos permiten un ajuste fino mediante el uso de anotaciones de servicio.

Habilitar readiness probe

Una readiness probe informa a K8s si la aplicación está lista para servir tráfico o no. Debe habilitar las readines probes a medida que pasan el tráfico al pod. Para hacerlo, debe tenerlo definido en cualquiera de sus implementaciones de K8s.

Si no tiene una en su lugar, el usuario llegará al pod pero no obtendrá una respuesta saludable del servidor. Esto se debe a que el trabajo de la readiness probe es señalar a Kubernetes cuándo colocar un pod detrás del balanceador de carga y un servicio detrás del proxy.

Habilitar liveness probe

Otra sonda clave que debe habilitar es una liveness probe. Le permite a Kubernetes saber si un pod está lo suficientemente saludable como para seguir funcionando o si reiniciarlo es una mejor idea. Realiza una comprobación simple o compleja basada en comandos bash.

Este mecanismo está ahí para ayudar a los K8 a determinar si el equilibrio de carga funciona bien o si algunos de sus componentes requieren soporte. Las activity probes aumentan la disponibilidad incluso si su aplicación contiene errores.

Aplicar políticas de red

Para proteger su implementación de K8s, el balanceador de carga debe poder aplicar políticas de grupo de seguridad a máquinas virtuales o nodos de trabajo.

En un escenario ideal, debe limitar el tráfico entrante y saliente al requisito mínimo. ¿Cuál es el beneficio de poner tal limitación? Le ayuda a evitar la exposición accidental de servicios no deseados al flujo de tráfico saliente.

Kubernetes viene con una funcionalidad de política de seguridad de red capaz de atender todos los recursos dentro de las implementaciones. También debe asegurarse de que su clúster de Kubernetes esté provisto de un complemento de red que admita políticas de red.

Habilitar solicitudes de CPU/memoria

De esa forma, los contenedores podrán solicitar recursos automáticamente. Esto ayuda a liberar la CPU y los recursos de memoria que necesita el sistema. Además, habilitar estas solicitudes le permite definir estos recursos para que el pod nunca se quede sin memoria. Además de eso, elimina el riesgo de que la CPU o la memoria se apoderen de todos los recursos en un nodo y provoquen un error o falla.

Categorized in: