Kubernetes: ¿por qué es tan importante configurar la gestión de recursos del sistema?

Como regla general, siempre existe la necesidad de proporcionar un conjunto de recursos dedicado a una aplicación para su funcionamiento correcto y estable. Pero ¿qué pasa si varias aplicaciones se ejecutan con la misma potencia? ¿Cómo dotar a cada uno de ellos de los recursos mínimos necesarios? ¿Cómo se puede limitar el consumo de recursos? ¿Cómo distribuir correctamente la carga entre nodos? ¿Cómo garantizar que el mecanismo de escala horizontal funcione si aumenta la carga de la aplicación?

Kubernetes: ¿por qué es tan importante configurar la gestión de recursos del sistema?

Debe comenzar con los principales tipos de recursos que existen en el sistema; esto, por supuesto, es el tiempo del procesador y la 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: solicitudes и límites. Solicitudes: describe los requisitos mínimos de recursos libres de un nodo para ejecutar un contenedor (y el pod en su conjunto), mientras que los límites establecen un límite estricto en los recursos disponibles para el contenedor.

Es importante entender que el manifiesto no tiene por qué definir explícitamente ambos tipos, pero el comportamiento será el siguiente:

  • Si solo se especifican explícitamente los límites de un recurso, las solicitudes de este recurso automáticamente toman un valor igual a los límites (puede verificar esto llamando a describir entidades). Aquellos. de hecho, el contenedor estará limitado a la misma cantidad de recursos que requiere para ejecutarse.
  • Si solo se especifican explícitamente solicitudes para un recurso, entonces no se establecen restricciones superiores en este recurso, es decir, el contenedor está limitado únicamente por los recursos del propio nodo.

También es posible configurar la gestión de recursos no sólo a nivel de un contenedor específico, sino también a nivel de espacio de nombres utilizando las siguientes entidades:

  • LímiteRango — describe la política de restricción a nivel de contenedor/pod en ns y es necesaria para describir los límites predeterminados en el contenedor/pod, así como para evitar la creación de contenedores/pods obviamente gordos (o viceversa), limitar su número y determinar la posible diferencia en los valores en límites y solicitudes
  • Cuotas de recursos — describe la política de restricción en general para todos los contenedores en ns y se utiliza, por regla general, para delimitar recursos entre entornos (útil cuando los entornos no están estrictamente delimitados a nivel de nodo)

Los siguientes son ejemplos de manifiestos que establecen límites de recursos:

  • A nivel de contenedor específico:

    containers:
    - name: app-nginx
      image: nginx
      resources:
        requests:
          memory: 1Gi
        limits:
          cpu: 200m

    Aquellos. en este caso, para ejecutar un contenedor con nginx, necesitará al menos 1G de RAM libre y 0.2 CPU en el nodo, mientras que como máximo el contenedor puede consumir 0.2 CPU y toda la RAM disponible en el nodo.

  • A nivel entero ns:

    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: nxs-test
    spec:
      hard:
        requests.cpu: 300m
        requests.memory: 1Gi
        limits.cpu: 700m
        limits.memory: 2Gi

    Aquellos. la suma de todos los contenedores de solicitudes en el ns predeterminado no puede exceder los 300 m para la CPU y 1G para el OP, y la suma de todos los límites es 700 m para la CPU y 2G para el OP.

  • Límites predeterminados para contenedores en 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: 4Gi

    Aquellos. en el espacio de nombres predeterminado para todos los contenedores, la solicitud se establecerá en 100 m para CPU y 1 G para OP, límite: 1 CPU y 2 G. Al mismo tiempo, también se establece un límite en los posibles valores en solicitud/límite para CPU (50m < x < 2) y RAM (500M < x < 4G).

  • Restricciones a nivel de pod ns:

    apiVersion: v1
    kind: LimitRange
    metadata:
     name: nxs-limit-pod
    spec:
     limits:
     - type: Pod
       max:
         cpu: 4
         memory: 1Gi

    Aquellos. para cada pod en el ns predeterminado habrá un límite de 4 vCPU y 1G.

Ahora me gustaría contaros qué ventajas nos puede aportar establecer estas restricciones.

Mecanismo de equilibrio de carga entre nodos.

Como sabes, el componente k8s es responsable de la distribución de pods entre nodos, como planificador, que funciona según un algoritmo específico. Este algoritmo pasa por dos etapas al seleccionar el nodo óptimo para lanzar:

  1. filtración
  2. rango

Aquellos. De acuerdo con la política descrita, inicialmente se seleccionan nodos en los que es posible lanzar un pod basado en un conjunto predicados (incluida la verificación de si el nodo tiene suficientes recursos para ejecutar el pod: PodFitsResources), y luego para cada uno de estos nodos, de acuerdo con prioridades Se otorgan puntos (incluidos, cuantos más recursos libres tenga un nodo, más puntos se le asignan: LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) y el pod se inicia en el nodo con más puntos (si varios nodos satisfacen esta condición a la vez, entonces se selecciona uno al azar).

Al mismo tiempo, debe comprender que el programador, al evaluar los recursos disponibles de un nodo, se guía por los datos almacenados en etcd, es decir, para la cantidad de recurso solicitado/límite de cada pod que se ejecuta en este nodo, pero no para el consumo de recursos real. Esta información se puede obtener de la salida del 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 que se ejecutan en un nodo específico, así como los recursos que solicita cada pod. Y así es como se ven los registros del programador cuando se inicia el pod cronjob-cron-events-1573793820-xt6q9 (esta información aparecerá en el registro del programador cuando establezca el décimo nivel de registro en los argumentos del comando de inicio -v=10):

gaviota ancha

I1115 07:57:21.637791       1 scheduling_queue.go:908] About to try and schedule pod nxs-stage/cronjob-cron-events-1573793820-xt6q9                                                                                                                                           
I1115 07:57:21.637804       1 scheduler.go:453] Attempting to schedule pod: nxs-stage/cronjob-cron-events-1573793820-xt6q9                                                                                                                                                    
I1115 07:57:21.638285       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s5 is allowed, Node is running only 16 out of 110 Pods.                                                                               
I1115 07:57:21.638300       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s6 is allowed, Node is running only 20 out of 110 Pods.                                                                               
I1115 07:57:21.638322       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s3 is allowed, Node is running only 20 out of 110 Pods.                                                                               
I1115 07:57:21.638322       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s4 is allowed, Node is running only 17 out of 110 Pods.                                                                               
I1115 07:57:21.638334       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s10 is allowed, Node is running only 16 out of 110 Pods.                                                                              
I1115 07:57:21.638365       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s12 is allowed, Node is running only 9 out of 110 Pods.                                                                               
I1115 07:57:21.638334       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s11 is allowed, Node is running only 11 out of 110 Pods.                                                                              
I1115 07:57:21.638385       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s1 is allowed, Node is running only 19 out of 110 Pods.                                                                               
I1115 07:57:21.638402       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s2 is allowed, Node is running only 21 out of 110 Pods.                                                                               
I1115 07:57:21.638383       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s9 is allowed, Node is running only 16 out of 110 Pods.                                                                               
I1115 07:57:21.638335       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s8 is allowed, Node is running only 18 out of 110 Pods.                                                                               
I1115 07:57:21.638408       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s13 is allowed, Node is running only 8 out of 110 Pods.                                                                               
I1115 07:57:21.638478       1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s10 is allowed, existing pods anti-affinity terms satisfied.                                                                         
I1115 07:57:21.638505       1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s8 is allowed, existing pods anti-affinity terms satisfied.                                                                          
I1115 07:57:21.638577       1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s9 is allowed, existing pods anti-affinity terms satisfied.                                                                          
I1115 07:57:21.638583       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s7 is allowed, Node is running only 25 out of 110 Pods.                                                                               
I1115 07:57:21.638932       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: BalancedResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 2343 millicores 9640186880 memory bytes, score 9        
I1115 07:57:21.638946       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: LeastResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 2343 millicores 9640186880 memory bytes, score 8           
I1115 07:57:21.638961       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: BalancedResourceAllocation, capacity 39900 millicores 66620170240 memory bytes, total request 4107 millicores 11307422720 memory bytes, score 9        
I1115 07:57:21.638971       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: BalancedResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 5847 millicores 24333637120 memory bytes, score 7        
I1115 07:57:21.638975       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: LeastResourceAllocation, capacity 39900 millicores 66620170240 memory bytes, total request 4107 millicores 11307422720 memory bytes, score 8           
I1115 07:57:21.638990       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: LeastResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 5847 millicores 24333637120 memory bytes, score 7           
I1115 07:57:21.639022       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: TaintTolerationPriority, Score: (10)                                                                                                        
I1115 07:57:21.639030       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: TaintTolerationPriority, Score: (10)                                                                                                         
I1115 07:57:21.639034       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: TaintTolerationPriority, Score: (10)                                                                                                         
I1115 07:57:21.639041       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: NodeAffinityPriority, Score: (0)                                                                                                            
I1115 07:57:21.639053       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: NodeAffinityPriority, Score: (0)                                                                                                             
I1115 07:57:21.639059       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: NodeAffinityPriority, Score: (0)                                                                                                             
I1115 07:57:21.639061       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: InterPodAffinityPriority, Score: (0)                                                                                                                   
I1115 07:57:21.639063       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: SelectorSpreadPriority, Score: (10)                                                                                                                   
I1115 07:57:21.639073       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: InterPodAffinityPriority, Score: (0)                                                                                                                    
I1115 07:57:21.639077       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: SelectorSpreadPriority, Score: (10)                                                                                                                    
I1115 07:57:21.639085       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: InterPodAffinityPriority, Score: (0)                                                                                                                    
I1115 07:57:21.639088       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: SelectorSpreadPriority, Score: (10)                                                                                                                    
I1115 07:57:21.639103       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: SelectorSpreadPriority, Score: (10)                                                                                                         
I1115 07:57:21.639109       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: SelectorSpreadPriority, Score: (10)                                                                                                          
I1115 07:57:21.639114       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: SelectorSpreadPriority, Score: (10)                                                                                                          
I1115 07:57:21.639127       1 generic_scheduler.go:781] Host nxs-k8s-s10 => Score 100037                                                                                                                                                                            
I1115 07:57:21.639150       1 generic_scheduler.go:781] Host nxs-k8s-s8 => Score 100034                                                                                                                                                                             
I1115 07:57:21.639154       1 generic_scheduler.go:781] Host nxs-k8s-s9 => Score 100037                                                                                                                                                                             
I1115 07:57:21.639267       1 scheduler_binder.go:269] AssumePodVolumes for pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", node "nxs-k8s-s10"                                                                                                               
I1115 07:57:21.639286       1 scheduler_binder.go:279] AssumePodVolumes for pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", node "nxs-k8s-s10": all PVCs bound and nothing to do                                                                             
I1115 07:57:21.639333       1 factory.go:733] Attempting to bind cronjob-cron-events-1573793820-xt6q9 to nxs-k8s-s10

Aquí vemos que inicialmente el planificador filtra y genera una lista de 3 nodos en los que se puede iniciar (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Luego calcula puntuaciones basadas en varios parámetros (incluidos BalancedResourceAllocation, LeastResourceAllocation) para cada uno de estos nodos para determinar el nodo más adecuado. En última instancia, el pod se programa en el nodo con la mayor cantidad de puntos (aquí dos nodos tienen la misma cantidad de puntos a la vez 100037, por lo que se selecciona uno aleatorio: nxs-k8s-s10).

conclusión: si un nodo ejecuta pods para los cuales no se establecen restricciones, entonces para k8 (desde el punto de vista del consumo de recursos) esto será equivalente a como si no existieran tales pods en este nodo. Por lo tanto, si tiene condicionalmente un pod con un proceso glotón (por ejemplo, wowza) y no se le imponen restricciones, entonces puede surgir una situación en la que este pod realmente se comió todos los recursos del nodo, pero para k8 este nodo se considera descargado y se le otorgará la misma cantidad de puntos al clasificarse (precisamente en puntos que evalúan los recursos disponibles) como un nodo que no tiene pods en funcionamiento, lo que en última instancia puede conducir a una distribución desigual de la carga entre los nodos.

El desalojo de la vaina

Como sabes, a cada pod se le asigna una de las 3 clases de QoS:

  1. garantizado — se asigna cuando para cada contenedor en el pod se especifican una solicitud y un límite para la memoria y la CPU, y estos valores deben coincidir
  2. rompible — al menos un contenedor en el pod tiene una solicitud y un límite, con solicitud <límite
  3. mejor esfuerzo — cuando ni un solo contenedor en el pod tiene recursos limitados

Al mismo tiempo, cuando un nodo experimenta una falta de recursos (disco, memoria), kubelet comienza a clasificar y desalojar los pods de acuerdo con un algoritmo específico que tiene en cuenta la prioridad del pod y su clase de QoS. Por ejemplo, si hablamos de RAM, según la clase QoS, los puntos se otorgan de acuerdo con el siguiente principio:

  • Garantizado:-998
  • Mejor esfuerzo: 1000
  • rompible: min(max(2, 1000 - (1000 * memoriaRequestBytes) / máquinaMemoryCapacityBytes), 999)

Aquellos. Con la misma prioridad, el kubelet primero desalojará del nodo los pods con la clase QoS de mejor esfuerzo.

conclusión: si desea reducir la probabilidad de que el pod deseado sea desalojado del nodo en caso de falta de recursos, entonces, junto con la prioridad, también debe encargarse de establecer la solicitud/límite para él.

Mecanismo de escalado automático horizontal de pods de aplicaciones (HPA)

Cuando la tarea es aumentar y disminuir automáticamente la cantidad de pods dependiendo del uso de recursos (sistema - CPU/RAM o usuario - rps), una entidad k8s como HPA (Escalador automático de cápsulas horizontales). cuyo algoritmo es el siguiente:

  1. Se determinan las lecturas actuales del recurso observado (currentMetricValue)
  2. Se determinan los valores deseados para el recurso (desiredMetricValue), que para los recursos del sistema se establecen mediante solicitud
  3. Se determina el número actual de réplicas (currentReplicas)
  4. La siguiente fórmula calcula el número deseado de réplicas (desiredReplicas)
    Réplicas deseadas = [Replicas actuales * (ValorMetricActual / ValorMetricoDeseado)]

En este caso, la escala no se producirá cuando el coeficiente (currentMetricValue / wantedMetricValue) esté cerca de 1 (en este caso, podemos establecer el error permitido nosotros mismos; de forma predeterminada es 0.1).

Veamos cómo funciona hpa usando el ejemplo de la aplicación app-test (descrita como Deployment), donde es necesario cambiar la cantidad de réplicas dependiendo del consumo de CPU:

  • Manifiesto de 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-status

    Aquellos. 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 un especificado solicitudes para CPU.

  • Manifiesto 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: 30

    Aquellos. Creamos un hpa que monitoreará la prueba de implementación de la aplicación y regulará la cantidad de pods con la aplicación según el indicador de CPU (esperamos que el pod consuma el 30% de la CPU que solicita), siendo la cantidad de réplicas en el rango de 2-10.

    Ahora, veamos el mecanismo de funcionamiento del hpa si aplicamos una carga a uno de los hogares:

     # 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 de hpa, tenemos 30%
  • Valor actual (currentMetricValue): para el cálculo, el controlador-administrador calcula el valor promedio del consumo de recursos en %, es decir, condicionalmente hace lo siguiente:
    1. Recibe valores absolutos de las métricas del pod del servidor de métricas, es decir. 101m y 4m
    2. Calcula el valor absoluto medio, es decir (101m + 4m) / 2 = 53m
    3. Obtiene el valor absoluto del consumo de recursos deseado (para ello, se suman las solicitudes de todos los contenedores) 60m + 30m = 90m
    4. Calcula el porcentaje promedio de consumo de CPU en relación con el pod de solicitudes, es decir, 53m / 90m * 100% = 59%

Ahora tenemos todo lo que necesitamos para determinar si necesitamos cambiar el número de réplicas, para ello calculamos el coeficiente:

ratio = 59% / 30% = 1.96

Aquellos. el número de réplicas debe aumentarse aproximadamente 2 veces y ascender a [2 * 1.96] = 4.

Conclusión: Como puede ver, para que este mecanismo funcione, una condición necesaria es la presencia de solicitudes para todos los contenedores en el pod observado.

Mecanismo de escalado automático horizontal de nodos (Cluster Autoscaler)

Para neutralizar el impacto negativo en el sistema durante los aumentos repentinos de carga, no basta con tener un hpa configurado. Por ejemplo, de acuerdo con la configuración en el administrador del controlador hpa, decide que la cantidad de réplicas debe aumentarse 2 veces, pero los nodos no tienen recursos libres para ejecutar tal cantidad de pods (es decir, el nodo no puede proporcionar la recursos solicitados al pod de solicitudes) y estos pods cambian al estado Pendiente.

En este caso, si el proveedor tiene una IaaS/PaaS correspondiente (por ejemplo, GKE/GCE, AKS, EKS, etc.), una herramienta como Escalador automático de nodos. Le permite establecer la cantidad máxima y mínima de nodos en el clúster y ajustar automáticamente la cantidad actual de nodos (llamando a la API del proveedor de la nube para ordenar/eliminar un nodo) cuando faltan recursos en el clúster y los pods. no se pueden programar (están en estado Pendiente).

Conclusión: Para poder escalar automáticamente los nodos, es necesario configurar solicitudes en los contenedores del pod para que k8s pueda evaluar correctamente la carga en los nodos y, en consecuencia, informar que no hay recursos en el clúster para lanzar el siguiente pod.

Conclusión

Cabe señalar que establecer límites de recursos del contenedor no es un requisito para que la aplicación se ejecute correctamente, pero es mejor hacerlo por las siguientes razones:

  1. Para un funcionamiento más preciso del programador en términos de equilibrio de carga entre nodos k8s
  2. Para reducir la probabilidad de que ocurra un evento de “desalojo de cápsulas”
  3. Para que funcione el escalado automático horizontal de pods de aplicaciones (HPA)
  4. Para escalado automático horizontal de nodos (Cluster Autoscaling) para proveedores de nube

Lea también otros artículos en nuestro blog:

Fuente: habr.com

Añadir un comentario