Kubernetes: por que é tan importante configurar a xestión de recursos do sistema?

Como regra xeral, sempre hai que proporcionar un conxunto de recursos dedicados a unha aplicación para o seu funcionamento correcto e estable. Pero que pasa se varias aplicacións funcionan coa mesma enerxía? Como dotar a cada un deles dos recursos mínimos necesarios? Como se pode limitar o consumo de recursos? Como distribuír correctamente a carga entre os nodos? Como garantir o funcionamento do mecanismo de escala horizontal se a carga da aplicación aumenta?

Kubernetes: por que é tan importante configurar a xestión de recursos do sistema?

Debe comezar cos principais tipos de recursos que existen no sistema: isto, por suposto, é o tempo do procesador e a memoria RAM. Nos manifestos k8s estes tipos de recursos mídense nas seguintes unidades:

  • CPU - en núcleos
  • RAM - en bytes

Ademais, para cada recurso é posible establecer dous tipos de requisitos: solicitudes и límites. Solicitudes: describe os requisitos mínimos dos recursos gratuítos dun nodo para executar un contedor (e un pod no seu conxunto), mentres que os límites establecen un límite estricto aos recursos dispoñibles para o contedor.

É importante entender que o manifesto non ten que definir explícitamente ambos tipos, pero o comportamento será o seguinte:

  • Se só se especifican explícitamente os límites dun recurso, entón as solicitudes deste recurso tomarán automaticamente un valor igual aos límites (podes verificar isto chamando ás entidades describe). Eses. de feito, o contedor estará limitado á mesma cantidade de recursos que precisa para funcionar.
  • Se só se especifican de xeito explícito as solicitudes para un recurso, non se establecen restricións superiores neste recurso, é dicir. o contedor está limitado só polos recursos do propio nodo.

Tamén é posible configurar a xestión de recursos non só a nivel dun contedor específico, senón tamén a nivel de espazo de nomes mediante as seguintes entidades:

  • Rango límite — describe a política de restrición a nivel de recipiente/vaina en ns e é necesaria para describir os límites predeterminados do recipiente/vaina, así como evitar a creación de recipientes/vainas obviamente gordos (ou viceversa), limitar o seu número e determinar a posible diferenza nos valores en límites e solicitudes
  • Cotas de recursos — describir a política de restrición en xeral para todos os contedores en ns e utilízase, como regra, para delimitar recursos entre ambientes (útil cando os ambientes non están estrictamente delimitados a nivel de nodos)

Os seguintes son exemplos de manifestos 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

    Eses. neste caso, para executar un contedor con nginx, necesitará polo menos 1G de RAM libre e 0.2 CPU no nodo, mentres que como máximo o contedor pode consumir 0.2 CPU e toda a RAM dispoñible no nodo.

  • A nivel enteiro ns:

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

    Eses. a suma de todos os contedores de solicitude no ns predeterminado non pode superar os 300 m para a CPU e 1G para o OP, e a suma de todos os límites é de 700 m para a CPU e 2G para o OP.

  • Límites predeterminados para contedores 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

    Eses. no espazo de nomes predeterminado para todos os contedores, a solicitude establecerase en 100 m para CPU e 1G para OP, límite: 1 CPU e 2G. Ao mesmo tempo, tamén se establece un límite nos posibles valores en solicitude/límite para CPU (50m < x < 2) e RAM (500M < x < 4G).

  • Restricións a nivel de pod ns:

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

    Eses. para cada pod no ns predeterminado haberá un límite de 4 vCPU e 1G.

Agora gustaríame dicirvos cales son as vantaxes que nos pode dar establecer estas restricións.

Mecanismo de equilibrio de carga entre nodos

Como sabes, o compoñente k8s é responsable da distribución de pods entre nós, como planificador, que funciona segundo un algoritmo específico. Este algoritmo pasa por dúas etapas á hora de seleccionar o nodo óptimo para lanzar:

  1. filtrado
  2. Variando

Eses. segundo a política descrita, selecciónanse inicialmente os nodos nos que é posible lanzar un pod baseado nun conxunto predicados (incluíndo a comprobación de se o nodo ten recursos suficientes para executar o pod - PodFitsResources), e despois para cada un destes nodos, segundo prioridades outórganse puntos (incluíndo, cantos máis recursos gratuítos teña un nodo, máis puntos se lle asignen - LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) e o pod lánzase no nodo con máis puntos (se varios nodos cumpren esta condición á vez, entón se selecciona un aleatorio).

Ao mesmo tempo, cómpre entender que o planificador, ao avaliar os recursos dispoñibles dun nodo, está guiado polos datos que se almacenan en etcd, é dicir. para a cantidade de recurso solicitado/límite de cada pod que se executa neste nodo, pero non para o consumo real de recursos. Esta información pódese obter da saída do comando kubectl describe node $NODE, por exemplo:

# 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 os pods que se executan nun nodo específico, así como os recursos que cada pod solicita. E aquí está o aspecto dos rexistros do planificador cando se inicia o pod cronjob-cron-events-1573793820-xt6q9 (esta información aparecerá no rexistro do planificador cando estableza o décimo nivel de rexistro nos argumentos do comando de inicio -v=10):

rexistro

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 o planificador filtra e xera unha lista de 3 nodos nos que se pode lanzar (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). A continuación, calcula as puntuacións en función de varios parámetros (incluíndo BalancedResourceAllocation, LeastResourceAllocation) para cada un destes nodos co fin de determinar o nodo máis axeitado. En definitiva, o pod está programado no nodo con maior número de puntos (aquí dous nodos á vez teñen o mesmo número de puntos 100037, polo que se selecciona un aleatorio: nxs-k8s-s10).

Saída: se un nodo executa pods para os que non se establecen restricións, entón para k8s (desde o punto de vista do consumo de recursos) isto será equivalente a que non houbese tales pods neste nodo. Polo tanto, se tes, condicionalmente, un pod cun proceso glotón (por exemplo, wowza) e non se establecen restricións para el, entón pode xurdir unha situación cando este pod consumiu realmente todos os recursos do nodo, pero para k8s este nodo considérase descargado e outorgaráselle o mesmo número de puntos á hora de clasificar (precisamente en puntos que avalían os recursos dispoñibles) que un nodo que non teña pods de traballo, o que finalmente pode levar a unha distribución desigual da carga entre nodos.

Desaloxo de Pod

Como sabes, a cada pod ten asignada unha das 3 clases de QoS:

  1. garantido — atribúese cando para cada contedor do pod se especifica unha solicitude e un límite para a memoria e a CPU, e estes valores deben coincidir
  2. estourable — polo menos un contedor do pod ten unha solicitude e un límite, con solicitude < límite
  3. mellor esforzo — cando nin un só contedor da vaina teña recursos limitados

Ao mesmo tempo, cando un nodo experimenta unha falta de recursos (disco, memoria), kubelet comeza a clasificar e desaloxar os pods segundo un algoritmo específico que ten en conta a prioridade do pod e a súa clase de QoS. Por exemplo, se falamos de RAM, en base á clase de QoS, os puntos concédense segundo o seguinte principio:

  • Garantida: -998
  • Mellor Esforzo: 1000
  • Burstable: min(max (2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

Eses. coa mesma prioridade, o kubelet expulsará primeiro os pods coa clase de QoS do mellor esforzo do nodo.

Saída: se quere reducir a probabilidade de que o pod desexado sexa desaloxado do nodo en caso de falta de recursos nel, entón, xunto coa prioridade, tamén debe ocuparse de establecer a solicitude/límite para el.

Mecanismo de escalado automático horizontal de módulos de aplicación (HPA)

Cando a tarefa é aumentar e diminuír automaticamente o número de pods dependendo do uso dos recursos (sistema - CPU/RAM ou usuario - rps), unha entidade k8s como HPA (Horizontal Pod Autoscaler). O algoritmo do cal é o seguinte:

  1. Determináronse as lecturas actuais do recurso observado (currentMetricValue)
  2. Determínanse os valores desexados para o recurso (desiredMetricValue), que para os recursos do sistema establécense mediante a solicitude
  3. Determínase o número actual de réplicas (currentReplicas)
  4. A seguinte fórmula calcula o número desexado de réplicas (réplicas desexadas)
    Réplicas desexadas = [ Réplicas actuais * (ValorMetrica actual /ValorMetrica desexada )]

Neste caso, a escala non se producirá cando o coeficiente (currentMetricValue / wantMetricValue) sexa próximo a 1 (neste caso, podemos establecer o erro permitido nós mesmos; por defecto é 0.1).

Vexamos como funciona hpa usando o exemplo da aplicación de proba de aplicacións (descrita como Implementación), onde é necesario cambiar o número de réplicas dependendo do consumo da CPU:

  • Manifesto da solicitude

    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

    Eses. vemos que o pod de aplicación lanzase inicialmente en dúas instancias, cada unha das cales contén dous contedores nginx e nginx-exporter, para cada un dos cales un solicitudes para CPU.

  • Manifesto 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

    Eses. Creamos un hpa que supervisará a proba da aplicación de implementación e axustará o número de pods coa aplicación en función do indicador da CPU (esperamos que o pod consuma o 30 % da CPU que solicita), co número de réplicas en rango de 2-10.

    Agora, vexamos o mecanismo de funcionamento de hpa se aplicamos unha carga a un dos fogares:

     # kubectl top pod
    NAME                                                   CPU(cores)   MEMORY(bytes)
    app-test-78559f8f44-pgs58            101m         243Mi
    app-test-78559f8f44-cj4jz            4m           240Mi

En total temos o seguinte:

  • O valor desexado (desiredMetricValue): segundo a configuración de hpa, temos un 30%
  • Valor actual (currentMetricValue): para o cálculo, o controlador-xestor calcula o valor medio do consumo de recursos en %, é dicir. condicionalmente fai o seguinte:
    1. Recibe valores absolutos das métricas de pod do servidor de métricas, é dicir. 101 m e 4 m
    2. Calcula o valor absoluto medio, é dicir. (101 m + 4 m) / 2 = 53 m
    3. Obtén o valor absoluto para o consumo de recursos desexado (para iso, as solicitudes de todos os contedores son resumidas) 60m + 30m = 90m
    4. Calcula a porcentaxe media de consumo de CPU en relación ao pod de solicitude, é dicir. 53 min/90 min * 100 % = 59 %

Agora temos todo o necesario para determinar se hai que cambiar o número de réplicas; para iso, calculamos o coeficiente:

ratio = 59% / 30% = 1.96

Eses. o número de réplicas debería aumentarse en ~2 veces e ascender a [2 * 1.96] = 4.

Conclusión: Como podes ver, para que este mecanismo funcione, unha condición necesaria é a presenza de solicitudes para todos os contedores na vaina observada.

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

Para neutralizar o impacto negativo sobre o sistema durante os aumentos de carga, non é suficiente ter un hpa configurado. Por exemplo, segundo a configuración do xestor do controlador hpa, decide que o número de réplicas debe aumentarse 2 veces, pero os nodos non teñen recursos gratuítos para executar tal número de pods (é dicir, o nodo non pode proporcionar o recursos solicitados ao módulo de solicitudes) e estes módulos cambian ao estado Pendente.

Neste caso, se o provedor ten un IaaS/PaaS correspondente (por exemplo, GKE/GCE, AKS, EKS, etc.), unha ferramenta como Escalador automático de nodos. Permítelle establecer o número máximo e mínimo de nós no clúster e axustar automaticamente o número actual de nós (chamando á API do provedor de nube para ordenar/eliminar un nodo) cando faltan recursos no clúster e nos pods. non se poden programar (están no estado Pendente).

Conclusión: Para poder escalar os nodos automaticamente, é necesario establecer solicitudes nos contedores de pods para que k8s poida avaliar correctamente a carga dos nodos e, en consecuencia, informar de que non hai recursos no clúster para lanzar o seguinte pod.

Conclusión

Nótese que establecer límites de recursos do contedor non é un requisito para que a aplicación se execute correctamente, pero aínda así é mellor facelo polos seguintes motivos:

  1. Para un funcionamento máis preciso do planificador en termos de equilibrio de carga entre os nodos k8s
  2. Para reducir a probabilidade de que se produza un evento de "desaloxo de vainas".
  3. Para que funcione a escala automática horizontal de módulos de aplicación (HPA).
  4. Para a escala automática horizontal de nodos (Cluster Autoscaling) para provedores de nube

Lea tamén outros artigos no noso blog:

Fonte: www.habr.com

Engadir un comentario