Si No Tienes Cuidado, Puedes Bloquear La Escalabilidad De Tus Cargas De Trabajo
Foto de Joshua Hoehne en Unsplash
Una de las grandes cosas sobre los desarrollos basados en contenedores es definir espacios de aislamiento donde tienes recursos garantizados como CPU y memoria. Esto también se extiende en entornos basados en Kubernetes a nivel de namespace, por lo que puedes tener diferentes entornos virtuales que no pueden exceder el uso de recursos a un nivel especificado.
Para definir eso, tienes el concepto de Cuota de Recursos que funciona a nivel de namespace. Basado en su propia definición (https://kubernetes.io/docs/concepts/policy/resource-quotas/)
Una cuota de recursos, definida por un objeto ResourceQuota, proporciona restricciones que limitan el consumo agregado de recursos por namespace. Puede limitar la cantidad de objetos que se pueden crear en un namespace por tipo, así como la cantidad total de recursos de cómputo que pueden ser consumidos por recursos en ese namespace.
Tienes varias opciones para definir el uso de estas Cuotas de Recursos, pero nos centraremos en este artículo en las principales de la siguiente manera:
- limits.cpu: En todos los pods en un estado no terminal, la suma de los límites de CPU no puede exceder este valor.
- limits.memory: En todos los pods en un estado no terminal, la suma de los límites de memoria no puede exceder este valor.
- requests.cpu: En todos los pods en un estado no terminal, la suma de las solicitudes de CPU no puede exceder este valor.
- requests.memory: En todos los pods en un estado no terminal, la suma de las solicitudes de memoria no puede exceder este valor.
Así que puedes pensar que esta es una gran opción para definir una cuota de limit.cpu y limit.memory, para asegurarte de que no excederás esa cantidad de uso por ningún medio. Pero necesitas tener cuidado con lo que esto significa, y para ilustrarlo usaré un ejemplo.
Tengo una sola carga de trabajo con un solo pod con la siguiente limitación de recursos:
- requests.cpu: 500m
- limits.cpu: 1
- requests.memory: 500Mi
- limits.memory: 1 GB
Tu aplicación es una aplicación basada en Java que expone un Servicio REST y ha configurado una regla de Escalador Horizontal de Pods para escalar cuando la cantidad de CPU excede su 50%.
Entonces, comenzamos en la situación primaria: con una sola instancia que requiere ejecutar 150 m de vCPU y 200 RAM, un poco menos del 50% para evitar el escalador. Pero tenemos una Cuota de Recursos sobre los límites del pod (1 vCPU y 1 GB) por lo que hemos bloqueado eso. Tenemos más solicitudes y necesitamos escalar a dos instancias. Para simplificar los cálculos, asumiremos que usaremos la misma cantidad de recursos para cada una de las instancias, y continuaremos de esa manera hasta llegar a 8 instancias. Así que veamos cómo cambian los límites definidos (el que limitará la cantidad de objetos que puedo crear en mi namespace) y la cantidad real de recursos que estoy usando:
Entonces, para una cantidad de recursos usados de 1.6 vCPU he bloqueado 8 vCPU, y en caso de que ese fuera mi Límite de Recursos, no puedo crear más instancias, aunque tengo 6.4 vCPU no usados que he permitido desplegar debido a este tipo de limitación no puedo hacerlo.
Sí, puedo asegurar el principio de que nunca usaré más de 8 vCPU, pero me he bloqueado muy temprano en esa tendencia afectando el comportamiento y la escalabilidad de mis cargas de trabajo.
Debido a eso, necesitas ser muy cuidadoso cuando estás definiendo este tipo de límites y asegurarte de lo que estás tratando de lograr porque al resolver un problema puedes estar generando otro.
Espero que esto pueda ayudarte a prevenir que este problema ocurra en tu trabajo diario o al menos tenerlo en cuenta cuando te enfrentes a escenarios similares.