Hay un momento que todo CTO o Engineering Manager conoce: abrís la consola de AWS Billing, ves el número del mes, y sentís que algo no cuadra. Tus aplicaciones no crecieron tanto, tu equipo no cambió de tamaño, pero la factura sigue subiendo. Mes tras mes.
La razón suele ser la misma: estás pagando por capacidad que no usás. Nodos de Kubernetes corriendo 24/7 al 30% de utilización. Instancias sobredimensionadas “por si acaso”. Infraestructura que se escaló para un pico de tráfico hace tres meses y nunca se redujo.
La combinación Karpenter + Spot Instances puede reducir tu factura de compute entre un 40% y 60%. El problema es que configurarlo correctamente — de forma estable y mantenible — es bastante más complejo de lo que parece.
👻El problema: estás pagando por capacidad fantasma
En un setup típico de EKS con el Cluster Autoscaler tradicional, la historia suele ser así: ASGs con tipos de instancia fijos, nodos On-Demand las 24 horas, y un autoscaler que escala en bloques enteros.
- Los nodos se agregan en minutos, pero tardan mucho más en removerse — el autoscaler es conservador por diseño.
- Todos los nodos son del mismo tipo y tamaño, aunque tus workloads tengan necesidades muy diferentes.
- Los nodos corren como On-Demand, pagando precio completo las 24 horas.
- La utilización real rara vez supera el 40-50%, porque el autoscaler escala en bloques enteros.
Estás pagando por un edificio de oficinas cuando solo necesitás coworking. Capacidad fija, precio fijo, sin importar cuánto la usás realmente.
⚡La solución: Karpenter + Spot Instances
Karpenter reemplaza al Cluster Autoscaler con un enfoque radicalmente distinto. En vez de trabajar con Auto Scaling Groups pre-definidos, mira directamente los pods que no pueden ser programados y provisiona exactamente la instancia que necesita en ese momento.
- Selección inteligente: ¿Tenés un pod que necesita 2 vCPUs y 8 GB de RAM? Karpenter elige entre docenas de tipos de instancia y selecciona la opción más barata disponible en ese instante.
- Consolidación activa: si detecta que puede mover pods de un nodo subutilizado a otro y liberar ese nodo, lo hace. Menos nodos ociosos, menos dinero desperdiciado.
Son capacidad sobrante de AWS que podés usar entre un 60% y 90% más barata que On-Demand. El catch: AWS puede reclamarlas con 2 minutos de aviso. Karpenter puede priorizar Spot automáticamente, seleccionar entre múltiples familias para maximizar disponibilidad, y caer a On-Demand solo cuando Spot no está disponible.
🔧Instalar y configurar Karpenter
Karpenter necesita permisos IAM específicos para crear y destruir instancias EC2, gestionar ENIs, lanzar en subnets específicas y asumir roles. No es un simple helm install.
Un IAM Role dedicado con políticas específicas, un Instance Profile para los nodos, e IRSA (IAM Roles for Service Accounts) correctamente mapeado. Y tus subnets y security groups taggeados — si no, Karpenter no encuentra dónde lanzar los nodos y falla silenciosamente.
apiVersion: karpenter.sh/v1 kind: EC2NodeClass metadata: name: default spec: role: "KarpenterNodeRole" amiSelectorTerms: - alias: al2023@latest subnetSelectorTerms: - tags: karpenter.sh/discovery: "my-cluster" securityGroupSelectorTerms: - tags: karpenter.sh/discovery: "my-cluster" tags: Environment: production ManagedBy: karpenter
🗂️Definir NodePools con la estrategia correcta
Aquí empieza la complejidad real. Un NodePool define qué tipos de instancias puede usar Karpenter, en qué capacity types (Spot vs On-Demand), con qué límites. Un NodePool mal configurado puede generar más problemas que soluciones.
apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: general-workloads spec: template: spec: requirements: # Más variedad = más disponibilidad Spot - key: karpenter.k8s.aws/instance-family operator: In values: ["m5","m5a","m6i","m6a","m7i","c5","c6i","r5","r6i"] # Muy chicos = overhead, muy grandes = desperdicio - key: karpenter.k8s.aws/instance-size operator: In values: ["large","xlarge","2xlarge"] # Spot primero, On-Demand como fallback - key: karpenter.sh/capacity-type operator: In values: ["spot","on-demand"] nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: default # Límites para no despertar con una factura sorpresa limits: cpu: "200" memory: "400Gi" disruption: consolidationPolicy: WhenEmptyOrUnderutilized consolidateAfter: 30s
¿Cuántas familias de instancias incluir? Pocas = más interrupciones Spot, demasiadas = instancias subóptimas. ¿Qué límites poner? Muy bajos = tu app no escala, muy altos = riesgo de factura desbocada. ¿Qué política de consolidación? Muy agresiva = inestabilidad, muy conservadora = desperdicio.
⚖️Separar workloads críticos de no-críticos
No todo debería correr en Spot. Tu base de datos, tu sistema de colas, tu control plane — necesitan estabilidad. Esto implica múltiples NodePools con estrategias distintas.
apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: critical spec: template: spec: requirements: - key: karpenter.sh/capacity-type operator: In values: ["on-demand"] # Sin Spot para lo crítico taints: - key: workload-type value: critical effect: NoSchedule # Solo pods que toleren este taint nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: default limits: cpu: "50"
Cada uno de tus deployments necesita los tolerations y node affinity correspondientes. Si un pod crítico termina en un nodo Spot por un error de configuración, vas a tener interrupciones en producción que no deberían haber ocurrido.
🛡️Manejar las interrupciones de Spot
Spot Instances se interrumpen. Es parte del trato. AWS te da 2 minutos de aviso, y si no estás preparado, tus pods mueren sin gracia. Para manejar esto correctamente necesitás:
- Integración nativa de Karpenter con las señales de interrupción de Spot (o AWS Node Termination Handler).
- Pod Disruption Budgets (PDB) en cada deployment crítico para garantizar que siempre haya réplicas disponibles.
- Topology spread constraints para que las réplicas de un mismo servicio no caigan todas en el mismo nodo o zona.
- Graceful shutdown configurado en tus aplicaciones para terminar requests en vuelo antes de morir.
apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: my-app-pdb spec: minAvailable: 2 # Siempre al menos 2 réplicas disponibles selector: matchLabels: app: my-app --- # Deployment con topology spread para distribuir réplicas topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: DoNotSchedule - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: ScheduleAnyway
Sin PDBs ni topology spread, una interrupción de Spot puede significar un downtime que le cuesta más a tu negocio que lo que ahorraste en la factura de AWS. Los ahorros de Spot solo valen si la resiliencia está configurada correctamente.
📊Monitorear y ajustar continuamente
Karpenter no es “configurar y olvidarse”. Para mantener los ahorros necesitás visibilidad continua sobre preguntas como:
- ¿Cuál es la proporción real de Spot vs On-Demand en este momento?
- ¿Con qué frecuencia se interrumpen tus Spot Instances?
- ¿Cuál es la utilización real de los nodos después de la consolidación?
- ¿Estás cerca de los límites de tu NodePool?
- ¿Hay Spot pools que se están agotando y deberías agregar más familias de instancias?
Dashboards en Grafana o CloudWatch, alertas configuradas, y alguien en el equipo que entienda tanto Kubernetes como el mercado de Spot para tomar decisiones informadas cuando los patrones cambian.
| Qué configurar | Complejidad | Detalle |
|---|---|---|
| IAM Roles y políticas para Karpenter | Alta | IRSA, Instance Profile, 15+ acciones IAM específicas |
| EC2NodeClass con subnets y SGs taggeados | Media | Depende de cómo esté tu networking existente |
| NodePools con estrategia Spot/On-Demand | Alta | Decisiones de familias, tamaños, límites y consolidación |
| Separación de workloads críticos vs generales | Alta | Taints, tolerations y affinity por deployment |
| Manejo de interrupciones Spot | Alta | PDBs, topology spread, graceful shutdown |
| Monitoreo y ajuste continuo | Continua | Dashboards, alertas, revisión periódica del mercado Spot |
🌙Apagado programado de clusters no productivos
Hay un ahorro más que la mayoría de los equipos ni siquiera considera: ¿para qué tener prendidos tus clusters de dev y staging las 24 horas si tu equipo trabaja 8?
Si tu cluster de desarrollo cuesta USD 1.500/mes corriendo 24/7, con apagado programado pasa a costar aproximadamente USD 400/mes. Multiplicá eso por cada entorno no productivo (dev, staging, QA, demo) y el ahorro puede superar al de Spot Instances.
| Sin SleakOps | Con SleakOps |
|---|---|
| Instalar y configurar Karpenter manualmente | Pre-instalado y listo desde el día uno |
| Diseñar estrategia de NodePools desde cero | NodePools optimizados por defecto, personalizables |
| Configurar manejo de interrupciones Spot | Resiliencia integrada: PDBs, topology spread, graceful shutdown |
| Crear dashboards de monitoreo de costos | Visibilidad de costos incluida con Grafana |
| Semanas de prueba y ajuste antes de ver ahorros | Ahorros desde el primer deployment |
| Clusters no productivos corriendo 24/7 | Apagado programado por entorno configurable |
Tu factura de AWS no debería ser un misterio
Reducir costos en AWS no requiere magia — requiere las herramientas correctas configuradas correctamente. La pregunta es si tu equipo debería invertir semanas en convertirse en expertos en Karpenter, o si ese tiempo estaría mejor invertido construyendo el producto que genera ingresos.
Conocé SleakOps →