Recursos: requests y limits
Un clúster de Kubernetes tiene 3 nodos con 4 CPU y 16 GB de memoria asignables cada uno. Se despliega una aplicación con 20 réplicas; cada pod pide (requests) 500 m de CPU y 1 GB de memoria, y tiene como tope (limits) 1 CPU y 2 GB. ¿Caben las 20 réplicas? ¿Qué pasa si todos los pods llegan a su tope al mismo tiempo?
Cómo se resuelve
- 1El planificador de Kubernetes decide dónde cabe cada pod mirando únicamente los REQUESTS. Los limits no los mira para ubicar: son el tope en tiempo de ejecución.
- 2Capacidad del clúster: 3 nodos × 4 CPU = 12 CPU, y 3 × 16 = 48 GB de memoria asignables.
- 3Requests de CPU que se piden: 20 pods × 500 m = 10.000 m, o sea 10 CPU de las 12. Cabe.
- 4Requests de memoria: 20 × 1 GB = 20 GB de los 48. Cabe con holgura. Las 20 réplicas se programan sin problema, repartidas en unos 7 pods por nodo (7 × 500 m = 3,5 CPU de las 4 del nodo).
- 5Ahora el escenario de todos en el tope. Memoria: 20 × 2 GB = 40 GB contra 48 disponibles. Alcanza, no pasa nada.
- 6CPU: 20 × 1 = 20 CPU contra 12 reales. No alcanza, y aquí es donde importa la diferencia entre los dos recursos.
- 7La CPU es un recurso comprimible: cuando se acaba, el kernel simplemente le da menos tiempo a cada contenedor y todos van más lentos (estrangulamiento o throttling). Nadie se muere.
- 8La memoria no es comprimible: no se le puede dar «medio gigabyte del que pidió». Si un contenedor pasa su limit de memoria, el kernel lo mata en el acto y el pod aparece con el estado OOMKilled.
Respuesta: Sí caben: el planificador suma los requests, 10 CPU de 12 y 20 GB de 48. Con todos en el tope la memoria alcanza (40 de 48 GB), pero la CPU no (20 pedidas contra 12 reales) y los pods se estrangulan, sin que ninguno muera.
El error de siempre: Quitar los requests o dejarlos en cero «para que quepan más pods». Sin requests, el planificador cree que el pod no ocupa nada y amontona de más en cada nodo; cuando la memoria real se acaba, el nodo empieza a desalojar pods en plena producción. Además, un pod sin requests ni limits queda en la clase BestEffort, que es la primera de la fila para ser desalojada. La otra confusión que cuesta caro es tratar igual los dos topes: pasarse del límite de CPU solo frena el contenedor, pero pasarse del de memoria lo mata con OOMKilled. Si un pod se reinicia solo cada tanto sin explicación, lo primero que se mira es su limit de memoria, no la aplicación.
