Kubernetes: waarom is het zo belangrijk om systeemresourcebeheer te configureren?

In de regel is er altijd behoefte aan een specifieke pool van bronnen voor een applicatie voor een correcte en stabiele werking ervan. Maar wat als meerdere applicaties op hetzelfde vermogen draaien? Hoe kunnen we elk van hen voorzien van de minimaal noodzakelijke middelen? Hoe kun je het verbruik van hulpbronnen beperken? Hoe de belasting correct tussen knooppunten verdelen? Hoe zorg je ervoor dat het horizontale schaalmechanisme werkt als de applicatiebelasting toeneemt?

Kubernetes: waarom is het zo belangrijk om systeemresourcebeheer te configureren?

U moet beginnen met welke hoofdtypen bronnen er in het systeem bestaan ​​- dit zijn natuurlijk processortijd en RAM. In k8s-manifesten worden deze resourcetypen gemeten in de volgende eenheden:

  • CPU - in kernen
  • RAM-in bytes

Bovendien is het voor elke hulpbron mogelijk om twee soorten eisen te stellen: verzoeken и grenzen. Verzoeken - beschrijft de minimale vereisten voor vrije bronnen van een knooppunt om een ​​container (en pod als geheel) uit te voeren, terwijl limieten een harde limiet stellen aan de bronnen die beschikbaar zijn voor de container.

Het is belangrijk om te begrijpen dat het manifest niet beide typen expliciet hoeft te definiëren, maar dat het gedrag als volgt zal zijn:

  • Als alleen de limieten van een bron expliciet zijn opgegeven, nemen aanvragen voor deze bron automatisch een waarde aan die gelijk is aan limieten (u kunt dit verifiëren door beschrijvende entiteiten aan te roepen). Die. in feite zal de container beperkt zijn tot dezelfde hoeveelheid bronnen die nodig is om te draaien.
  • Als alleen verzoeken expliciet zijn gespecificeerd voor een bron, worden er geen hogere beperkingen ingesteld voor deze bron, d.w.z. de container wordt alleen beperkt door de bronnen van het knooppunt zelf.

Het is ook mogelijk om resourcebeheer niet alleen op het niveau van een specifieke container te configureren, maar ook op naamruimteniveau met behulp van de volgende entiteiten:

  • Limietbereik — beschrijft het beperkingsbeleid op container/pod-niveau in ns en is nodig om de standaardlimieten voor de container/pod te beschrijven, en om de creatie van duidelijk dikke containers/pods te voorkomen (of omgekeerd), en hun aantal te beperken en bepaal het mogelijke verschil in de waarden in limieten en verzoeken
  • Resourcequota — beschrijf het beperkingsbeleid in het algemeen voor alle containers in ns en wordt in de regel gebruikt om bronnen tussen omgevingen af ​​te bakenen (handig als omgevingen niet strikt afgebakend zijn op knooppuntniveau)

Hieronder volgen voorbeelden van manifesten die resourcelimieten instellen:

  • Op specifiek containerniveau:

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

    Die. in dit geval heb je, om een ​​container met nginx uit te voeren, minimaal 1 G vrij RAM en 0.2 CPU op het knooppunt nodig, terwijl de container maximaal 0.2 CPU en al het beschikbare RAM op het knooppunt kan verbruiken.

  • Op geheel getalniveau ns:

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

    Die. de som van alle aanvraagcontainers in de standaard ns mag niet groter zijn dan 300 m voor de CPU en 1G voor de OP, en de som van alle limieten is 700 m voor de CPU en 2G voor de OP.

  • Standaardlimieten voor containers in 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

    Die. in de standaardnaamruimte voor alle containers wordt het verzoek ingesteld op 100 m voor CPU en 1G voor OP, limiet - 1 CPU en 2G. Tegelijkertijd wordt er ook een limiet ingesteld op de mogelijke waarden in request/limit voor CPU (50m < x < 2) en RAM (500M < x < 4G).

  • Beperkingen op podniveau ns:

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

    Die. voor elke pod in de standaard ns geldt een limiet van 4 vCPU en 1G.

Nu zou ik u willen vertellen welke voordelen het instellen van deze beperkingen ons kan opleveren.

Mechanisme voor taakverdeling tussen knooppunten

Zoals u weet is de k8s-component verantwoordelijk voor de distributie van pods over knooppunten, zoals scheduler, dat werkt volgens een specifiek algoritme. Dit algoritme doorloopt twee fasen bij het selecteren van het optimale knooppunt om te starten:

  1. filtering
  2. Variërend

Die. volgens het beschreven beleid worden in eerste instantie knooppunten geselecteerd waarop het mogelijk is een pod te starten op basis van een set predikaten (inclusief het controleren of het knooppunt voldoende bronnen heeft om de pod uit te voeren - PodFitsResources), en vervolgens voor elk van deze knooppunten, volgens prioriteiten er worden punten toegekend (inclusief hoe meer vrije bronnen een knooppunt heeft, hoe meer punten het wordt toegewezen - LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) en de pod wordt gelanceerd op het knooppunt met de meeste punten (als meerdere knooppunten tegelijk aan deze voorwaarde voldoen, dan er wordt een willekeurige geselecteerd).

Tegelijkertijd moet u begrijpen dat de planner bij het beoordelen van de beschikbare bronnen van een knooppunt zich laat leiden door de gegevens die zijn opgeslagen in etcd - d.w.z. voor de hoeveelheid aangevraagde/gelimiteerde resource van elke pod die op dit knooppunt wordt uitgevoerd, maar niet voor het werkelijke resourceverbruik. Deze informatie kan worden verkregen uit de opdrachtuitvoer kubectl describe node $NODE, bijvoorbeeld:

# 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%)

Hier zien we alle pods die op een specifiek knooppunt draaien, evenals de bronnen die elke pod vraagt. En zo zien de plannerlogboeken eruit wanneer de cronjob-cron-events-1573793820-xt6q9 pod wordt gestart (deze informatie zal verschijnen in het plannerlogboek wanneer u het 10e logniveau instelt in de opstartopdrachtargumenten -v=10):

loggen

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

Hier zien we dat de planner aanvankelijk filtert en een lijst genereert met 3 knooppunten waarop deze kan worden gestart (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Vervolgens berekent het scores op basis van verschillende parameters (waaronder BalancedResourceAllocation, LeastResourceAllocation) voor elk van deze knooppunten om het meest geschikte knooppunt te bepalen. Uiteindelijk wordt de pod gepland op het knooppunt met het hoogste aantal punten (hier hebben twee knooppunten tegelijk hetzelfde aantal punten 100037, dus er wordt een willekeurig knooppunt geselecteerd: nxs-k8s-s10).

Uitgang: als een knooppunt pods uitvoert waarvoor geen beperkingen zijn ingesteld, dan zal dit voor k8s (vanuit het oogpunt van hulpbronnengebruik) gelijk zijn aan alsof er helemaal geen pods op dit knooppunt zouden zijn. Daarom, als je voorwaardelijk een pod hebt met een vraatzuchtig proces (bijvoorbeeld wowza) en er geen beperkingen aan zijn gesteld, dan kan er een situatie ontstaan ​​waarin deze pod feitelijk alle bronnen van het knooppunt opeet, maar voor k8s is dit knooppunt wordt als onbelast beschouwd en krijgt hetzelfde aantal punten bij de rangschikking (precies in punten die de beschikbare bronnen beoordelen) als een knooppunt dat geen werkende pods heeft, wat uiteindelijk kan leiden tot een ongelijke verdeling van de belasting tussen knooppunten.

De uitzetting van Pod

Zoals u weet, krijgt elke pod een van de drie QoS-klassen toegewezen:

  1. gegarandeerd — wordt toegewezen wanneer voor elke container in de pod een verzoek en limiet zijn opgegeven voor geheugen en cpu, en deze waarden moeten overeenkomen
  2. barstbaar — ten minste één container in de pod heeft een verzoek en een limiet, met verzoek <limiet
  3. beste poging — wanneer geen enkele container in de pod beperkte middelen heeft

Tegelijkertijd, wanneer een knooppunt een gebrek aan bronnen ervaart (schijf, geheugen), begint kubelet pods te rangschikken en uit te zetten volgens een specifiek algoritme dat rekening houdt met de prioriteit van de pod en zijn QoS-klasse. Als we het bijvoorbeeld over RAM hebben, worden op basis van de QoS-klasse punten toegekend volgens het volgende principe:

  • Gegarandeerd:-998
  • Beste poging: 1000
  • barstvast: min(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

Die. met dezelfde prioriteit zal de kubelet eerst pods met de beste QoS-klasse van het knooppunt verwijderen.

Uitgang: als u de kans wilt verkleinen dat de gewenste pod van het knooppunt wordt verwijderd in het geval van een gebrek aan middelen erop, dan moet u naast de prioriteit ook zorgen voor het instellen van het verzoek/de limiet ervoor.

Mechanisme voor horizontaal automatisch schalen van applicatiepods (HPA)

Wanneer het de taak is om het aantal pods automatisch te verhogen of te verlagen, afhankelijk van het gebruik van bronnen (systeem - CPU/RAM of gebruiker - rps), zoals een k8s-entiteit als HPA (Horizontale Pod Autoscaler). Het algoritme hiervan is als volgt:

  1. De huidige metingen van de waargenomen bron worden bepaald (currentMetricValue)
  2. De gewenste waarden voor de resource worden bepaald (desiredMetricValue), die voor systeembronnen worden ingesteld met behulp van request
  3. Het huidige aantal replica's wordt bepaald (currentReplicas)
  4. De volgende formule berekent het gewenste aantal replica's (desiredReplicas)
    gewensteReplicas = [ currentReplicas * ( currentMetricValue / gewensteMetricValue )]

In dit geval vindt er geen schaling plaats wanneer de coëfficiënt (currentMetricValue / wantedMetricValue) dichtbij 1 ligt (in dit geval kunnen we de toegestane fout zelf instellen; standaard is deze 0.1).

Laten we eens kijken hoe hpa werkt aan de hand van het voorbeeld van de app-testapplicatie (beschreven als Implementatie), waarbij het nodig is om het aantal replica's te wijzigen, afhankelijk van het CPU-verbruik:

  • Toepassingsmanifest

    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

    Die. we zien dat de applicatie-pod aanvankelijk in twee instanties wordt gestart, die elk twee nginx- en nginx-exporter-containers bevatten, voor elk waarvan een gespecificeerde verzoeken voor CPU.

  • HPA-manifest

    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

    Die. We hebben een hpa gemaakt die de implementatie-app-test controleert en het aantal pods met de applicatie aanpast op basis van de cpu-indicator (we verwachten dat de pod 30% van de CPU die hij vraagt ​​zou moeten verbruiken), waarbij het aantal replica's in het bereik van 2-10.

    Laten we nu eens kijken naar het mechanisme van de hpa-werking als we een belasting uitoefenen op een van de haarden:

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

In totaal hebben wij het volgende:

  • De gewenste waarde (desiredMetricValue) - volgens de hpa-instellingen hebben we 30%
  • Huidige waarde (currentMetricValue) - voor berekening berekent de controller-manager de gemiddelde waarde van het resourceverbruik in%, d.w.z. doet voorwaardelijk het volgende:
    1. Ontvangt absolute waarden van pod-metrieken van de metrische server, d.w.z. 101m en 4m
    2. Berekent de gemiddelde absolute waarde, d.w.z. (101m + 4m) / 2 = 53m
    3. Krijgt de absolute waarde voor het gewenste resourceverbruik (hiervoor worden de verzoeken van alle containers opgeteld) 60m + 30m = 90m
    4. Berekent het gemiddelde percentage CPU-verbruik ten opzichte van de aanvraagpod, d.w.z. 53m / 90m * 100% = 59%

Nu hebben we alles wat we nodig hebben om te bepalen of we het aantal replica's moeten wijzigen; hiervoor berekenen we de coëfficiënt:

ratio = 59% / 30% = 1.96

Die. het aantal replica's moet met ~2 keer worden verhoogd en bedragen [2 * 1.96] = 4.

Conclusie: Zoals u kunt zien, is de aanwezigheid van verzoeken voor alle containers in de waargenomen pod een noodzakelijke voorwaarde om dit mechanisme te laten werken.

Mechanisme voor horizontale automatische schaling van knooppunten (Cluster Autoscaler)

Om de negatieve impact op het systeem tijdens belastingspieken te neutraliseren, is het hebben van een geconfigureerde hpa niet voldoende. Volgens de instellingen in de hpa-controllermanager besluit het bijvoorbeeld dat het aantal replica's met twee keer moet worden verhoogd, maar de knooppunten hebben geen vrije bronnen om een ​​dergelijk aantal pods uit te voeren (d.w.z. het knooppunt kan niet de aangevraagde bronnen naar de verzoeken-pod) en deze pods schakelen over naar de status In behandeling.

In dit geval, als de provider een overeenkomstige IaaS/PaaS heeft (bijvoorbeeld GKE/GCE, AKS, EKS, enz.), kan een tool als Automatische schaalverdeling van knooppunten. Hiermee kunt u het maximale en minimale aantal knooppunten in het cluster instellen en automatisch het huidige aantal knooppunten aanpassen (door de API van de cloudprovider aan te roepen om een ​​knooppunt te bestellen/verwijderen) wanneer er een tekort is aan bronnen in het cluster en de pods kunnen niet worden gepland (bevinden zich in de status In behandeling).

Conclusie: Om knooppunten automatisch te kunnen schalen, is het noodzakelijk om verzoeken in de pod-containers in te stellen, zodat k8s de belasting op de knooppunten correct kan beoordelen en dienovereenkomstig kan rapporteren dat er geen bronnen in het cluster zijn om de volgende pod te starten.

Conclusie

Opgemerkt moet worden dat het instellen van containerresourcelimieten geen vereiste is voor het succesvol uitvoeren van de applicatie, maar het is toch beter om dit te doen om de volgende redenen:

  1. Voor een nauwkeurigere werking van de planner in termen van taakverdeling tussen k8s-knooppunten
  2. Om de kans op een “pod-uitzetting” te verkleinen
  3. Om horizontaal automatisch schalen van applicatiepods (HPA) te laten werken
  4. Voor horizontale automatische schaling van knooppunten (Cluster Autoscaling) voor cloudproviders

Lees ook andere artikelen op onze blog:

Bron: www.habr.com

Voeg een reactie