Por lo general, siempre surge la necesidad de proporcionar un conjunto de recursos dedicados a alguna aplicación para su correcto y estable funcionamiento. Pero, ¿qué sucede si varias aplicaciones funcionan simultáneamente en la misma infraestructura? ¿Cómo garantizar que cada una de ellas cuente con los recursos mínimos necesarios? ¿De qué manera se puede limitar el consumo de recursos? ¿Cómo distribuir adecuadamente la carga entre los nodos? ¿Cómo asegurar el funcionamiento del mecanismo de escalado horizontal en caso de un aumento de la carga sobre las aplicaciones?

Lo primero es identificar los principales tipos de recursos que existen en el sistema: esto incluye, por supuesto, el tiempo de CPU y la memoria RAM. En los manifiestos de k8s, estos tipos de recursos se miden en las siguientes unidades:
- CPU — en núcleos
- RAM — en bytes
Además, para cada recurso es posible establecer dos tipos de requisitos: requests y limits. Requests — describe los requisitos mínimos de recursos libres en el nodo para ejecutar el contenedor (y el pod en general), mientras que limits establece un límite estricto de recursos disponibles para el contenedor.
Es importante comprender que no es necesario definir explícitamente ambos tipos en el manifiesto, siendo el comportamiento el siguiente:
- Si solo se especifica explícitamente el límite de un recurso, entonces requests para ese recurso automáticamente adoptará un valor igual a limits (esto se puede verificar al invocar describe en la entidad). Es decir, de hecho, el funcionamiento del contenedor estará limitado a la misma cantidad de recursos que requiere para su ejecución.
- Si para un recurso solo se especifican requests, no se establece ningún límite superior para ese recurso: es decir, el contenedor está limitado solo a los recursos del propio nodo.
También existe la posibilidad de administrar recursos no solo a nivel de un contenedor específico, sino también a nivel de namespace utilizando las siguientes entidades:
- LimitRange — describe la política de límites a nivel de contenedor/pod en el ns y es necesaria para definir las limitaciones predeterminadas en el contenedor/pod, así como para prevenir la creación de contenedores/pods excesivamente grandes (o a la inversa), limitar su cantidad y determinar la posible diferencia de valores en limits y requests.
- ResourceQuotas — describe la política de límites en general para todos los contenedores en el ns y se utiliza, como regla general, para la delimitación de recursos por entornos (útil cuando los entornos no están estrictamente separados a nivel de nodos)
A continuación se presentan ejemplos de manifiestos donde se establecen límites en los recursos:
A nivel de un contenedor específico:
containers: - name: app-nginx image: nginx resources: requests: memory: 1Gi limits: cpu: 200mEs decir, en este caso, se necesitará al menos 1G de RAM libre y 0.2 de CPU en el nodo para ejecutar el contenedor con nginx, siendo que el contenedor puede consumir un máximo de 0.2 de CPU y toda la RAM disponible en el nodo.
A nivel de todo el ns:
apiVersion: v1 kind: ResourceQuota metadata: name: nxs-test spec: hard: requests.cpu: 300m requests.memory: 1Gi limits.cpu: 700m limits.memory: 2GiEs decir, la suma de todas las solicitudes de los contenedores en el ns por defecto no puede exceder 300m para CPU y 1G para RAM, mientras que la suma de todos los límites debe ser 700m para CPU y 2G para RAM.
Límites predeterminados para contenedores en el ns:
apiVersion: v1 kind: LimitRange metadata: name: nxs-limit-per-container spec: limits: - type: Container defaultRequest: cpu: 100m memory: 1Gi default: cpu: 1 memory: 2Gi min: cpu: 50m memory: 500Mi max: cpu: 2 memory: 4GiEs decir, en el namespace por defecto se establecerá una solicitud de 100m para CPU y 1G para RAM para todos los contenedores, y un límite de 1 CPU y 2G. También se ha establecido un límite sobre los valores posibles en las solicitudes/límites para CPU (50m < x < 2) y RAM (500M < x < 4G).
Límites a nivel de pods en el ns:
apiVersion: v1 kind: LimitRange metadata: name: nxs-limit-pod spec: limits: - type: Pod max: cpu: 4 memory: 1GiEs decir, para cada pod en el ns por defecto se establecerá un límite de 4 vCPU y 1G.
Ahora me gustaría hablar sobre las ventajas que la implementación de estos límites puede ofrecernos.
El mecanismo de balanceo de carga entre nodos
Como es sabido, la distribución de pods entre nodos es responsabilidad de un componente de k8s llamado scheduler, que opera según un algoritmo específico. Este algoritmo, durante la selección del nodo óptimo para la ejecución, pasa por dos etapas:
- Filtrado
- Clasificación
Es decir, según la política descrita, inicialmente se seleccionan los nodos en los que es posible ejecutar el pod en función de un conjunto de predicados (incluyendo la comprobación de si hay suficientes recursos en el nodo para ejecutar el pod — PodFitsResources), y luego para cada uno de estos nodos, de acuerdo con prioridades se asignan puntos (es decir, cuanto más recursos libres tenga el nodo, más puntos se le asignan — LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) y se inicia en el nodo con la mayor cantidad de puntos (si varias nodos cumplen con esta condición, se elige uno al azar).
Es importante entender que el scheduler, al evaluar los recursos disponibles en el nodo, se basa en datos almacenados en etcd — es decir, en la suma de los recursos solicitados/límite de cada pod que se ejecuta en ese nodo, pero no en el consumo real de recursos. Esta información se puede obtener con el comando kubectl describe node $NODE, por ejemplo:
# kubectl describe nodes nxs-k8s-s1
..
Non-terminated Pods: (9 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
ingress-nginx nginx-ingress-controller-754b85bf44-qkt2t 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system kube-flannel-26bl4 150m (0%) 300m (1%) 64M (0%) 500M (1%) 233d
kube-system kube-proxy-exporter-cb629 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system kube-proxy-x9fsc 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system nginx-proxy-k8s-worker-s1 25m (0%) 300m (1%) 32M (0%) 512M (1%) 233d
nxs-monitoring alertmanager-main-1 100m (0%) 100m (0%) 425Mi (1%) 25Mi (0%) 233d
nxs-logging filebeat-lmsmp 100m (0%) 0 (0%) 100Mi (0%) 200Mi (0%) 233d
nxs-monitoring node-exporter-v4gdq 112m (0%) 122m (0%) 200Mi (0%) 220Mi (0%) 233d
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 487m (3%) 822m (5%)
memory 15856217600 (2%) 749976320 (3%)
ephemeral-storage 0 (0%) 0 (0%)Aquí vemos todos los pods ejecutándose en un nodo específico, así como los recursos que solicita cada uno de ellos. Así es como aparecen los registros del scheduler al iniciar el pod cronjob-cron-events-1573793820-xt6q9 (esta información aparecerá en el registro del scheduler al establecer el nivel de registro en 10 en los argumentos del comando de inicio —v=10):
registro
I1115 07:57:21.637791 1 scheduling_queue.go:908] A punto de intentar programar el pod nxs-stage/cronjob-cron-events-1573793820-xt6q9
I1115 07:57:21.637804 1 scheduler.go:453] Intentando programar el pod: nxs-stage/cronjob-cron-events-1573793820-xt6q9
I1115 07:57:21.638285 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s5, el Nodo está ejecutando solo 16 de 110 Pods.
I1115 07:57:21.638300 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s6, el Nodo está ejecutando solo 20 de 110 Pods.
I1115 07:57:21.638322 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s3, el Nodo está ejecutando solo 20 de 110 Pods.
I1115 07:57:21.638322 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s4, el Nodo está ejecutando solo 17 de 110 Pods.
I1115 07:57:21.638334 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s10, el Nodo está ejecutando solo 16 de 110 Pods.
I1115 07:57:21.638365 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s12, el Nodo está ejecutando solo 9 de 110 Pods.
I1115 07:57:21.638334 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s11, el Nodo está ejecutando solo 11 de 110 Pods.
I1115 07:57:21.638385 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s1, el Nodo está ejecutando solo 19 de 110 Pods.
I1115 07:57:21.638402 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s2, el Nodo está ejecutando solo 21 de 110 Pods.
I1115 07:57:21.638383 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s9, el Nodo está ejecutando solo 16 de 110 Pods.
I1115 07:57:21.638335 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s8, el Nodo está ejecutando solo 18 de 110 Pods.
I1115 07:57:21.638408 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s13, el Nodo está ejecutando solo 8 de 110 Pods.
I1115 07:57:21.638478 1 predicates.go:1369] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s10, se satisfacen los términos de anti-afinidad de los pods existentes.
I1115 07:57:21.638505 1 predicates.go:1369] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s8, se satisfacen los términos de anti-afinidad de los pods existentes.
I1115 07:57:21.638577 1 predicates.go:1369] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s9, se satisfacen los términos de anti-afinidad de los pods existentes.
I1115 07:57:21.638583 1 predicates.go:829] Se permite programar el Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 en el Nodo nxs-k8s-s7, el Nodo está ejecutando solo 25 de 110 Pods.
I1115 07:57:21.638932 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: BalancedResourceAllocation, capacidad 39900 milicore 66620178432 bytes de memoria, solicitud total 2343 milicore 9640186880 bytes de memoria, puntuación 9
I1115 07:57:21.638946 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: LeastResourceAllocation, capacidad 39900 milicore 66620178432 bytes de memoria, solicitud total 2343 milicore 9640186880 bytes de memoria, puntuación 8
I1115 07:57:21.638961 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: BalancedResourceAllocation, capacidad 39900 milicore 66620170240 bytes de memoria, solicitud total 4107 milicore 11307422720 bytes de memoria, puntuación 9
I1115 07:57:21.638971 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: BalancedResourceAllocation, capacidad 39900 milicore 66620178432 bytes de memoria, solicitud total 5847 milicore 24333637120 bytes de memoria, puntuación 7
I1115 07:57:21.638975 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: LeastResourceAllocation, capacidad 39900 milicore 66620170240 bytes de memoria, solicitud total 4107 milicore 11307422720 bytes de memoria, puntuación 8
I1115 07:57:21.638990 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: LeastResourceAllocation, capacidad 39900 milicore 66620178432 bytes de memoria, solicitud total 5847 milicore 24333637120 bytes de memoria, puntuación 7
I1115 07:57:21.639022 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: TaintTolerationPriority, Puntuación: (10)
I1115 07:57:21.639030 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: TaintTolerationPriority, Puntuación: (10)
I1115 07:57:21.639034 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: TaintTolerationPriority, Puntuación: (10)
I1115 07:57:21.639041 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: NodeAffinityPriority, Puntuación: (0)
I1115 07:57:21.639053 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: NodeAffinityPriority, Puntuación: (0)
I1115 07:57:21.639059 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: NodeAffinityPriority, Puntuación: (0)
I1115 07:57:21.639061 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: InterPodAffinityPriority, Puntuación: (0)
I1115 07:57:21.639063 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: SelectorSpreadPriority, Puntuación: (10)
I1115 07:57:21.639073 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: InterPodAffinityPriority, Puntuación: (0)
I1115 07:57:21.639077 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: SelectorSpreadPriority, Puntuación: (10)
I1115 07:57:21.639085 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: InterPodAffinityPriority, Puntuación: (0)
I1115 07:57:21.639088 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: SelectorSpreadPriority, Puntuación: (10)
I1115 07:57:21.639103 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: SelectorSpreadPriority, Puntuación: (10)
I1115 07:57:21.639109 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: SelectorSpreadPriority, Puntuación: (10)
I1115 07:57:21.639114 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: SelectorSpreadPriority, Puntuación: (10)
I1115 07:57:21.639127 1 generic_scheduler.go:781] Host nxs-k8s-s10 => Puntuación 100037
I1115 07:57:21.639150 1 generic_scheduler.go:781] Host nxs-k8s-s8 => Puntuación 100034
I1115 07:57:21.639154 1 generic_scheduler.go:781] Host nxs-k8s-s9 => Puntuación 100037
I1115 07:57:21.639267 1 scheduler_binder.go:269] Asumir Volúmenes de Pod para el pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", nodo "nxs-k8s-s10"
I1115 07:57:21.639286 1 scheduler_binder.go:279] Asumir Volúmenes de Pod para el pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", nodo "nxs-k8s-s10": todos los PVCs están vinculados y no hay nada que hacer
I1115 07:57:21.639333 1 factory.go:733] Intentando vincular cronjob-cron-events-1573793820-xt6q9 al nxs-k8s-s10Aquí vemos que inicialmente el scheduler filtra y forma una lista de 3 nodos, en los cuales es posible iniciar (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Luego, realiza el conteo de puntos en base a varios parámetros (incluyendo BalancedResourceAllocation, LeastResourceAllocation) para cada uno de estos nodos con el fin de determinar el nodo más adecuado. Al final se despliega en el nodo con más puntos (aquí, dos nodos tienen la misma cantidad de puntos, 100037, por lo que se elige uno aleatoriamente: nxs-k8s-s10).
Salida: si en el nodo están en funcionamiento pods para los cuales no se han establecido límites, para k8s (en términos de consumo de recursos) será como si esos pods no estuvieran presentes en absoluto en ese nodo. Por lo tanto, si tiene, hipotéticamente, un pod con un proceso que consume muchos recursos (por ejemplo, wowza) y no se han establecido límites para él, podría haber una situación en la que este pod consuma todos los recursos del nodo. Sin embargo, para k8s, este nodo se considera sin carga y recibirá la misma cantidad de puntos en la clasificación (específicamente en los puntos de evaluación de recursos disponibles) que un nodo donde no hay pods activos, lo que puede llevar, en última instancia, a una distribución desigual de la carga entre los nodos.
Desalojo de pod
Como se sabe, a cada pod se le asigna una de las 3 clases de QoS:
- garantizada — se asigna cuando para cada contenedor en el pod se han establecido tanto el request como el limit de memoria y CPU, y estos valores deben coincidir
- burstable — al menos un contenedor en el pod tiene request y limit, siendo request < limit
- mejor esfuerzo — cuando ningún contenedor en el pod está limitado en recursos
Además, cuando existe una escasez de recursos (disco, memoria) en el nodo, kubelet comienza a clasificar y desalojar pods según un algoritmo específico que toma en cuenta la prioridad del pod y su clase de QoS. Por ejemplo, si se trata de RAM, se asignan puntos con base en la clase de QoS de la siguiente manera:
- Guaranteed: -998
- BestEffort: 1000
- Burstable: min(max(2, 1000 — (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)
Es decir, con la misma prioridad, kubelet desalojará primero los pods con la clase de QoS de mejor esfuerzo.
Salida: si desea reducir la probabilidad de que un pod necesario sea desalojado de un nodo en caso de escasez de recursos, deberá preocuparse no solo por la prioridad, sino también por establecer request/limit para él.
Mecanismo de escalado automático horizontal de pods de aplicación (HPA)
Cuando se busca aumentar y disminuir automáticamente el número de pods según el uso de recursos (sistémicos — CPU/RAM o de usuario — rps), puede ayudar una entidad de k8s como HPA (Horizontal Pod Autoscaler). Su algoritmo consiste en lo siguiente:
- Se determinan los valores actuales del recurso observado (currentMetricValue)
- Se determinan los valores deseados para el recurso (desiredMetricValue), que para los recursos sistémicos se establecen mediante request
- Se determina el número actual de réplicas (currentReplicas)
- Se calcula el número deseado de réplicas (desiredReplicas) según la siguiente fórmula
desiredReplicas = [ currentReplicas * ( currentMetricValue / desiredMetricValue )]
En este caso, no se producirá escalado cuando el coeficiente (currentMetricValue / desiredMetricValue) esté cerca de 1 (la tolerancia que podemos establecer nosotros mismos, por defecto es 0.1).
Consideremos el funcionamiento del hpa con el ejemplo de la aplicación app-test (descrita como Deployment), donde es necesario cambiar el número de réplicas en función del consumo de CPU:
Manifiesto de la aplicación
kind: Deployment apiVersion: apps/v1beta2 metadata: name: app-test spec: selector: matchLabels: app: app-test replicas: 2 template: metadata: labels: app: app-test spec: containers: - name: nginx image: registry.nixys.ru/generic-images/nginx imagePullPolicy: Always resources: requests: cpu: 60m ports: - name: http containerPort: 80 - name: nginx-exporter image: nginx/nginx-prometheus-exporter resources: requests: cpu: 30m ports: - name: nginx-exporter containerPort: 9113 args: - -nginx.scrape-uri - http://127.0.0.1:80/nginx-statusEs decir, vemos que el pod de la aplicación se inicia inicialmente en dos instancias, cada una de las cuales contiene dos contenedores nginx y nginx-exporter, para cada uno de los cuales se ha establecido requests para CPU.
Manifiesto del HPA
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: app-test-hpa spec: maxReplicas: 10 minReplicas: 2 scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: app-test metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 30Es decir, hemos creado un hpa que supervisará el Deployment app-test y regulará el número de pods de la aplicación en función del índice de cpu (esperamos que el pod consuma el 30% del CPU solicitado), manteniendo el número de réplicas entre 2 y 10.
Ahora consideremos el mecanismo de funcionamiento del hpa al aplicar carga a uno de los pods:
# kubectl top pod NAME CPU(cores) MEMORY(bytes) app-test-78559f8f44-pgs58 101m 243Mi app-test-78559f8f44-cj4jz 4m 240Mi
En total, tenemos lo siguiente:
- El valor deseado (desiredMetricValue) — según la configuración del hpa es igual a 30%
- El valor actual (currentMetricValue) — para el cálculo, el controller-manager calcula el valor promedio del consumo de recursos en %, es decir, hace lo siguiente:
- Obtiene los valores absolutos de las métricas de los pods del metric-server, es decir, 101m y 4m
- Calcula el valor absoluto promedio, es decir, (101m + 4m) / 2 = 53m
- Obtiene el valor absoluto para el consumo deseado de recursos (para esto se suman los requests de todos los contenedores) 60m + 30m = 90m
- Calcula el porcentaje promedio de consumo de CPU en relación con el request del pod, es decir, 53m / 90m * 100% = 59%
Ahora tenemos todo lo necesario para determinar si es necesario cambiar la cantidad de réplicas, para esto calculamos el coeficiente:
ratio = 59% / 30% = 1.96
Es decir, la cantidad de réplicas debe aumentarse en aproximadamente 2 veces y ser [2 * 1.96] = 4.
Salida: Como se puede observar, para que este mecanismo funcione, es condición necesaria tener requests para todos los contenedores en el pod observado.
Mecanismo de escalamiento automático horizontal de nodos (Cluster Autoscaler)
Para mitigar la influencia negativa en el sistema durante picos de carga, tener un hpa configurado a veces no es suficiente. Por ejemplo, según la configuración del hpa, el controller manager decide que es necesario aumentar la cantidad de réplicas en 2 veces, sin embargo, en los nodos no hay recursos libres para ejecutar tal cantidad de pods (es decir, el nodo no puede proporcionar los recursos solicitados por los requests del pod) y esos pods pasan al estado Pendiente.
En este caso, si el proveedor tiene un IaaS/PaaS correspondiente (por ejemplo, GKE/GCE, AKS, EKS, etc.), puede ayudarnos una herramienta como Node Autoscaler. Permite establecer la cantidad máxima y mínima de nodos en el clúster y regula automáticamente la cantidad actual de nodos (mediante la llamada a la API del proveedor de la nube para solicitar/eliminar un nodo), cuando se observa escasez de recursos en el clúster y los pods no pueden ser programados (están en estado Pendiente).
Salida: Para la posibilidad de escalamiento automático de nodos, es necesario establecer requests en los contenedores de los pods, para que k8s pueda evaluar correctamente la carga de los nodos y, en consecuencia, informar que no hay suficientes recursos en el clúster para lanzar un nuevo pod.
Conclusión
Es importante señalar que establecer restricciones de recursos para el contenedor no es un requisito obligatorio para el inicio exitoso de la aplicación, sin embargo, es recomendable hacerlo por las siguientes razones:
- Para que el scheduler funcione de manera más precisa en cuanto al balanceo de carga entre los nodos de k8s
- Para reducir la probabilidad de un evento de “desalojo de pod”
- Para que funcione el escalado automático horizontal de los pods de la aplicación (HPA)
- Para que funcione el escalado automático horizontal de nodos (Cluster Autoscaling) en proveedores de nube
También lee otros artículos en nuestro blog:
Fuente: habr.com
