{"id":25532,"date":"2022-06-23T11:21:29","date_gmt":"2022-06-23T09:21:29","guid":{"rendered":"https:\/\/www.makingscience.com\/?p=25532"},"modified":"2022-06-23T11:21:29","modified_gmt":"2022-06-23T09:21:29","slug":"por-que-eks-agota-todas-las-ips-de-mi-subred","status":"publish","type":"post","link":"https:\/\/www.makingscience.com\/es\/blog\/por-que-eks-agota-todas-las-ips-de-mi-subred\/","title":{"rendered":"\u00bfPor qu\u00e9 EKS agota todas las IPs de mi subred?"},"content":{"rendered":"<p><span style=\"font-weight: 400;\"><strong>\u00bfTienes tu aplicaci\u00f3n desplegada sobre EKS y parece que te has quedado corto de IPs al asignar los CIDRs en las subredes?<\/strong> Vamos a analizar qu\u00e9 es lo que sucede debajo del servicio gestionado de <strong>Kubernetes de AWS.<\/strong><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Partiendo de una arquitectura de referencia como la siguiente:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img fetchpriority=\"high\" decoding=\"async\" class=\"alignnone size-full wp-image-25533\" src=\"https:\/\/www.makingscience.com\/wp-content\/uploads\/1\/2022\/06\/Captura-de-pantalla-2022-06-23-a-las-10.43.17.png\" alt=\"\" width=\"547\" height=\"648\" \/><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Imagen: eks_blog-base.png<\/span><\/p>\n<p><span style=\"font-weight: 400;\">T\u00edpica arquitectura de referencia \u201ctier 3 webapp\u201d con su balanceador en subred p\u00fablica, control plane de EKS, nodos gestionados por AWS, as\u00ed como RDS y\/o Elasticache todo ello en la subred privada.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Por <\/span><a href=\"https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/network_reqs.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">dise\u00f1o<\/span><\/a><span style=\"font-weight: 400;\"> de AWS y su integraci\u00f3n con el <\/span><a href=\"https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/pod-networking.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">CNI<\/span><\/a><span style=\"font-weight: 400;\">, los nodos y los pods de EKS usan IPs de las subredes donde se hayan desplegado, en este caso, las subredes privadas en color azul.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Hace unos a\u00f1os, cuando se montaban los cl\u00fasters <\/span><a href=\"https:\/\/github.com\/kelseyhightower\/kubernetes-the-hard-way\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">the-hard-way<\/span><\/a><span style=\"font-weight: 400;\">, hab\u00eda que definir unas subredes \u201cvirtuales\u201d que iban a usar el apiserver, los pods y los services.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">A d\u00eda de hoy, usando los servicios gestionados de nuestro proveedor cloud, en este caso AWS, \u00e9l se encarga de esta labor y es totalmente transparente para nosotros una vez le facilitamos las subredes para desplegar nuestro cl\u00faster de EKS.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><b>Exponiendo el problema<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">En un primer vistazo, nuestro diagrama tiene buena pinta y la provisi\u00f3n de IPs para nuestra peque\u00f1a aplicaci\u00f3n es m\u00e1s que suficiente, al menos a corto plazo. Como hemos hecho bien los deberes, hemos dado un CIDR lo suficientemente grande, en nuestro caso un par de \/22 lo que son 2048 IPS para nuestra aplicaci\u00f3n que tiene unos pocos de pods y varios nodos para proporcionarnos HA entre zonas.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img decoding=\"async\" class=\"alignnone size-full wp-image-25538\" src=\"https:\/\/www.makingscience.com\/wp-content\/uploads\/1\/2022\/06\/Captura-de-pantalla-2022-06-23-a-las-10.43.25.png\" alt=\"\" width=\"647\" height=\"113\" \/><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Imagen: red_eks1.png<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>\u00bfQu\u00e9 sucede cuando tengo un pico de carga?<\/strong> Al haber tenido esto en cuenta, hemos definido un HPA para que nuestros pods escalen y en caso de que sea necesario, el cluster-autoescaler levante m\u00e1s nodos para seguir dando servicio a este aumento puntual de peticiones.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Despu\u00e9s de este pico de carga, nos damos cuenta que volvemos a tener niveles normales de pods y nodos, pero observamos que nos hemos quedado sin IPs disponibles en las subredes privadas.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img decoding=\"async\" class=\"alignnone size-full wp-image-25543\" src=\"https:\/\/www.makingscience.com\/wp-content\/uploads\/1\/2022\/06\/Captura-de-pantalla-2022-06-23-a-las-10.43.36.png\" alt=\"\" width=\"640\" height=\"120\" \/><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Imagen: red_eks2.png<\/span><\/p>\n<p><strong>\u00bfY ahora qu\u00e9 hacemos? \u00bfC\u00f3mo recuperamos estas IPs?<\/strong><\/p>\n<p>&nbsp;<\/p>\n<h3><b>Investigaci\u00f3n<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Para responder a estas preguntas, debemos entender c\u00f3mo funciona \u201cpor debajo\u201d la provisi\u00f3n de IPs en los ENI de cada nodo y como funciona el AWS VPC CNI.\u00a0<\/span><\/p>\n<p><strong>1.Provisi\u00f3n de ENIs<\/strong><\/p>\n<p><span style=\"font-weight: 400;\">Seg\u00fan la <\/span><a href=\"https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/pod-networking.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">documentaci\u00f3n<\/span><\/a><span style=\"font-weight: 400;\">, AWS VPC CNI es responsable de asignar direcciones IP de la VPC a los nodos de Kubernetes y realizar la configuraci\u00f3n de la red necesaria para los pods en cada nodo.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Si nos fijamos en esta parte: \u201cDaemon L-IPAM: responsable de crear interfaces de red y adjuntar las interfaces de red a las instancias de Amazon EC2, asignar direcciones IP secundarias a las interfaces de red y mantener un grupo activo de direcciones IP en cada nodo para asignarlas a los pods de Kubernetes cuando se programan. Cuando el n\u00famero de pods que se ejecutan en el nodo supera el n\u00famero de direcciones que se pueden asignar a una interfaz de red \u00fanica, el complemento comienza a asignar una interfaz de red nueva, siempre y cuando el n\u00famero m\u00e1ximo de interfaces de red para la instancia no se encuentre conectado.\u201d conseguiremos tener muchas cosas claras.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Cada nodo puede ejecutar un <\/span><a href=\"https:\/\/github.com\/awslabs\/amazon-eks-ami\/blob\/master\/files\/eni-max-pods.txt\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">n\u00famero m\u00e1ximo de pods<\/span><\/a><span style=\"font-weight: 400;\"> y esto va ligado al n\u00famero m\u00e1ximo de <\/span><a href=\"https:\/\/docs.aws.amazon.com\/AWSEC2\/latest\/UserGuide\/using-eni.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">ENIs<\/span><\/a><span style=\"font-weight: 400;\"> que puede tener.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Si usamos como ejemplo un tipo de instancia m5.xlarge, vemos lo siguiente:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-25548\" src=\"https:\/\/www.makingscience.com\/wp-content\/uploads\/1\/2022\/06\/Captura-de-pantalla-2022-06-23-a-las-10.44.16.png\" alt=\"\" width=\"635\" height=\"88\" \/><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Imagen: eks_m5.png<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><strong>2.Configuraci\u00f3n de AWS VPC CNI<\/strong><\/p>\n<p><span style=\"font-weight: 400;\">Tratemos de entender ahora c\u00f3mo podemos <\/span><a href=\"https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/cni-env-vars.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">configurar<\/span><\/a><span style=\"font-weight: 400;\"> este componente de nuestro cl\u00faster.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Este componente se puede configurar para elegir c\u00f3mo se mantienen activas las direcciones IP. El valor predeterminado es WARM_ENI_TARGET=1. Esto significa que EKS intentar\u00e1 mantener un ENI completo disponible en el nodo. Entonces, si un nodo tiene un ENI adjunto y se usa alguna de esas direcciones IP, se adjuntar\u00e1 otro ENI para que se mantenga esta configuraci\u00f3n predeterminada.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Esto quiere decir, que cada nodo puede tener 4 ENIs y cada ENI 15 IPs, si hacemos una cuenta r\u00e1pida, vemos que cada nodo puede reservar hasta 60 IPs, por lo que 60 IPs reservadas m\u00e1s 1 IP del propio nodo, estamos consumiendo hasta 61 IPs por nodo.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><b>Soluciones<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Las IPs no se pueden recuperar hasta que no se rotan los nodos, se pueden rotar a mano o ajustar el node_group size para que AWS lo haga por nosotros.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Tenemos dos alternativas para solucionarlo:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\"><strong>Cambiar la variable de entorno que controla esto a: WARM_IP_TARGET=2 del daemonset aws-node<\/strong> de modo que cada nodo s\u00f3lo reservar\u00e1 2 IPs. De esta forma, la cuenta anterior ser\u00eda: 4 ENIs y cada ENI 2 IPs, 8 IPs, m\u00e1s 1 IP del nodo, estar\u00edamos consumiendo 9 IPs respecto a las 61 IPs con la configuraci\u00f3n por defecto.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Como buena pr\u00e1ctica, si queremos<strong> mantener las WARM IPs<\/strong> puesto que es una buena idea y permite que tu aplicaci\u00f3n escale m\u00e1s r\u00e1pido, se puede ampliar el CIDR de la VPC con un nuevo CIDR s\u00f3lo para los pods, de tal forma que los pods se desplieguen ah\u00ed y no usen nuestras valiosas IPs del CIDR principal.<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400;\"><strong>a.<\/strong> Para ello, hay que adjuntar un nuevo CIDR a nuestra VPC y crear las subredes correspondientes que usaremos m\u00e1s adelante.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-25553\" src=\"https:\/\/www.makingscience.com\/wp-content\/uploads\/1\/2022\/06\/Captura-de-pantalla-2022-06-23-a-las-10.44.23.png\" alt=\"\" width=\"645\" height=\"139\" \/><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Imagen: red_eks3.png<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>b.<\/strong> Crear la variable AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG con valor true en el daemonset de aws-node.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>c.<\/strong> Desplegar una definici\u00f3n crd.k8s.amazonaws.com\/v1alpha1 del tipo ENIConfig en nuestro cl\u00faster, del estilo:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-25558\" src=\"https:\/\/www.makingscience.com\/wp-content\/uploads\/1\/2022\/06\/Captura-de-pantalla-2022-06-23-a-las-10.44.29.png\" alt=\"\" width=\"340\" height=\"159\" \/><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Imagen: eniconfig.png<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>d.<\/strong> Rotar los nodos para que usen la nueva configuraci\u00f3n.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Nuestra arquitectura pasar\u00eda a estar definida de la siguiente manera:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-25563\" src=\"https:\/\/www.makingscience.com\/wp-content\/uploads\/1\/2022\/06\/Captura-de-pantalla-2022-06-23-a-las-10.44.39.png\" alt=\"\" width=\"503\" height=\"753\" \/><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Imagen: eks_blog-extra.png<\/span><\/p>\n<p>&nbsp;<\/p>\n<blockquote><p><span style=\"font-weight: 400;\">Si te has encontrado con estos problemas y necesitas que te ayudemos, nuestro equipo de especialistas en Cloud estar\u00e1 encantado de trabajar tu caso concreto.<\/span><\/p><\/blockquote>\n<p style=\"text-align: center;\"><a style=\"border-radius: 15px; padding: 1em; background-color: #f0076f; color: white;\" href=\"https:\/\/www.makingscience.es\/contacto\/\" target=\"_blank\" rel=\"noopener\">Contacta aqu\u00ed<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00bfTienes tu aplicaci\u00f3n desplegada sobre EKS y parece que te has quedado corto de IPs al asignar los CIDRs en las subredes? Vamos a analizar qu\u00e9 es lo que sucede debajo del servicio gestionado de Kubernetes de AWS. Partiendo de una arquitectura de referencia como la siguiente: Imagen: eks_blog-base.png T\u00edpica arquitectura de referencia \u201ctier 3 [&hellip;]<\/p>\n","protected":false},"author":40,"featured_media":25568,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[34],"tags":[322,302,321,323],"class_list":["post-25532","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology-ai","tag-aws","tag-cloud-es","tag-eks","tag-kubernetes"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/posts\/25532","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/users\/40"}],"replies":[{"embeddable":true,"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/comments?post=25532"}],"version-history":[{"count":0,"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/posts\/25532\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/media\/25568"}],"wp:attachment":[{"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/media?parent=25532"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/categories?post=25532"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.makingscience.com\/es\/wp-json\/wp\/v2\/tags?post=25532"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}