Kubernetes: hvorfor det er så vigtigt at konfigurere ressourcehåndtering?

Som regel opstår der altid behov for at sikre en dedikeret pulje af ressourcer til en anvendelse for at sikre dens korrekte og stabile drift. Men hvad nu, hvis flere applikationer kører på de samme ressourcer? Hvordan sikrer man, at hver af dem har de minimalt nødvendige ressourcer? Hvordan kan man begrænse ressourceforbruget? Hvordan fordeler man belastningen mellem noderne? Hvordan sikrer man, at mekanismen til horisontal skalering fungerer i tilfælde af øget belastning på applikationerne?

Kubernetes: hvorfor det er så vigtigt at konfigurere ressourcehåndtering?

Man skal starte med at overveje, hvilke hovedtyper af ressourcer der findes i systemet — det er selvfølgelig CPU-tid og RAM. I k8s-manifester måles disse typer ressourcer i følgende enheder:

  • CPU — i kerner
  • RAM — i bytes

Desuden er der mulighed for at angive to typer krav for hver ressource — requests og limits. Requests — beskriver de minimale krav til tilgængelige ressourcer på noden for at starte en container (og pod'en som helhed), mens limits fastsætter en striks grænse for de ressourcer, der er tilgængelige for containeren.

Det er vigtigt at forstå, at det ikke er nødvendigt at angive begge typer eksplicit i manifestet, og adfærden vil være som følger:

  • Hvis der kun er angivet limits for ressourcen, vil requests for denne ressource automatisk blive sat til værdien lig med limits (dette kan du bekræfte ved at kalde beskrivelsen af enheden). Det vil sige, at containerens drift faktiske vil være begrænset til det samme antal ressourcer, som den kræver for sin opstart.
  • Hvis der kun er angivet requests for ressourcen, så er der ikke nogen begrænsninger på denne ressource — det vil sige, at containeren kun er begrænset af nodens egne ressourcer.

Det er også muligt at konfigurere ressourcehåndteringen ikke kun på niveau med den enkelte container, men også på niveau med namespace ved hjælp af følgende enheder:

  • LimitRange — beskriver politikken for begrænsning på niveau af container/pod i ns og er nødvendig for at beskrive standardbegrænsninger for container/pod samt for at forhindre oprettelsen af alt for tunge containere/pods (eller omvendt), begrænse deres antal og bestemme den mulige forskel i værdier mellem limits og requests.
  • ResourceQuotas — beskriver begrænsningspolitikken generelt for alle containere i ns og bruges som regel til at adskille ressourcer efter miljøer (nyttigt, når miljøer ikke er strengt adskilt på nodeniveau)

Nedenfor er eksempler på manifests, hvor ressourcerne begrænses:

  • På niveau med den specifikke container:

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

    Det vil sige, at det i dette tilfælde kræver mindst 1G RAM og 0.2 CPU på noden for at køre en container med nginx, mens containeren maksimalt kan bruge 0.2 CPU og al tilgængelig RAM på noden.

  • På niveau med hele ns:

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

    Det vil sige, at summen af alle containeranmodninger i den standard ns ikke må overstige 300m for CPU og 1G for RAM, mens summen af alle grænser må være 700m for CPU og 2G for RAM.

  • Standardbegrænsninger for containere i 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

    Det vil sige, at der i den standard namespace for alle containere som standard bliver angivet en anmodning på 100m for CPU og 1G for RAM, grænsen — 1 CPU og 2G. Derudover er der også sat en grænse for mulige værdier i anmodning/grænse for CPU (50m < x < 2) og RAM (500M < x < 4G).

  • Begrænsninger på pod-niveau i ns:

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

    Det vil sige, at for hver pod i den standard ns vil der være en grænse på 4 vCPU og 1G.

Nu vil jeg gerne fortælle, hvilke fordele vi kan få ved at sætte disse begrænsninger.

Mekanismen for belastningsfordeling mellem noder

Som det er kendt, er der en komponent i k8s, der står for fordelingen af pods på noderne, nemlig scheduler, som arbejder efter en bestemt algoritme. Denne algoritme går gennem to faser, når den vælger den optimale node til at køre:

  1. Filtrering
  2. Vurdering

Det vil sige, at i henhold til den beskrevne politik vælges noder først, hvor det er muligt at køre en pod på baggrund af et sæt predicates (herunder kontrolleres det, om der er tilstrækkeligt med ressourcer på noden til at køre podden — PodFitsResources), og derefter vurderes hver af disse noder i forhold til priorities der gives points (including the more free resources the node has — the more points it is assigned — LeastResourceAllocation / LeastRequestedPriority / BalancedResourceAllocation) and launches on the node with the highest number of points (if several nodes meet this condition, one is chosen randomly).

At the same time, it is important to understand that the scheduler evaluates the available resources of the node based on the data stored in etcd — i.e., the sum of the requested/limit resources for each pod running on that node, but not on the actual resource consumption. This information can be obtained from the output of the command kubectl describe node $NODE, for eksempel:

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

Here we see all the pods running on a specific node, as well as the resources requested by each pod. This is what the scheduler logs look like when launching the pod cronjob-cron-events-1573793820-xt6q9 (this information will appear in the scheduler log when logging level 10 is set in the command start arguments —v=10):

log

I1115 07:57:21.637791       1 scheduling_queue.go:908] Forsøger at planlægge pod nxs-stage/cronjob-cron-events-1573793820-xt6q9
I1115 07:57:21.637804       1 scheduler.go:453] Forsøger at planlægge pod: nxs-stage/cronjob-cron-events-1573793820-xt6q9
I1115 07:57:21.638285       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s5, det er tilladt, Node kører kun 16 ud af 110 Pods.
I1115 07:57:21.638300       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s6, det er tilladt, Node kører kun 20 ud af 110 Pods.
I1115 07:57:21.638322       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s3, det er tilladt, Node kører kun 20 ud af 110 Pods.
I1115 07:57:21.638322       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s4, det er tilladt, Node kører kun 17 ud af 110 Pods.
I1115 07:57:21.638334       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s10, det er tilladt, Node kører kun 16 ud af 110 Pods.
I1115 07:57:21.638365       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s12, det er tilladt, Node kører kun 9 ud af 110 Pods.
I1115 07:57:21.638334       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s11, det er tilladt, Node kører kun 11 ud af 110 Pods.
I1115 07:57:21.638385       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s1, det er tilladt, Node kører kun 19 ud af 110 Pods.
I1115 07:57:21.638402       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s2, det er tilladt, Node kører kun 21 ud af 110 Pods.
I1115 07:57:21.638383       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s9, det er tilladt, Node kører kun 16 ud af 110 Pods.
I1115 07:57:21.638335       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s8, det er tilladt, Node kører kun 18 ud af 110 Pods.
I1115 07:57:21.638408       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s13, det er tilladt, Node kører kun 8 ud af 110 Pods.
I1115 07:57:21.638478       1 predicates.go:1369] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s10, det er tilladt, eksisterende pods anti-affinity vilkår opfyldt.
I1115 07:57:21.638505       1 predicates.go:1369] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s8, det er tilladt, eksisterende pods anti-affinity vilkår opfyldt.
I1115 07:57:21.638577       1 predicates.go:1369] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s9, det er tilladt, eksisterende pods anti-affinity vilkår opfyldt.
I1115 07:57:21.638583       1 predicates.go:829] Planlæg Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 på Node nxs-k8s-s7, det er tilladt, Node kører kun 25 ud af 110 Pods.
I1115 07:57:21.638932       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Balanceret ressourceallokering, kapacitet 39900 millicores 66620178432 hukommelsesbytes, samlet anmodning 2343 millicores 9640186880 hukommelsesbytes, score 9
I1115 07:57:21.638946       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Mindst ressourceallokering, kapacitet 39900 millicores 66620178432 hukommelsesbytes, samlet anmodning 2343 millicores 9640186880 hukommelsesbytes, score 8
I1115 07:57:21.638961       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Balanceret ressourceallokering, kapacitet 39900 millicores 66620170240 hukommelsesbytes, samlet anmodning 4107 millicores 11307422720 hukommelsesbytes, score 9
I1115 07:57:21.638971       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Balanceret ressourceallokering, kapacitet 39900 millicores 66620178432 hukommelsesbytes, samlet anmodning 5847 millicores 24333637120 hukommelsesbytes, score 7
I1115 07:57:21.638975       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Mindst ressourceallokering, kapacitet 39900 millicores 66620170240 hukommelsesbytes, samlet anmodning 4107 millicores 11307422720 hukommelsesbytes, score 8
I1115 07:57:21.638990       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Mindst ressourceallokering, kapacitet 39900 millicores 66620178432 hukommelsesbytes, samlet anmodning 5847 millicores 24333637120 hukommelsesbytes, 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] Antager Pod volumener for pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", node "nxs-k8s-s10"
I1115 07:57:21.639286       1 scheduler_binder.go:279] Antager Pod volumener for pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", node "nxs-k8s-s10": alle PVC'er bundet og intet at gøre
I1115 07:57:21.639333       1 factory.go:733] Forsøger at binde cronjob-cron-events-1573793820-xt6q9 til nxs-k8s-s10

Her ser vi, at scheduler oprindeligt filtrerer og opretter en liste over 3 noder, hvorpå der er mulighed for at køre (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Derefter tælles point op baseret på flere parametre (herunder BalancedResourceAllocation, LeastResourceAllocation) for hver af disse noder med henblik på at bestemme den mest passende node. I sidste ende planlægges det på noden med det højeste antal point (her har to noder samme antal point 100037, så der vælges tilfældigt en af dem — nxs-k8s-s10).

Output: hvis der kører pods på noden, for hvilke der ikke er angivet begrænsninger, vil dette for k8s (set fra ressourceforbrugets synspunkt) svare til, at der ikke findes sådanne pods på denne node. Derfor, hvis du hypotetisk har en pod med en ressourcekrævende proces (f.eks. wowza) og der ikke er angivet begrænsninger for den, kan der opstå en situation, hvor denne pod faktisk har spist alle nodens ressourcer, mens k8s stadig anser denne node for ikke at være belastet, og den vil få tildelt det samme antal point under rangeringen (netop i punkterne om tilgængelige ressourcer) som en node uden aktive pods, hvilket i sidste ende kan føre til en ujævn fordeling af belastningen mellem noderne.

Udsættelse af pod

Som bekendt tildeles hver pod én af 3 QoS-klasser:

  1. guaranuted — tildeles når der for hver container i pod’en er angivet både request og limit for hukommelse og CPU, og disse værdier skal være ens
  2. burstable — mindst én container i pod’en har request og limit angivet, hvor request < limit
  3. best effort — når ingen container i pod’en har begrænsninger på ressourcer

Når der observeres mangel på ressourcer (disk, hukommelse) på noden, begynder kubelet at rangere og udsætte pods baseret på en bestemt algoritme, der tager højde for pod’ens prioritet og dens QoS-klasse. For eksempel, når det drejer sig om RAM, tildeles point baseret på QoS-klassen ifølge følgende princippet:

  • Guaranteed: -998
  • BestEffort: 1000
  • Burstable: min(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

Det vil sige, at når prioriteten er den samme, vil kubelet i første omgang udsætte pods med QoS-klassen best effort.

Output: hvis du vil mindske risikoen for, at den nødvendige pod bliver udsat fra noden i tilfælde af ressourcemangel, skal du, ud over prioriteten, også sørge for at angive request/limit for den.

Mekanismen for vandret automatisk skalering af applikationspods (HPA)

Når opgaven er at øge og reducere antallet af pods automatisk afhængigt af ressourceforbruget (system — CPU/RAM eller bruger — rps), kan en k8s-enhed som HPA (Horizontal Pod Autoscaler) være nyttig. Algoritmen er som følger:

  1. De nuværende målinger af den overvågede ressource (currentMetricValue) bestemmes.
  2. De ønskede værdier for ressourcen (desiredMetricValue) bestemmes, hvilket for systemressourcer angives via request.
  3. Det nuværende antal replikaer (currentReplicas) bestemmes.
  4. Det ønskede antal replikaer (desiredReplicas) beregnes ud fra følgende formel:
    desiredReplicas = [ currentReplicas * ( currentMetricValue / desiredMetricValue )]

Skaleringen vil dog ikke finde sted, når forholdet (currentMetricValue / desiredMetricValue) er tæt på 1 (den acceptable fejlmargin kan indstilles selv, som standard er den 0,1).

Lad os se på, hvordan hpa fungerer med eksemplet app-test (beskrevet som Deployment), hvor antallet af replikaer skal ændres afhængigt af CPU-forbruget:

  • Applikationsmanifest

    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

    Det vil sige, vi ser, at pod'en med applikationen oprindeligt kører i to instanser, hvoraf hver indeholder to containere, nginx og nginx-exporter, for hver af dem er der angivet requests for 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

    Det vil sige, vi har oprettet en hpa, der vil overvåge Deployment app-test og regulere antallet af pods med applikationen baseret på cpu-metric (vi forventer, at pod'en skal forbruge 30% af den CPU, den har anmodet om), samtidig med at antallet af replikaer holdes mellem 2-10.

    Nu lad os se på automatisk skalering, hvis der pålægges belastning på en af pods:

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

Alt i alt har vi følgende:

  • Det ønskede værdi (desiredMetricValue) — i henhold til HPA-indstillingerne er lig med 30%
  • Den aktuelle værdi (currentMetricValue) — til beregningen beregner controller-manager det gennemsnitlige ressourceforbrug i %, dvs. det gør i princippet følgende:
    1. Modtager absolutte værdier for pod-metrikker fra metric-serveren, dvs. 101m og 4m
    2. Beregner det gennemsnitlige absolutte værdier, dvs. (101m + 4m) / 2 = 53m
    3. Modtager den absolutte værdi for det ønskede ressourceforbrug (til dette summeres requests fra alle containere) 60m + 30m = 90m
    4. Beregner den gennemsnitlige procentdel af CPU-forbruget i forhold til pod-requesten, dvs. 53m / 90m * 100% = 59%

Nu har vi alt hvad vi behøver for at bestemme, om antallet af replikaer skal ændres; for dette beregner vi forholdet:

ratio = 59% / 30% = 1.96

Det vil sige, antallet af replikaer skal øges med cirka 2 gange og udgøre [2 * 1.96] = 4.

Output: Som man kan se, er det nødvendigt, at der er requests for alle containere i den overvågede pod for at denne mekanisme fungerer.

Mekanismen for horisontal autoskalering af noder (Cluster Autoscaler)

For at afbøde den negative indvirkning på systemet ved belastningsspidser er det nogle gange ikke tilstrækkeligt med en konfigureret HPA. For eksempel, ifølge indstillingerne i HPA-tracker beslutter controller-manageren, at antallet af replikaer skal fordobles; men der er ikke ledige ressourcer på noderne til at køre så mange pods (dvs. noden kan ikke give de anmodede ressourcer fra podens requests), og disse pods går ind i Pending-tilstand.

I dette tilfælde, hvis udbyderen har en passende IaaS/PaaS (f.eks. GKE/GCE, AKS, EKS osv.), kan vi bruge et værktøj som Node Autoscaler. Det gør det muligt at angive det maksimale og minimale antal noder i klyngen og automatisk regulere det nuværende antal noder (ved at anmode om via cloud-udbyderens API for at oprette/slette en node), når der observeres mangel på ressourcer i klyngen, og pods ikke kan planlægges (de er i Pending-tilstand).

Output: For at muliggøre autoskalering af noder er det nødvendigt at angive requests i pod-containere, så k8s korrekt kan vurdere belastningen på noderne og derved kommunikere, at der ikke er ressourcer i klyngen til at starte en ny pod.

Konklusion

Det skal bemærkes, at opsætning af ressourcebegrænsninger for containeren ikke er et obligatorisk krav for en vellykket opstart af applikationen, men det er alligevel bedre at gøre det af følgende grunde:

  1. For mere præcist at arbejde scheduler i forhold til belastningsbalancering mellem noder i k8s
  2. For at mindske sandsynligheden for, at der opstår hændelsen 'pod eviction'
  3. For at aktivere horisontal autoskalering af applikationens pods (HPA)
  4. For at muliggøre horisontal autoskalering af noder (Cluster Autoscaling) hos cloud-udbydere

Læs også andre artikler på vores blog:

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster