Un cliente SaaS europeo vino a nosotros con un problema conocido: su factura de AWS había pasado de $15K a $38K al mes en 18 meses, mientras que su base de usuarios solo se había duplicado. Kubernetes hacía fácil escalar — y fácil malgastar dinero. Así es exactamente como bajamos la factura a $20K.
El punto de partida
El cliente tenía 3 clústeres EKS: producción, staging y desarrollo. Los tres funcionaban 24/7 sobre instancias on-demand m5.2xlarge. Hallazgos clave de nuestra auditoría inicial:
- Uso medio de CPU en todos los nodos: 18%
- Uso medio de memoria: 34%
- Clústeres de staging y desarrollo funcionando 24/7 pese a usarse solo en horario laboral (9 AM - 7 PM CET)
- Sin autoscaling configurado — número fijo de nodos definido hace meses
- Resource requests sobredimensionados — la mayoría de los pods pedían 2-4x su consumo real
- 23 volúmenes EBS huérfanos de PVC antiguos — $420/mes a cambio de nada
Fase 1: right-sizing (semana 1-2)
Desplegamos el Vertical Pod Autoscaler en modo recomendación en todos los namespaces y recogimos datos durante 14 días. Los resultados fueron llamativos:
Un servicio de API en Java pedía 2 CPU y 4Gi de memoria, pero usaba de forma constante 400m de CPU y 800Mi de memoria — un 80% de desperdicio en un solo deployment con 6 réplicas. Multiplica eso por 47 servicios.
Ajustamos los resource requests y limits según el uso P95 con un margen del 30%. Solo con esto pudimos reducir los worker nodes de producción de 24 a 14.
Ahorro: $5,200/mes
Fase 2: instancias Spot para cargas de trabajo stateless (semana 3)
Analizamos qué cargas de trabajo eran compatibles con spot: - Servicios de API stateless (12 servicios, 34 pods) — totalmente compatibles con spot - Servidores web de frontend — compatibles con spot - Workers en segundo plano y consumidores de colas — compatibles con spot - Bases de datos y servicios stateful — deben seguir en on-demand
Configuramos pools de instancias mixtas con Karpenter (en sustitución del Cluster Autoscaler por defecto). Karpenter elige entre 15+ tipos de instancia repartidos en 3 AZ, lo que maximiza la disponibilidad de spot y minimiza las interrupciones.
Las reglas de node affinity garantizan que las cargas de trabajo stateful (PostgreSQL, Redis, Elasticsearch) solo se programen en nodos on-demand, mientras que los servicios stateless prefieren nodos spot.
El precio de las instancias spot para nuestra combinación fue, de media, un 68% más barato que on-demand.
Ahorro: $7,400/mes
Fase 3: programar los entornos de no producción (semana 3)
Los clústeres de staging y desarrollo no necesitan estar funcionando a las 3 AM. Implantamos:
- Clúster de desarrollo: escala a cero nodos fuera del horario 8 AM - 8 PM CET, de lunes a viernes
- Clúster de staging: escala al mínimo (2 nodos) fuera del horario laboral y a plena capacidad durante las ejecuciones de CI/CD
Combinando el escalado de nodos de Karpenter con CronJobs que hacen cordon/drain de los nodos, redujimos el cómputo de no producción en un 65%.
Ahorro: $3,800/mes
Fase 4: limpieza y optimización del almacenamiento (semana 4)
- Eliminamos 23 volúmenes EBS huérfanos ($420/mes)
- Migramos el almacenamiento de logs de EBS gp3 a S3 con políticas de ciclo de vida ($280/mes de ahorro)
- Cambiamos las bases de datos de desarrollo de la storage class io2 a gp3 ($190/mes de ahorro)
- Implantamos la limpieza automática de PVC al eliminar un namespace
Ahorro: $890/mes
Fase 5: precios basados en compromiso (semana 5)
Tras 4 semanas de datos de uso ya optimizado, teníamos una visibilidad clara del cómputo base que siempre iba a estar funcionando. Compramos:
- Un Compute Savings Plan de 1 año que cubría el 70% de la base on-demand restante
- Esto cubría las cargas de trabajo stateful de producción y la capacidad mínima de staging
Ahorro: $1,100/mes
Resumen de resultados
| Categoría | Ahorro mensual | |----------|----------------| | Right-sizing | $5,200 | | Instancias Spot | $7,400 | | Programación de no producción | $3,800 | | Limpieza de almacenamiento | $890 | | Savings Plans | $1,100 | | Total | $18,390 |
Factura mensual final: $19,610 (antes, $38,000) Reducción: 47%
Lo que NO hicimos
Lo importante es que no: - Cambiamos ningún código de la aplicación - Redujimos el número de réplicas de los servicios en producción - Pusimos en riesgo la disponibilidad ni la recuperación ante desastres - Introdujimos ningún nuevo punto único de fallo - Tuvimos ningún tiempo de inactividad durante la optimización
La aplicación siguió sirviendo el mismo tráfico con la misma latencia. Los usuarios no notaron nada. El CFO notó muchísimo.
Lecciones aprendidas
- 1Empieza por la visibilidad — No puedes optimizar lo que no mides. Kubecost u OpenCost deberían ser tu primer despliegue.
- 2Primero, right-sizing — Es la optimización más segura y con mayor ROI. Hazla antes que nada.
- 3Spot está listo para producción — Con pod disruption budgets bien configurados, varias réplicas y pools de instancias mixtas, las interrupciones de spot son invisibles para los usuarios.
- 4El desperdicio fuera de producción es enorme — Los entornos de dev y staging suelen representar el 30-40% del gasto cloud, pero están sin usar el 70% del tiempo.
- 5Comprométete al final — Compra reservas solo después de haber optimizado. Si no, estás blindando el desperdicio.
Conclusión
La optimización de costes cloud no consiste en escatimar — consiste en eliminar el desperdicio. Cada dólar gastado en cómputo ocioso es un dólar que no se invierte en desarrollo de producto, contratación o captación de clientes. Las herramientas y técnicas de este caso de éxito se aplican a cualquier entorno Kubernetes que funcione en la nube pública, y el rango de ahorro del 30-50% se consigue de forma consistente.