BLUF
En la comunidad de Kubernetes existe una convención: los componentes integrados en Kubernetes hacen referencia a kubernetes.io en su nomenclatura, mientras que los Add-ons no. Los Add-ons suelen seguir una convención autodescriptiva como ebs.csi.aws.com, con la que se intuye fácilmente que se trata de un add-on. El add-on aws-load-balancer-controller rompe con esta convención.
Público objetivo
Este artículo apunta a tres audiencias/propósitos:
1. Administradores de Kubernetes que ejecutan EKS o distribuciones genéricas de Kubernetes en AWS: no hace falta que lo leas ahora, pero te recomiendo guardarlo en favoritos y tenerlo presente como material de referencia para volver a él si algún día necesitas depurar el aprovisionamiento de AWS Load Balancers usando servicios de Kubernetes con anotaciones del tipo service.beta.kubernetes.io/aws-load-balancer-*.
2. Fanáticos de Kubernetes a los que les gustan los artículos a fondo que les ayudan a entender mejor la plataforma.
3. Mantenedores de EKS, aws-cloud-controller-manager, aws-load-balancer-controller y de la documentación de AWS: mi intención con este artículo es exponer una inconsistencia confusa que es exclusiva del aprovisionamiento de Load Balancers de Kubernetes en AWS. Espero que sirva de empujón para alinearse con el resto de la comunidad de Kubernetes. (El problema abarca varios repositorios de git y sitios de documentación, así que no se resuelve con un par de merge requests).
Introducción
Hace poco empecé una prueba de concepto que implicaba aprovisionar AWS Load Balancers para un cluster de EKS (Elastic Kubernetes Service) usando servicios de Kubernetes de tipo LoadBalancer con anotaciones del tipo service.beta.kubernetes.io/aws-load-balancer-*, las cuales aparecen listadas en esta página.
Al principio, algunas anotaciones no funcionaban como esperaba. Logré resolverlas, pero vale la pena destacar que para hacerlo tuve que entender por qué no funcionaban. La documentación de la página enlazada explica de manera aceptable cómo funcionan las cosas, pero las explicaciones no son muy amigables para quien recién empieza.
Por eso, este post sirve como una explicación a fondo de varios temas:
- Por qué el aws-load-balancer-controller resulta confuso
- Información de contexto que ayudará a los principiantes a ponerse al día
- Detalles sobre por qué las cosas funcionan como funcionan
- Algunos consejos básicos pero útiles para resolver problemas
- Ideas sobre cómo los distintos grupos de mantenedores podrían hacer esto menos confuso a futuro
El reto: un caso de identidad equivocada
Mencioné que la página enlazada no me parece muy amigable para principiantes. Para ser claro: el proyecto me resultó tan confuso que me llevó un día entenderlo. Eso es una mala señal, considerando que soy SME de Kubernetes desde julio de 2018. Después de descifrarlo, mi primera reacción fue: "Ah, eso es lo que estaba pasando. TIL (Today I learned) que hay dos controladores distintos de Kubernetes específicos de AWS que pueden terminar usando anotaciones adjuntas a servicios de Kubernetes de tipo Load Balancer para aprovisionar y gestionar AWS LBs". La segunda fue: "Wow… ¿Cómo se supone que el resto de la gente va a entender esto sin un experto al lado? Debería escribir un artículo".
Lista de aspectos que vuelven confuso al proyecto AWS Load Balancer Controller:
1.) Parece funcionalidad oficial integrada, ¡pero no lo es!
Cuando busqué en Google "aws service of type lb":
Primer resultado: docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html
Segundo resultado: kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/service/annotations/
Y la sección relevante de la documentación oficial de Kubernetes, que es el primer resultado al buscar "kubernetes service of type loadbalancer":
https://kubernetes.io/docs/concepts/services-networking/service/
Las tres páginas parecen documentación oficial, y todas dan la impresión de tratar el mismo tema, porque las mismas anotaciones aparecen en las tres.
Si haces Ctrl+F en las tres páginas buscando:
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
El mismo recurso aparece en las tres páginas. Eso te hace pensar a primera vista que los tres sitios están hablando de lo mismo.
En realidad, el aws-load-balancer-controller es un Add-on de Kubernetes que extiende la funcionalidad integrada. O sea: dos de los enlaces anteriores cubren funcionalidad integrada, y el tercero es un add-on pensado para ofrecer funcionalidad ampliada.
2.) La convención de nomenclatura del sitio web del proyecto y de las anotaciones es muy poco intuitiva. Te lleva a pensar que las anotaciones hacen referencia a funcionalidad integrada:
2A.) El nombre DNS donde se aloja la documentación del proyecto es kubernetes-sigs.github.io, lo que hace que parezca funcionalidad nativa de Kubernetes.
2B.) Las anotaciones del add-on hacen referencia a service.beta.kubernetes.io, dominio que normalmente se reserva para funcionalidad integrada.
3.) La página principal del sitio de documentación del proyecto no deja claro de inmediato que se trata de un Add-on de Kubernetes pensado para extender la funcionalidad integrada.
Recién cuando llegas casi al final de la segunda página de la documentación:
y ves helm install aws-load-balancer-controller, recién ahí tu cerebro hace clic: "¡Aaah! Es un add-on, ok, ahora tiene sentido".
4.) El patrón que usa la API es inconsistente con el patrón habitual del resto de la comunidad de Kubernetes: tomemos Cert Manager y EBS Volume CSI (Container Storage Interface) Driver como dos ejemplos de patrones normales:
- En el caso de la documentación de cert-manager, el 95 % de sus anotaciones usan
cert-manager.io. A primera vista resulta intuitivamente obvio que las anotaciones corresponden a un add-on de terceros. - La primera oración de la página de aterrizaje de la documentación es: "cert-manager adds certificates and certificate issuers as resource types in Kubernetes clusters…". Esto deja claro de entrada que el proyecto es una extensión que añade funcionalidad.
- En el caso de EBS Volume CSI Driver, se usa una convención de nomenclatura que permite distinguir intuitivamente, a primera vista, que es algo distinto de la funcionalidad integrada.
La Storage Class integrada de AWS usa provisioner: kubernetes.io/aws-ebs
La Storage Class del Add-on de EBS usa provisioner:ebs.csi.aws.com
- Es muy común que las páginas iniciales de varios sitios de documentación de EBS CSI dejen claro repetidamente desde el principio que se trata de un add-on que no viene instalado por defecto. La documentación de este proyecto incluso incluye a propósito la palabra clave "driver" para hacerlo más intuitivo: "The Amazon EBS CSI driver isn't installed when you first create a cluster. To use the driver, you must add it as an Amazon EKS add-on or as a self-managed add-on". Y por si la gente cae primero en GitHub en lugar de la documentación, hasta la página de aterrizaje del proyecto en GitHub tiene un enlace a "Driver Installation".
5.) La interfaz y la documentación de AWS también son inconsistentes en lo que respecta al aws-load-balancer-controller: AWS Load Balancer Controller tiene una guía de usuario en docs.aws.amazon.com titulada "Installing the AWS Load Balancer Controller add-on".
Pero si miras la GUI, no aparece como add-on oficial, ni siquiera al hacer clic en Get more add-ons, donde sí ves Amazon EBS CSI Driver y AWS Distro for OpenTelemetry.
6.) Al proyecto le falta información de contexto
La página de anotaciones de servicio de la documentación menciona brevemente dos temas que son útiles para entender el funcionamiento (entender ayuda a depurar) y casi imposibles de asimilar para alguien recién llegado sin más explicación. Si intentas googlearlos, la información que vas a encontrar es muy vaga, fragmentada y aparentemente contradictoria, salvo que captes muchos matices.
Los dos temas a los que me refiero, mencionados al pasar y sin explicación en la documentación, son:
1. "in-tree": "the k8s in-tree kube-controller-manager"
2. "Legacy AWS Cloud Provider": "The AWS Load Balancer Controller manages Kubernetes Services in a compatible way with the legacy aws cloud provider".
En un mundo ideal, habría una definición resumida del significado de cada término y un enlace a lectura adicional para quien quiera profundizar. Así los resumiría yo: técnicamente son dos cosas distintas, pero a efectos prácticos son lo mismo. El Legacy AWS Cloud Provider es lo que provee la funcionalidad integrada por defecto para aprovisionar servicios de tipo Load Balancer en clusters de Kubernetes que corren en AWS.
Información de contexto
Cada vez que estoy resolviendo un problema, lo primero que hago es tratar de entenderlo. El tema del aprovisionamiento de AWS LBs requiere mucha información de contexto para entenderse a fondo. Lamentablemente, hasta hoy esa información estaba dispersa, nunca se explicaba en profundidad y estaba llena de matices difíciles de asimilar. Este es mi intento de consolidar algunas piezas clave de contexto y hacerlas fáciles de entender.
Contexto de los temas clave:
1.) kube-controller-manager vs cloud-controller-manager vs aws-cloud-controller-manager. Hay matices respecto a qué significan "in-tree" y "Legacy AWS Cloud Provider" que cuesta entender sin conocer el contexto de estos temas relacionados, así que arranquemos por aquí.
En el pasado, Kubernetes tenía cuatro componentes en el plano de control: el controller-manager, el scheduler, el api-server y etcd. Se ejecutaba o bien kube-controller-manager o bien cloud-controller-manager, no ambos.
El cloud-controller-manager era la opción que se usaba el 95 % de las veces. Tenía la misma funcionalidad que kube-controller-manager, más soporte integrado para interactuar con APIs de varios CSP (Cloud Service Provider). Como sabía cómo comunicarse con las APIs de los CSP, podía hacer cosas como aprovisionar volúmenes AWS EBS y AWS Load Balancers.
El kube-controller-manager es una implementación agnóstica respecto a la nube, por lo que carece de la capacidad integrada para hacer cosas como aprovisionar automáticamente almacenamiento o Load Balancers de un CSP.
El Kubernetes actual normalmente tiene cinco componentes en el plano de control:
etcd, kube-api-server, kube-scheduler, kube-controller-manager y un controller manager específico de un CSP, como aws-cloud-controller-manager. Los diagramas de la documentación oficial de Kubernetes se actualizaron para reflejar esta nueva arquitectura. También puedes verificarlo con métodos de despliegue como kops o kubeadm, que te permiten ver el plano de control. El cambio principal es que ahora hay cloud controller managers dedicados a un único proveedor de servicios cloud, pensados para correr junto con el kube-controller-manager. El cloud-controller-manager original, en cambio, era más bien una solución universal todo-en-uno.
2.) "In-tree" hace referencia a la época en que las librerías de Go que sabían interactuar con APIs de varios CSP vivían en el repo de Kubernetes para construir una imagen de contenedor universal del Kubernetes Cloud Controller Manager:
In-tree: código que vive en el repositorio principal de Kubernetes k8s.io/kubernetes.
Out-of-Tree: código que vive en un repositorio externo, fuera del repo de git k8s.io/kubernetes.
El código base de Kubernetes 1.14 tenía APIs para 8 CSPs distintos integradas. Se quería sumar más, y el hecho de que estuvieran todas empaquetadas juntas implicaba que todas tenían que alcanzar estabilidad al mismo tiempo para una release. Era un patrón insostenible desde el punto de vista de la mantenibilidad. Para resolverlo, se aprobó un KEP (Kubernetes Enhancement Proposal) que proponía desacoplar la funcionalidad de los CSP de Kubernetes y refactorizarla como add-ons.
Este desacoplamiento simplificaría el proceso de release de Kubernetes y permitiría a los proveedores cloud lanzar funciones y correcciones de bugs de forma independiente al ciclo y los procesos de release de Kubernetes. Fue una decisión para saldar deuda técnica y asegurar la salud a largo plazo del proyecto.
3.) Si intentas investigar este tema por tu cuenta, es fácil topar con información que a primera vista parece contradictoria, hasta que captas varios matices. Aquí van algunos, sin un orden particular:
- Da la impresión de que la migración de in-tree a out-of-tree lleva años. También hay mucha información que sugiere que comenzó hace mucho y terminó hace mucho. Que comenzó y terminó en momentos distintos. Y que aún sigue en curso.
- Antes mencioné que el código base de Kubernetes 1.14 tenía APIs para ocho CSPs distintos. Si miras el código base de Kubernetes 1.26, todavía verás cuatro CSPs distintos in-tree. AWS sigue apareciendo en la lista de CSPs in-tree. Pero hay un repo de git out-of-tree que hace referencia al aws-cloud-provider y que da a entender que AWS terminó su migración allá por la 1.20.
Pero el KEP sugiere que la migración terminará alrededor de la versión 1.27.
Cosas como esta son la razón por la que decidí escribir un artículo en lugar de contribuir a corregir un problema con la documentación. Aunque AWS y otros CSPs siguen existiendo in-tree, en una versión universal del cloud controller manager, esa versión no es la que se usa en la práctica. AWS y los demás CSPs usan su propia implementación específica, como aws-cloud-controller-manager, en vez del antiguo cloud-controller-manager universal todo-en-uno in-tree.
Distintos CSPs vienen completando su migración del universal in-tree al específico out-of-tree a ritmos distintos. Otra cosa un poco confusa es que este complejo esfuerzo se dividió en dos partes. La funcionalidad integrada in-tree original incluía lógica para aprovisionar almacenamiento de CSP y LBs de CSP. No solo se sacó out-of-tree, sino que se desacopló todavía más, de modo que los drivers CSI para almacenamiento de CSP pasaron a ser un componente aislado, con su propia línea de tiempo de migración.
- Cuando te das cuenta de la magnitud de complejidad de esa refactorización, varias cosas empiezan a tener sentido. Primero, no es de extrañar que la refactorización haya tardado más de 4 años. Las implementaciones out-of-tree de cloud providers alcanzaron estado beta en la versión 1.11, allá por mayo de 2019. Segundo, cuando te enteras de que se aplicaron varios feature freezes para acompañar el proceso de migración, empieza a tener sentido por qué cosas como los bugs asociados con implementar
ExternalTrafficPolicy: Localen AWS LBs tardaron años en corregirse. También explica por qué durante años no hubo muchas mejoras en la lógica integrada de aprovisionamiento de AWS LB.
4.) "Legacy AWS Cloud Provider" se refiere básicamente a la funcionalidad de aprovisionamiento de load balancers por defecto a la que tienes acceso en una instalación predeterminada de EKS o de Kubernetes en AWS.
Hay algunos matices que impiden que la afirmación anterior sea 100 % precisa, pero está lo suficientemente cerca de la realidad como para resultar útil.
Los matices son los siguientes:
- Legacy AWS Cloud Provider puede referirse a la lógica específica de AWS que existía in-tree, en el (CSP universal) cloud-controller-manager, y que podía aprovisionar volúmenes AWS EBS y AWS LBs.
- Legacy AWS Cloud Provider también puede referirse a la lógica de aprovisionamiento de load balancer por defecto presente en aws-cloud-controller-manager.
- aws-cloud-controller-manager suele ser invisible para los usuarios.
– Si usas EKS, aws-cloud-controller-manager corre en los nodos master gestionados que no puedes ver.
– Si usas kops o kubeadm, que utilizan nodos master autoalojados, sí lo verás.
– Si usas RKE2, no lo verás debido a ciertos detalles de implementación de seguridad en profundidad que aplican para correr algunos componentes del plano de control como procesos aislados de Kubernetes.
- Legacy AWS Cloud Provider puede referirse a dos cosas distintas, pero en el contexto de los AWS LBs vienen a ser lo mismo, ya que soportan las mismas anotaciones. Puedes encontrar las 22 anotaciones originales buscando en esta página la cadena
const ServiceAnnotationLoadBalancer. Ojo: al momento de escribir esto, si buscas la cadenaservice.beta.kubernetes.io/aws-load-balanceren la página de la documentación, solo verás 21 anotaciones. Eso es solo un problema con la documentación, no un cambio en el código.
Aquí está la lista de las 22 anotaciones a las que tienes acceso por defecto:
service.beta.kubernetes.io/aws-load-balancer-type
service.beta.kubernetes.io/aws-load-balancer-internal
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol
service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval
service.beta.kubernetes.io/aws-load-balancer-access-log-enabled
service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name
service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix
service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled
service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled
service.beta.kubernetes.io/aws-load-balancer-extra-security-groups
service.beta.kubernetes.io/aws-load-balancer-security-groups
service.beta.kubernetes.io/aws-load-balancer-ssl-cert
service.beta.kubernetes.io/aws-load-balancer-ssl-ports
service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy
service.beta.kubernetes.io/aws-load-balancer-backend-protocol
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold
service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold
service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval
5.) El proyecto AWS Load Balancer Controller es conceptualmente similar al proyecto AWS EBS CSI Driver: ambos representan el desacoplamiento de la lógica del controlador de Kubernetes que solía vivir in-tree dentro del cloud-controller-manager universal todo-en-uno. Ambos tenían el objetivo común de garantizar la compatibilidad hacia atrás. Una parte de mí se pregunta si esto influyó en la decisión del proyecto de reutilizar algunas anotaciones.
6.) El Add-on EBS CSI Driver y el Add-on AWS LB Controller fueron iniciados por grupos distintos.
El proyecto del Add-on EBS CSI Driver fue iniciado por AWS. El proyecto del Add-on AWS LB Controller fue iniciado originalmente por Ticketmaster y CoreOS, y antes se conocía como "AWS ALB Ingress Controller". Se donó al SIG-AWS de Kubernetes en 2018. Originalmente, la mejor descripción del ALB Ingress Controller era la de Application Load Balancer Controller. Con el tiempo, el alcance del proyecto se amplió para abarcar también el control de NLBs. Por eso, en julio de 2021 se renombró como "AWS Load Balancer Controller".
¿Por qué las cosas son como son?
Si la lógica del cloud-controller-manager universal todo-en-uno no se hubiera migrado out-of-tree a add-ons externos desacoplados, la deuda técnica habría ralentizado de forma permanente todo el desarrollo futuro de funcionalidades y correcciones de bugs. Recuerdo una época en la que los bugs relacionados con externalTrafficPolicy: local reaparecían una y otra vez y tomaban años en corregirse de forma adecuada. Ahora que la lógica está desacoplada del código, del proceso de release y del testing del proyecto oficial de Kubernetes, los bugs se corrigen en meses en lugar de años, y las solicitudes de funcionalidades pueden volver a considerarse.
Este desarrollo más ágil ha permitido grandes mejoras, como facilitar la implementación del concepto de Software Defined Perimeter mediante un Authn/z Proxy, gracias a la nueva integración de AWS Cognito con la lógica de aprovisionamiento de ALB. El proyecto AWS LB Controller también ofrece más opciones a la hora de aprovisionar NLBs vía anotaciones. Una nueva funcionalidad que me gusta especialmente es la anotación service.beta.kubernetes.io/aws-load-balancer-nlb-target-type:, que te permite elegir cómo enrutar el tráfico a los pods backend. El valor por defecto "instance" hace que el tráfico vaya desde nELB -> NodePort -> servicio Kube -> Pod. Un valor recién añadido, "ip", hace que el tráfico pueda ir nELB -> Pod, similar a cómo funciona aELB.
Referencia abreviada:
nELB = network Elastic Load Balancer (LB de capa 4 como servicio)
aELB/ALB = application Elastic Load Balancer (LB de capa 7 como servicio)
cELB = classic Elastic Load Balancer (LB de capas 4/7 como servicio)
Sospecho que parte de la razón por la que se produjo el scope creep de incorporar la gestión de nELBs al proyecto antes conocido como ALB Ingress Controller es que ese proyecto probablemente era más receptivo a cambios y nuevas funcionalidades en una época en la que aws-cloud-controller-manager tenía un feature freeze para acompañar la migración in-tree.
En cuanto a por qué AWS Load Balancer Controller no se parece más al Add-on AWS EBS CSI Driver, creo que tiene que ver con que AWS tuvo el control del proyecto EBS CSI de principio a fin. En cambio, el proyecto LB Controller fue adoptado, y las grandes organizaciones tienden a implementar cambios lentamente debido a la ley de Brooks. (La sobrecarga de comunicación en organizaciones grandes ralentiza significativamente los cambios).
Tips para resolver problemas con AWS LB Controller
Estos consejos para resolver problemas no pretenden ser extensos ni exhaustivos. Solo buscan ser lo suficientemente útiles como para sacarte de un atasco y orientarte hacia temas relevantes sobre los que profundizar después.
1.) Verifica si AWS LB Controller está instalado: kubectl get deployments --namespace=kube-system
Esto importa porque puede provocar cambios significativos en el comportamiento. Si tienes dos clusters con el 99 % de los mismos workloads y configuración en YAML desplegados, y la única diferencia (ese 1 %) es si AWS LB Controller está instalado o no, ese 99 % de YAML similar puede arrojar resultados distintos.
2.) Considera seriamente actualizar a la versión más reciente
Puedes usar el siguiente comando para ver qué versión estás corriendo:
kubectl get deploy aws-load-balancer-controller -n=kube-system -o yaml | grep image:
image: public.ecr.aws/eks/aws-load-balancer-controller:v2.4.6
Aquí va un escenario reciente del mundo real donde mantenerse al día resultó útil:
EKS 1.21 llegó al final de su vida útil el 15 de febrero de 2023. Algunos usuarios de AWS LB Controller sufrieron caídas hasta que actualizaron de 2.3.x → 2.4.x. Las caídas se debieron a que la actualización de Kubernetes 1.21 a 1.22 eliminó muchas APIs deprecadas. AWS LB Controller 2.4.x soporta la nueva API de Ingress networking.k8s.io/v1. La 2.3.x solo soporta la API anterior networking.k8s.io/v1beta1, que fue eliminada en Kubernetes 1.22. Los tickets de issues del proyecto aws-lb-controller detectaron que esto sería un problema e hicieron que las versiones 2.4.x funcionaran con Kubernetes 1.19++, lo que les dio a las organizaciones tiempo para migrar. Las que siguen la buena práctica de mantener sus add-ons actualizados se evitaron las caídas. Otras, que hacen el mantenimiento mínimo, probablemente se toparon con este problema al actualizar Kubernetes para mantenerse en una release soportada.
3.) Léete de cabo a rabo toda la documentación de instalación; es fácil pasar por alto algún requisito:
Además de instalar el aws-load-balancer-controller en el namespace kube-system y configurar correctamente los roles de IAM, también tienes que etiquetar correctamente las subnets de la VPC.
# Snippet of Terraform VPC Config as Code
module vpc {
...
public_subnet_tags = {
"kubernetes.io/role/elb" = "1"
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = "1"
}
}
/*
Additional Background Contextual Info:
If you look at the EKS docs
https://aws.amazon.com/premiumsupport/knowledge-center/eks-load-balancer-controller-subnets/
You'll see a reference to
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
That tag used to be required by older versions of aws-load-balancer-controller
*/
4.) Si necesitas depurar un objeto Ingress, revisa qué Ingressclasses están instaladas
kubectl get ingressclass
Si ves más de una, ejecuta kubectl describe ingressclass y revisa si alguna tiene una anotación que la marque como predeterminada.
Si la ingress class de alb no está marcada como predeterminada, conviene listar explícitamente la ingress class que quieres usar en el objeto Ingress que estás intentando depurar.
5. Si necesitas depurar anotaciones de aprovisionamiento de LB específicas de objetos service, la cosa se complica un poco…
Por qué se complica:
- En la práctica, tendrías dos controladores distintos corriendo al mismo tiempo en el mismo cluster.
- En el caso de EKS, al ser un servicio gestionado / con nodos master de Kubernetes gestionados, solo puedes ver visualmente uno de los dos controladores. (No verás aws-cloud-controller-manager, ya que se ejecuta en los nodos master gestionados).
- Los dos controladores tienen mucho solapamiento en cuanto a funcionalidad y a los objetos de los que se hacen cargo:
– aws-cloud-controller-manager: aprovisiona cELBs y nELBs
– aws-load-balancer-controller: aprovisiona aELBs y nELBs
5A.) Determina cuál de los controladores está gestionando activamente tu objeto service de Kubernetes. Según esta documentación, si anotas un servicio de Kubernetes con cualquiera de estas opciones:
service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip service.beta.kubernetes.io/aws-load-balancer-type: external
Entonces el controlador aws-cloud-controller-manager ignorará el objeto, de modo que aws-load-balancer-controller pueda gestionarlo.
5B.) Si aws-load-balancer-controller está gestionando un servicio, ¡kubectl describe service se vuelve útil! Mucha gente que ha probado opciones avanzadas de LB seguramente se topó con un escenario en el que el LB se queda en estado pending y se niega a aprovisionarse. Supongamos que ejecutas kubectl describe service $NAME para depurarlo. Si Legacy AWS Controller Manager está gestionando el servicio, lo más probable es que obtengas un mensaje de error inútil. Si lo gestiona aws-load-balancer-controller, vas a obtener mensajes de error que sí sirven para depurar. (Son excelentes para indicarte si te saltaste un paso de la instalación, como permisos de IAM faltantes, o si pasaste por alto la parte de etiquetar las subnets).
5C.) Repasa las release notes para revisar cualquier cambio que debas tener en cuenta:
- aws-cloud-controller-manager por defecto aprovisiona LBs con IPs públicas. Hay que añadir configuración para aprovisionar IPs privadas. Con aws-load-balancer-controller pasa lo contrario. (desde v2.2.0)
- aws-cloud-controller-manager por defecto aprovisiona cELBs. aws-load-balancer-controller por defecto aprovisiona nELBs (para cualquier servicio anotado con
service.beta.kubernetes.io/aws-load-balancer-type: external, ya que eso define qué controlador está al mando). - Las imágenes de contenedor de aws-cloud-controller-manager solían estar disponibles en Docker Hub, pero a partir de la v2.4.6 solo se alojarán en el registry de contenedores public.ecr.aws en adelante.
5D.) La mayoría de los objetos de Kubernetes admiten loops de reconciliación que llevan el estado actual al estado deseado. Los controladores de Load Balancer suelen tener algunos casos límite donde necesitas eliminar y volver a crear el objeto para que los cambios iterativos surtan efecto.
Esto normalmente no hace falta, pero a veces vale la pena intentarlo: la anotación de 5A es un ejemplo donde la documentación recomienda recrear en lugar de modificar. También vale la pena señalar que los valores nlb-ip y external son específicos del AWS LB Controller; el Legacy Controller usa los valores nlb y (en blanco aprovisionará un cELB). Este detalle podría ser importante para cualquiera que use un controlador de GitOps como ArgoCD o Flux para hacer cambios iterativos, ya que estos tienden a actualizar manifiestos en lugar de eliminar y volver a crear recursos. Así que, si un usuario de ArgoCD o Flux estuviera probando cambios iterativos en un entorno de dev, podría necesitar intervenir manualmente en este caso límite para ver implementados sus cambios.
Tuve dos motivos principales para escribir esto. El primero era compartir conocimiento, y esa parte ya está hecha. El segundo era ayudar a impulsar cambios que vuelvan todo esto menos confuso. Hay tres cambios que los mantenedores del proyecto y de la documentación podrían hacer y que ayudarían enormemente a despejar la confusión. Todos pasan por hacer que aws-load-balancer-controller se parezca más al proyecto EBS-CSI:
- Sumar el proyecto a la lista de add-ons oficiales de EKS instalables a través de la GUI de la consola de AWS.
- Actualizar la documentación en varios lugares para que quede inmediatamente claro que aws-load-balancer-controller es un add-on.
- Actualizar las anotaciones para que en lugar de hacer referencia a
kubernetes.iose parezcan más aebs.csi.aws.com. Así el estatus de add-on queda evidente a simple vista, y además aporta un efecto SEO (search engine optimization) que mejoraría la experiencia de quien busca la documentación relevante.