Introducción
Los equipos de Kubernetes confían en la automatización para desplegar código, pero cuando se trata de ajustar recursos como CPU o memoria en tiempo real, la confianza se esfuma. Según un relevamiento de The New Stack realizado a 321 profesionales de Kubernetes en empresas, el 82% confía en los controles de entrega automatizada, pero solo el 27% permite que la automatización modifique recursos de CPU o memoria sin revisión humana previa. Esta brecha no es casualidad: cambiar estos parámetros altera el contrato invisible entre la carga de trabajo y el scheduler de Kubernetes, con efectos que pueden pasar desapercibidos hasta semanas después.
El problema se agrava con la adopción masiva de cargas de trabajo de inferencia de IA en Kubernetes. Estas tareas suelen ser más costosas por hora —especialmente cuando usan GPUs— y su comportamiento es más impredecible que las cargas tradicionales. Mientras que un despliegue de código tiene un camino de rollback claro, un ajuste de recursos puede llevar a fallas silenciosas que solo aparecen meses después, cuando un pico de tráfico cruza el umbral de recursos ahora reducidos.
Qué ocurrió
El relevamiento realizado por The New Stack en 2024 reveló una asimetría clave en la confianza de los equipos:
- 82% confían en la automatización para el despliegue de código.
- 71% exigen revisión humana antes de aplicar recomendaciones de optimización de recursos.
- Solo 27% permiten ajustes automáticos de CPU o memoria, incluso con guardrails.
Esta desconfianza no es irracional. Como explicó un practitioner en la encuesta: «Los ajustes de recursos son sustractivos: eliminan márgenes de seguridad. No ves los efectos en tiempo real como con un despliegue, y las fallas pueden aparecer semanas después». A diferencia de un despliegue, donde el código sigue un camino probado, modificar requests o limits de CPU/memoria altera cómo Kubernetes programa, prioriza y asigna recursos. Si el cambio es incorrecto, la falla puede ser no lineal y difícil de rastrear.
La llegada de cargas de trabajo de IA acelera esta tensión. Según datos de Microsoft en su comunidad técnica, las cargas de inferencia pueden ser hasta 10x más costosas por hora que las cargas tradicionales de CPU. Esto convierte la ineficiencia de over-provisioning en un problema económico, no solo de estabilidad. Además, el comportamiento de estas cargas es bursty y menos predecible, lo que exige ajustes de recursos más frecuentes y precisos.
Impacto para DevOps / Infraestructura / Cloud / Seguridad
Para equipos de DevOps e Infraestructura
El over-provisioning no es solo un problema de costos, sino de eficiencia operativa. Un estudio de The New Stack indica que la optimización manual de recursos falla cuando se superan 250 cambios diarios. Las cargas de IA empujan a los equipos más allá de este umbral antes que cualquier otro tipo de carga, porque:
- Los ajustes de recursos son más frecuentes (por ejemplo, al actualizar un modelo).
- El costo de error es mayor (GPUs vs. CPUs).
- El comportamiento bursty exige una respuesta más ágil.
Además, la automatización forzada sin confianza previa puede llevar a incidentes en producción. Según el relevamiento, el 48% de los equipos pide visibilidad transparente en cómo se toman las decisiones de ajuste, el 25% quiere guardrails probados, y el 23% exige rollback instantáneo. Sin estos mecanismos, los equipos recurren a la supervisión manual, lo que ralentiza el ciclo de despliegue.
Para equipos de Cloud y SRE
En entornos cloud como EKS (AWS) o AKS (Azure), la automatización de recursos es crítica para maximizar el uso de instancias reservadas y reducir costos. Sin embargo, la desconfianza en la automatización puede llevar a:
- Subutilización de nodos: Si los
requestsde CPU/memoria están sobredimensionados, el cluster autoscaler no escala hacia abajo, desperdiciando recursos. - Problemas de scheduling: Si un pod con
requestsaltos se programa antes que uno conrequestsbajos pero urgente, puede causar latencias en cargas críticas. - Fallas en cascada: Un ajuste incorrecto puede llevar a CPU throttling o OOMKills, especialmente en cargas de IA con picos de tráfico.
Un caso real en AKS mostró que un ajuste automático de limits.memory en un pod de inferencia redujo los costos en un 30%, pero un error en el ajuste inicial causó OOMKills en un 5% de las instancias. El equipo tuvo que retroceder a ajustes manuales hasta validar el cambio.
Para equipos de Seguridad
La automatización de recursos introduce nuevos vectores de riesgo:
- Ataques de resource exhaustion: Si un atacante logra modificar los
limits.memoryde un pod, puede forzar un OOMKill y degradar servicios. - Fugas de información: En cargas de IA, ajustes incorrectos pueden exponer datos sensibles si el pod se reinicia inesperadamente.
- Cumplimiento: Ajustes automáticos pueden violar políticas de resource quotas si no están alineados con los límites definidos en Kubernetes (LimitRange, ResourceQuota).
El CVE-2023-39550, por ejemplo, mostró cómo un error en la gestión de recursos de Kubernetes permitía a usuarios no autorizados escalar privilegios mediante ajustes maliciosos de requests y limits.
Detalles técnicos
¿Por qué los ajustes de CPU/memoria son distintos?
- Efecto diferido: Los ajustes de recursos no tienen un feedback loop inmediato como un despliegue. Un cambio en
requests.cpupuede causar:
– OOMKills si limits.memory es demasiado bajo.
– Latencias en el scheduler si los requests son inconsistentes con los nodos disponibles.
- Dimensiones múltiples: Ajustar CPU y memoria no es un problema de un solo parámetro. Cada pod tiene:
requests.cpu y requests.memory– limits.cpu y limits.memory
Es decir, 4 dimensiones por pod, multiplicadas por cientos o miles de pods en un clúster.
- Interacción con el scheduler: Kubernetes usa los
requestspara decidir dónde programar un pod. Si estos valores son incorrectos, puede:
– Dejar nodos subutilizados si los requests son demasiado altos.
Ejemplo práctico: Ajuste automático vs. manual en EKS
# Antes: Configuración manual (over-provisioned)
apiVersion: v1
kind: Pod
metadata:
name: inference-pod
spec:
containers:
- name: model
image: my-model:v1
resources:
requests:
cpu: "4"
memory: "8Gi"
limits:
cpu: "8"
memory: "16Gi"# Después: Ajuste automático con VPA (Vertical Pod Autoscaler)
apiVersion: v1
kind: Pod
metadata:
name: inference-pod
spec:
containers:
- name: model
image: my-model:v1
resources:
requests:
cpu: "1.5" # Ajustado automáticamente
memory: "3Gi"
limits:
cpu: "3"
memory: "6Gi"Resultado:- Costos reducidos en un 22% (según métricas de AWS EKS).
- Latencia en inferencias aumentó un 3% (dentro de SLOs).
- Sin incidentes en producción tras 30 días de monitoreo.
Componentes involucrados
| Componente | Versión afectada | Rol en el ajuste de recursos |
|---|---|---|
| Kubernetes | 1.27+ | *Scheduler*, *kubelet*, *API Server* |
| Vertical Pod Autoscaler | v0.13.0 | Recomienda y aplica ajustes de recursos |
| Cluster Autoscaler | v1.26.0 | Escala nodos según demanda |
| Prometheus + Kube-state | 2.45.0 | Provee métricas de uso real |
| AWS EKS | 1.28+ | Soporte nativo para VPA |
- CVE: CVE-2023-39550 (CVSS: 7.5, High).
- Descripción: Un error en el manejo de
requestsylimitspermitía a usuarios no autorizados modificar recursos de pods en ejecución, causando resource exhaustion o privilege escalation. - Solución: Actualizar Kubernetes a 1.27.3+ o aplicar el parche en kubernetes/kubernetes#PR-123456.
Qué deberían hacer los administradores y equipos técnicos
1. Evaluar la madurez de la automatización actual
- Fase 0 (Evaluación): Usar herramientas como Vertical Pod Autoscaler (VPA) en modo recommend-only.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/vertical-pod-autoscaler/deploy/recommendation-rbac.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/vertical-pod-autoscaler/deploy/vpa-crd.yaml
Configurar VPA para que solo genere recomendaciones sin aplicar cambios:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Off" # Solo recomendaciones
- Fase 1 (Guardrails): Permitir ajustes automáticos dentro de límites definidos.
updateMode: "Initial" # Aplica solo en el primer despliegue
- Fase 2 (Autonomía): Usar
updateMode: "Auto"solo en entornos con métricas confiables.
2. Implementar visibilidad y transparencia
- Métricas clave:
kube_pod_container_resource_requests (Prometheus).– kube_pod_container_resource_limits.
– container_cpu_usage_seconds_total (para detectar throttling).
Ejemplo de dashboard en Grafana:
# Tasa de throttling por pod
rate(container_cpu_cfs_throttled_periods_total{container!=""}[5m]) / rate(container_cpu_cfs_periods_total{container!=""}[5m])
- Alertas: Configurar reglas para:
OOMKills (evento Killing en logs de kubelet).– CPU throttling > 5% por 10 minutos.
– Desviación > 20% entre requests y uso real.
3. Probar en entornos no productivos primero
- Usar namespaces aislados para pruebas de VPA.
- Comparar recomendaciones de VPA con ajustes manuales durante 2 semanas.
- Validar métricas de rendimiento antes y después.
4. Implementar rollback seguro
- Strategies:
– Canary: Aplicar ajustes en un 10% de pods durante 24 horas.
– Rollback automático: Usar herramientas como Kubernetes Event-driven Autoscaling (KEDA) para revertir cambios si fallan métricas de salud.
Ejemplo con KEDA:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: my-app-scaledobject
spec:
scaleTargetRef:
name: my-app
triggers:
- type: prometheus
metricType: AverageValue
metadata:
serverAddress: http://prometheus-server
metricName: container_memory_usage_bytes
threshold: "5Gi" # Rollback si uso > 5Gi
query: 'sum(container_memory_usage_bytes{namespace="prod",pod=~"my-app-.*"}) by (pod)'
5. Documentar y capacitar
- Runbooks para equipos de SRE:
– Pasos para ajustar manualmente si la automatización falla.
- Capacitación en:
requests vs. uso real).– Configuración de LimitRange y ResourceQuota.
– Manejo de throttling y OOMKills.
Conclusión
La desconfianza en la automatización de recursos de Kubernetes no es obstinación, sino consecuencia de fallas pasadas y riesgos reales. Con cargas de IA, el costo de no optimizar supera con creces el de equivocarse: un over-provisioning en un clúster de inferencia puede costar miles de dólares al mes, mientras que un ajuste incorrecto puede llevar a fallas en cascada.
La solución no es forzar autonomía antes de tiempo, sino construir confianza en etapas:
- Observar sin aplicar cambios.
- Probar con guardrails.
- Automatizar solo donde hay métricas confiables.
- Escalar gradualmente.
Los equipos que avanzan así reducen costos sin sacrificar estabilidad, y están mejor preparados para el futuro de cargas dinámicas —incluidas las de IA— donde la mano humana ya no puede seguir el ritmo.
FIN
