Kubernetes: Optimize IP addresses usage in EKS

Es probable que nunca os hayáis planteado como gestiona internamente Amazon EKS las IP, o no al menos hasta no haber podido desplegar un nuevo nodo debido a la falta de direcciones libres. Lógico, al final y al cabo, una de las fortalezas de los servicios gestionados reside en abstraer al usuario de este tipo de cuestiones, al menos en la medida de lo posible. Pero, ¿Qué se puede hacer una vez alcanzado el dichoso limite?

En el presente artículo se pretende describir cómo AWS Elastic Kubernetes Service gobierna las direcciones IP del cluster y cómo configurarlo para realizar un uso más óptimo de las mismas.

Caso de uso

Se dispone de un cluster de EKS compuesto por 3 nodos workers de tipo t3.2xlarge, desplegado sobre una VPC compuesta de 3 subnets distribuidas en 3 availability zone distintas, del que se quiere optimizar el uso de direcciones IPs, para no tener problemas de escalabilidad en un futuro.

CNI

Tal y como describe la documentación oficial, EKS emplea el Amazon VPC CNI plugin para trabajar de forma nativa con las AWS VPC y que los pods de Kubernetes pueden tener la misma dirección IP dentro del pod que en la red VPC.

Para ello, se despliega sobre cada nodo de EKS un DaemonSet denominado aws-node, encargado de crear las interfaces de red, conectarlas a las instancias EC2, asignar direcciones IP secundarias a las interfaces de red y mantener ‘warm pool’ de direcciones IP en cada nodo para su asignación a los pods de Kubernetes cuando estos lo requieran.

En otras palabras, cada nodo dispone de uno más ENIs (elastic network interface), que se encargan de asignar direcciones IP a los pods y que además reserva una cantidad de IPs para que los pods puedan tomarlas de forma más rápida al arrancar. Si, como bien habéis deducido, el quid de la cuestión consistente en comprender como se gestiona ese ‘warm pool’ y modificarlo si fuera necesario.

ENI Allocation

La configuración por defecto del amazon-vpc-cni-k8s determina que todo nodo del cluster debe mantener un ENI completamente libre como ‘warm pool’, independientemente del numero pods desplegados. Es decir, cuando un nuevo nodo se une al cluster de EKS, no solo dispone de 1 ENI con todas sus direcciones libres, sino que se trata aprovisionar otro ENI adicional, siempre que la instancia EC2 lo soporte.

Así, cuando la cantidad de pods que se ejecutan en el nodo excede la cantidad de direcciones en el primer ENI, el backend del CNI pasa a utilizar el ‘warm pool’ como ENI primario, al mismo tiempo que aprovisiona uno nuevo de reserva, tal y como especifica la configuración por defecto.

Veamos como aplica esta teoría sobre el caso de uso descrito previamente. Se dispone de una VPC con un bloque de CIDR 10.0.0.0/16, es decir, 65,536 IPs (2¹⁶), y tres subnets sobre la misma de 10.0.0.0/24, 10.0.1.0/24 y 10.0.2.0/24.

Sin haber desplegado nada sobre las mismas, esta es la cantidad de IPs libres en cada una.

¿Por que solo hay 251 direcciones libres en lugar de las 256 esperadas? Tal y como describe la documentación oficial de AWS, las cuatro primeras direcciones IP y la última dirección IP de cada bloque de CIDR de las subredes no se podrán utilizar ni asignar a ninguna instancia. En el presente caso de uso, las direcciones IP reservadas son las siguientes: 

  • 10.0.0.0: Dirección de red.
  • 10.0.0.1: Reservada por AWS para el router de la VPC.
  • 10.0.0.2: Reservada por AWS para el servidor DNS.
  • 10.0.0.3: Reservada por AWS para su uso en el futuro.
  • 10.0.0.255: Dirección de red broadcast. Dado que el broadcast no esta permitido en las VPC, esta dirección queda reservada.

Una vez desplegado el cluster de EKS con 3 nodos t3.2xlarge, la cantidad de IPs libres en cada subnet es la siguiente.

Tal y como se puede observar, cada subnet dispone de 31 direcciones IP libres menos que antes, que corresponden a los dos ENIs asignados (el primario y el ‘warm pool’), así como una dirección IP adicional para el nodo.

Para corroborar el calculo no hay más que acedera a la documentación oficial de AWS y comprobar el numero de direcciones IP disponibles por ENI para una instancia EC2 de tipo t3.2xlarge.

Available IPv4 addresses = 251 IP – (2 ENI x 15 IP) – 1 IP nodo = 220

CNI Configuration

El VPC CNI plugin de Kubernetes permite modificar distintos parámetros de su configuración mediante variables de entorno. Para el caso de uso actual, la propiedad susceptible a ser modificada es WARM_IP_TARGET, ya que especifica la cantidad de direcciones IP libres que el plugin debe intentar mantener disponibles para la asignación de los pods en el nodo.

Es decir, si se establece la variable de entorno WARM_IP_TARGET a 5, el plugin tratará de mantener 5 direcciones IP libres disponibles en todo momento, en lugar de un ENI completo con 15 direcciones. Puede parecer una ganancia escasa, pero cuando el numero de nodos se dispara, es mas que bienvenida, especialmente si tu VPC y/o subnets no han sido correctamente dimensionadas.

Para llevar a cambio este cambio, bastará con ejecutar el siguiente comando mediante el cliente kubectl.

kubectl -n kube-system set env daemonset aws-node WARM_IP_TARGET=5

Una vez aplicado, la cantidad de IPs libres en cada subnet es la siguiente.

En esta ocasión, el numero de direcciones IP libres sube hasta las 242, habiendo únicamente 9 consumidas por nodo de EKS: 1 dirección para el nodo físico, las 5 reservadas por el VPC CNI plugin y 3 mas por cada DaemonSet que despliega AWS en el cluster (aws-node, coredns, kubeproxy)

Available IPv4 addresses = 251 IP – 1 IP nodo – 5 IP reserva – 3 IP DaemonSet = 242 IP

Conclusiones

En conclusión, AWS permite modificar como EKS gestiona las direcciones IPs mediante el amazon-vpc-cni-k8s, si bien esto no implica que automáticamente deba realizarse independientemente del caso de uso.

La mayoría de las veces esta configuración por defecto será la adecuada y no habrá que preocuparse de ello, pero habrá, especialmente en aquellos clusteres grandes que hagan uso de aplicaciones exigentes, en las que modificar este comportamiento puede ser mas que bienvenido para poder seguir escalando horizontalmente el EKS.

Referencias

Se recomienda encarecidamente leer los siguientes artículos que han servido de base para el escrito:

  1. https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html
  2. https://docs.aws.amazon.com/eks/latest/userguide/pod-networking.html
  3. https://github.com/aws/amazon-vpc-cni-k8s
  4. https://medium.com/better-programming/amazon-eks-is-eating-my-ips-e18ea057e045

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s