Kubernetes: per què és tan important configurar la gestió de recursos del sistema?

Per regla general, sempre hi ha la necessitat de proporcionar un conjunt de recursos dedicats a una aplicació per al seu funcionament correcte i estable. Però, què passa si s'executen diverses aplicacions amb la mateixa potència? Com dotar a cadascun d'ells dels recursos mínims necessaris? Com es pot limitar el consum de recursos? Com distribuir correctament la càrrega entre els nodes? Com assegurar-se que el mecanisme d'escala horitzontal funciona si la càrrega de l'aplicació augmenta?

Kubernetes: per què és tan important configurar la gestió de recursos del sistema?

Heu de començar amb quins tipus principals de recursos existeixen al sistema: això, per descomptat, és el temps del processador i la memòria RAM. En els manifests k8s, aquests tipus de recursos es mesuren en les unitats següents:

  • CPU - en nuclis
  • RAM - en bytes

A més, per a cada recurs es poden establir dos tipus de requisits: peticions и límits. Sol·licituds: descriu els requisits mínims per als recursos lliures d'un node per executar un contenidor (i un pod en conjunt), mentre que els límits estableixen un límit dur als recursos disponibles per al contenidor.

És important entendre que el manifest no ha de definir explícitament els dos tipus, però el comportament serà el següent:

  • Si només s'especifiquen explícitament els límits d'un recurs, aleshores les sol·licituds d'aquest recurs prenen automàticament un valor igual als límits (podeu verificar-ho trucant a les entitats descriu). Aquells. de fet, el contenidor estarà limitat a la mateixa quantitat de recursos que necessita per funcionar.
  • Si només s'especifiquen de manera explícita les sol·licituds per a un recurs, no s'estableixen restriccions superiors en aquest recurs, és a dir. el contenidor només està limitat pels recursos del propi node.

També és possible configurar la gestió de recursos no només a nivell d'un contenidor específic, sinó també a nivell d'espai de noms mitjançant les entitats següents:

  • Interval límit — descriu la política de restricció a nivell de contenidor/pod en ns i és necessària per descriure els límits predeterminats del contenidor/pod, així com evitar la creació de contenidors/pods òbviament grassos (o viceversa), limitar-ne el nombre i determinar la possible diferència en els valors en límits i peticions
  • Quotes de recursos — descriure la política de restricció en general per a tots els contenidors en ns i s'utilitza, per regla general, per delimitar recursos entre entorns (útil quan els entorns no estan estrictament delimitats a nivell de node)

Els següents són exemples de manifests que estableixen límits de recursos:

  • A nivell de contenidor específic:

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

    Aquells. en aquest cas, per executar un contenidor amb nginx, necessitareu almenys 1 G de RAM lliure i 0.2 CPU al node, mentre que com a màxim el contenidor pot consumir 0.2 CPU i tota la RAM disponible al node.

  • A nivell enter ns:

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

    Aquells. la suma de tots els contenidors de sol·licitud en els ns predeterminats no pot superar els 300 m per a la CPU i 1 G per a l'OP, i la suma de tots els límits és de 700 m per a la CPU i 2G per a l'OP.

  • Límits per defecte per als contenidors 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

    Aquells. a l'espai de noms predeterminat per a tots els contenidors, la sol·licitud s'establirà en 100 m per a CPU i 1G per a OP, límit: 1 CPU i 2G. Al mateix temps, també s'estableix un límit als valors possibles en petició/límit per a CPU (50m < x < 2) i RAM (500M < x < 4G).

  • Restriccions a nivell de pod ns:

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

    Aquells. per a cada pod del ns predeterminat hi haurà un límit de 4 vCPU i 1G.

Ara m'agradaria dir-vos quins avantatges ens pot donar establir aquestes restriccions.

Mecanisme d'equilibri de càrrega entre nodes

Com sabeu, el component k8s és responsable de la distribució de pods entre nodes, com ara planificador, que funciona segons un algorisme específic. Aquest algorisme passa per dues etapes a l'hora de seleccionar el node òptim per llançar:

  1. filtració
  2. Avançant

Aquells. d'acord amb la política descrita, inicialment es seleccionen nodes sobre els quals és possible llançar un pod basat en un conjunt predicats (inclosa la comprovació de si el node té prou recursos per executar el pod - PodFitsResources), i després per a cadascun d'aquests nodes, segons prioritats s'atorguen punts (incloent-hi, com més recursos lliures tingui un node, més punts s'assigna - LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) i el pod es llança al node amb més punts (si diversos nodes compleixen aquesta condició alhora, aleshores se n'ha seleccionat un a l'atzar).

Al mateix temps, cal entendre que el planificador, quan avalua els recursos disponibles d'un node, es guia per les dades que s'emmagatzemen a etcd, és a dir. per a la quantitat del recurs sol·licitat/limitat de cada pod que s'executa en aquest node, però no pel consum real de recursos. Aquesta informació es pot obtenir de la sortida de l'ordre kubectl describe node $NODE, per exemple:

# 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í veiem tots els pods que s'executen en un node específic, així com els recursos que cada pod sol·licita. I aquí és com es veuen els registres del planificador quan s'inicia el pod cronjob-cron-events-1573793820-xt6q9 (aquesta informació apareixerà al registre del planificador quan establiu el desè nivell de registre als arguments de l'ordre d'inici -v=10):

registre

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í veiem que inicialment el planificador filtra i genera una llista de 3 nodes sobre els quals es pot llançar (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). A continuació, calcula puntuacions en funció de diversos paràmetres (incloent BalancedResourceAllocation, LeastResourceAllocation) per a cadascun d'aquests nodes per tal de determinar el node més adequat. En última instància, el pod es programa al node amb el nombre més alt de punts (aquí dos nodes alhora tenen el mateix nombre de punts 100037, de manera que se'n selecciona un a l'atzar: nxs-k8s-s10).

Sortida: si un node executa pods per als quals no s'estableixen restriccions, llavors per a k8s (des del punt de vista del consum de recursos) serà equivalent a com si no hi hagués cap pods en aquest node. Per tant, si, condicionalment, teniu un pod amb un procés glotós (per exemple, wowza) i no hi ha cap restricció establerta, aleshores es pot produir una situació quan aquest pod realment es menja tots els recursos del node, però per a k8s aquest node es considera descarregat i se li atorgarà el mateix nombre de punts a l'hora de classificar-se (precisament en punts que avaluen els recursos disponibles) que un node que no té pods de treball, cosa que en última instància pot provocar una distribució desigual de la càrrega entre nodes.

Desnonament de Pod

Com ja sabeu, a cada pod se li assigna una de les 3 classes de QoS:

  1. garantida — s'assigna quan per a cada contenidor del pod s'especifiquen una sol·licitud i un límit per a la memòria i la CPU, i aquests valors han de coincidir
  2. esclatable — Almenys un contenidor del pod té una sol·licitud i un límit, amb petició < límit
  3. el millor esforç — quan ni un sol contenidor de la beina té recursos limitats

Al mateix temps, quan un node experimenta una manca de recursos (disc, memòria), kubelet comença a classificar i desallotjar els pods segons un algorisme específic que té en compte la prioritat del pod i la seva classe de QoS. Per exemple, si parlem de RAM, basant-nos en la classe QoS, els punts s'atorguen segons el principi següent:

  • Garantit: -998
  • El millor esforç: 1000
  • Esclatable: min(màx (2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

Aquells. amb la mateixa prioritat, el kubelet desallotjarà primer les beines amb la millor classe de QoS del node.

Sortida: si voleu reduir la probabilitat que el pod desitjat sigui desallotjat del node en cas de falta de recursos en ell, aleshores, juntament amb la prioritat, també us heu de preocupar d'establir-ne la sol·licitud/límit.

Mecanisme per a l'escalat automàtic horitzontal de pods d'aplicació (HPA)

Quan la tasca és augmentar i disminuir automàticament el nombre de pods en funció de l'ús dels recursos (sistema - CPU/RAM o usuari - rps), una entitat k8s com ara HPA (Horizontal Pod Autoscaler). L'algorisme del qual és el següent:

  1. Es determinen les lectures actuals del recurs observat (currentMetricValue)
  2. Es determinen els valors desitjats per al recurs (desiredMetricValue), que per als recursos del sistema s'estableixen mitjançant la sol·licitud
  3. Es determina el nombre actual de rèpliques (currentReplicas)
  4. La fórmula següent calcula el nombre desitjat de rèpliques (desiredReplicas)
    desitjatReplicas = [currentReplicas * ( currentMetricValue / wishMetricValue )]

En aquest cas, l'escala no es produirà quan el coeficient (currentMetricValue / wishMetricValue) sigui proper a 1 (en aquest cas, podem establir l'error admissible nosaltres mateixos; per defecte és 0.1).

Vegem com funciona hpa utilitzant l'exemple de l'aplicació app-test (descrita com a Deployment), on cal canviar el nombre de rèpliques en funció del consum de CPU:

  • Manifest de la sol·licitud

    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

    Aquells. veiem que el pod d'aplicació es llança inicialment en dos casos, cadascun dels quals conté dos contenidors nginx i nginx-exporter, per a cadascun dels quals peticions per a la CPU.

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

    Aquells. Hem creat un hpa que supervisarà la prova de l'aplicació de desplegament i ajustarà el nombre de pods amb l'aplicació en funció de l'indicador de la CPU (esperem que el pod consumeixi el 30% de la CPU que sol·licita), amb el nombre de rèpliques en el rang de 2-10.

    Ara, mirem el mecanisme de funcionament de hpa si apliquem una càrrega a una de les llars:

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

En total tenim el següent:

  • El valor desitjat (desiredMetricValue): segons la configuració de hpa, tenim un 30%
  • Valor actual (currentMetricValue): per al càlcul, el gestor-controlador calcula el valor mitjà del consum de recursos en %, és a dir. condicionalment fa el següent:
    1. Rep valors absoluts de mètriques pod del servidor de mètriques, és a dir. 101 m i 4 m
    2. Calcula el valor absolut mitjà, és a dir. (101m + 4m) / 2 = 53m
    3. Obté el valor absolut del consum de recursos desitjat (per a això, es resumeixen les peticions de tots els contenidors) 60m + 30m = 90m
    4. Calcula el percentatge mitjà de consum de CPU en relació al pod de sol·licitud, és a dir. 53 m/90 m * 100 % = 59 %

Ara tenim tot el que necessitem per determinar si hem de canviar el nombre de rèpliques; per fer-ho, calculem el coeficient:

ratio = 59% / 30% = 1.96

Aquells. el nombre de rèpliques s'hauria d'augmentar en ~ 2 vegades i ascendir a [2 * 1.96] = 4.

Conclusió: Com podeu veure, perquè aquest mecanisme funcioni, una condició necessària és la presència de sol·licituds per a tots els contenidors del pod observat.

Mecanisme per a l'escalat automàtic horitzontal dels nodes (Cluster Autoscaler)

Per neutralitzar l'impacte negatiu en el sistema durant les pujades de càrrega, no n'hi ha prou amb un hpa configurat. Per exemple, segons la configuració del gestor del controlador hpa, decideix que el nombre de rèpliques s'ha d'augmentar 2 vegades, però els nodes no tenen recursos gratuïts per executar aquest nombre de pods (és a dir, el node no pot proporcionar el recursos sol·licitats al pod de sol·licituds) i aquests pods canvien a l'estat Pendent.

En aquest cas, si el proveïdor té un IaaS/PaaS corresponent (per exemple, GKE/GCE, AKS, EKS, etc.), una eina com ara Node Autoscaler. Us permet establir el nombre màxim i mínim de nodes al clúster i ajustar automàticament el nombre actual de nodes (trucant a l'API del proveïdor de núvol per demanar/eliminar un node) quan hi ha una manca de recursos al clúster i als pods. no es poden programar (estan a l'estat Pendent).

Conclusió: Per poder escalar els nodes automàticament, cal establir sol·licituds als contenidors de pods perquè els k8s puguin avaluar correctament la càrrega dels nodes i, en conseqüència, informar que no hi ha recursos al clúster per llançar el següent pod.

Conclusió

Cal tenir en compte que establir límits de recursos del contenidor no és un requisit perquè l'aplicació s'executi correctament, però encara és millor fer-ho per les raons següents:

  1. Per a un funcionament més precís del planificador pel que fa a l'equilibri de càrrega entre els nodes k8s
  2. Per reduir la probabilitat que es produeixi un esdeveniment de "desnonament de la beina".
  3. Perquè funcioni l'escalat automàtic horitzontal dels pods d'aplicacions (HPA).
  4. Per a l'escalat automàtic horitzontal de nodes (Cluster Autoscaling) per a proveïdors de núvol

Llegiu també altres articles al nostre blog:

Font: www.habr.com

Afegeix comentari