El aprovisionamiento dinámico de recursos computacionales en entornos de orquestación de contenedores a gran escala presenta un desafío fundamental en la computación distribuida: cómo alinear la capacidad de infraestructura con la demanda de la carga de trabajo de manera eficiente, rápida y rentable. Los sistemas tradicionales basados en grupos de autoescalado predefinidos (como AWS Auto Scaling Groups) y controladores de escalado de Kubernetes (como Cluster Autoscaler) introducen latencia significativa y fragmentación de recursos debido a su naturaleza reactiva y a la gestión indirecta de la capacidad. Esto se agrava en entornos de hyperscaler con miles de clusters y cargas de trabajo heterogéneas.

Karpenter aborda este problema fundamental al desacoplar el aprovisionamiento de nodos de las Auto Scaling Groups, permitiendo una interacción directa con la API del proveedor de la nube. Esto permite a Karpenter provisionar nodos 'justo a tiempo' y 'del tamaño correcto' basándose en las solicitudes de recursos de los pods pendientes, optimizando el bin-packing y reduciendo la latencia de escalado de minutos a segundos. La necesidad de esta evolución surge de la creciente complejidad y escala de las implementaciones de Kubernetes, donde la gestión manual o semi-automatizada de miles de grupos de nodos se vuelve insostenible y costosa.

Arquitectura del Sistema

La arquitectura de Karpenter se centra en un controlador de Kubernetes que observa los pods pendientes en el cluster. A diferencia de Cluster Autoscaler, que interactúa con Auto Scaling Groups preconfiguradas, Karpenter interactúa directamente con la API de EC2 (en el caso de AWS) para provisionar instancias. Utiliza NodePool y EC2NodeClass como Custom Resources (CRDs) para definir las especificaciones de los nodos (tipos de instancia, volúmenes, etiquetas, etc.). Cuando Karpenter detecta pods no programables, evalúa los requisitos de recursos de esos pods y selecciona el tipo de instancia EC2 más adecuado para satisfacer la demanda, minimizando el desperdicio de recursos (bin-packing).

El proceso de migración de Salesforce implicó el desarrollo de herramientas personalizadas: un 'Karpenter transition tool' y un 'Karpenter patching check tool'. La herramienta de transición automatizó la conversión de configuraciones de Auto Scaling Group existentes a las definiciones de NodePool y EC2NodeClass de Karpenter. Esta herramienta orquestó la rotación de nodos, la validación de AMIs y el desalojo de pods, respetando los Pod Disruption Budgets (PDBs). La estrategia de despliegue fue por fases, comenzando con entornos de bajo riesgo y progresando hacia la producción, con puntos de control y capacidad de rollback. La gestión de PDBs, las limitaciones de longitud de etiquetas de Kubernetes y la protección de aplicaciones de instancia única fueron consideraciones clave durante la implementación.

Flujo de Aprovisionamiento de Nodos con Karpenter

  1. 1 Kubernetes Scheduler Intenta programar Pods, algunos quedan 'Pending'
  2. 2 Karpenter Controller Detecta Pods 'Pending' sin nodos disponibles
  3. 3 Karpenter Controller Evalúa requisitos de Pods y `NodePool`/`EC2NodeClass`
  4. 4 Karpenter Controller Llama a la API de EC2 para provisionar instancia 'right-sized'
  5. 5 EC2 Service Provisiona nueva instancia EC2
  6. 6 Kubelet Se une al cluster Kubernetes
  7. 7 Kubernetes Scheduler Programa Pods pendientes en el nuevo nodo

Flujo de Migración Automatizada de Nodos (Salesforce)

  1. 1 Karpenter Transition Tool Identifica nodos legacy (Auto Scaling Group)
  2. 2 Karpenter Transition Tool Cordon & Drain nodo legacy (respetando PDBs)
  3. 3 Karpenter Controller Provisiona nuevo nodo Karpenter para reemplazar capacidad
  4. 4 Karpenter Transition Tool Verifica salud del cluster y pods
  5. 5 Karpenter Transition Tool Repite secuencialmente para otros nodos
  6. 6 CI/CD Pipeline Integra y estandariza el proceso de migración
CapaTecnologíaJustificación
orchestration Kubernetes Plataforma de orquestación de contenedores para cargas de trabajo de Salesforce
orchestration Amazon EKS Servicio gestionado de Kubernetes en AWS, base de la infraestructura de Salesforce
orchestration Karpenter Controlador de aprovisionamiento de nodos dinámico para Kubernetes, reemplazando Cluster Autoscaler vs Kubernetes Cluster Autoscaler Uso de `NodePool` y `EC2NodeClass` CRDs para configuración
orchestration Kubernetes Cluster Autoscaler Solución de autoescalado de nodos legacy, dependiente de AWS Auto Scaling Groups vs Karpenter
orchestration AWS Auto Scaling Groups Mecanismo de autoescalado de instancias EC2 legacy, gestionado por Cluster Autoscaler vs Karpenter (interacción directa con EC2 API)
security Open Policy Agent (OPA) Aplicado para la validación proactiva de Pod Disruption Budgets (PDBs)

Trade-offs

Ganancias
  • Latencia de escalado de nodos
  • Eficiencia de bin-packing y utilización de recursos
  • Complejidad operativa (número de grupos de nodos)
  • Costo de infraestructura
  • Experiencia del desarrollador (self-service)
Costes
  • Esfuerzo de migración inicial y desarrollo de tooling
  • Necesidad de refactorizar convenciones de nombres (labels)
  • Riesgo de interrupción para aplicaciones single-replica sin políticas de disrupción
metadata:
  name: m5.8xlarge-min-300-max-2500
data:
  k8s_instance_type: m6i.8xlarge
  k8s_root_volume_size: '100'
  k8s_root_volume_iops: '3000'
  k8s_root_volume_type: 'gp3'
  k8s_root_volume_throughput: '125'
  k8s_min_node_number: '300'
  k8s_max_node_number: '2500'
  multi_az_provisioned_workers: 'false'
  asg_launch_type: 'launch_template'
  gpu_enabled: 'false'
Ejemplo de mapeo de configuraciones legacy de Auto Scaling Group a la definición de `EC2NodeClass` de Karpenter, mostrando cómo se especifican tipos de instancia, volúmenes y etiquetas.

Fundamentos Teóricos

El problema de la asignación eficiente de recursos en sistemas distribuidos se remonta a los fundamentos de la programación de tareas y la optimización de recursos. Conceptos como el 'bin-packing problem' (problema de la mochila o empaquetamiento de contenedores) son centrales en la forma en que Karpenter optimiza la utilización de nodos. El bin-packing es un problema NP-hard en optimización combinatoria, donde el objetivo es empaquetar un conjunto de elementos de diferentes tamaños en el menor número posible de 'contenedores' (en este caso, nodos de computación) de capacidad fija. Los algoritmos heurísticos como 'First Fit Decreasing' o 'Best Fit Decreasing' son comúnmente utilizados para aproximar soluciones eficientes.

Además, la gestión de la consistencia y disponibilidad durante las transiciones de estado en sistemas distribuidos, como la rotación de nodos, se relaciona con los principios de tolerancia a fallos y el teorema CAP. La necesidad de respetar los Pod Disruption Budgets (PDBs) durante el desalojo de pods es una aplicación práctica de estos principios para mantener la disponibilidad de la aplicación mientras se modifica la infraestructura subyacente. La automatización de la configuración y el despliegue a gran escala también se alinea con los principios de la 'Infrastructure as Code' y la 'Continuous Delivery', que buscan reducir el error humano y acelerar el ciclo de vida del software, conceptos popularizados por autores como Jez Humble y David Farley.