Kubernetes: Varför Àr det sÄ viktigt att konfigurera systemresursförvaltning?

I regel uppstÄr behovet av att tillhandahÄlla en dedikerad resurspool för nÄgon applikation för att sÀkerstÀlla dess korrekta och stabila drift. Men vad hÀnder om flera applikationer körs pÄ samma kapacitet? Hur kan man ge varje applikation minimalt nödvÀndiga resurser? Hur kan man begrÀnsa resursanvÀndningen? Hur kan man smart fördela lasten mellan noderna? Hur kan man sÀkerstÀlla att mekanismen för horisontell skalning fungerar vid ökad belastning pÄ applikationerna?

Kubernetes: Varför Àr det sÄ viktigt att konfigurera systemresursförvaltning?

Vi börjar med att definiera de huvudsakliga typerna av resurser i systemet — det handlar förstĂ„s om CPU-tid och RAM. I k8s-manifesten mĂ€ts dessa resurstyper i följande enheter:

  • CPU — i kĂ€rnor
  • RAM — i byte

För varje resurs finns det möjlighet att stĂ€lla in tvĂ„ typer av krav — requests och limits. Requests — beskriver deminimala kraven pĂ„ fria resurser i noden för att köra en container (och podden i stort), medan limits sĂ€tter en strikt begrĂ€nsning pĂ„ de resurser som Ă€r tillgĂ€ngliga för containern.

Det Àr viktigt att förstÄ att det i manifestet inte Àr nödvÀndigt att uttryckligen definiera bÄda typerna, och beteendet blir dÄ följande:

  • Om endast limits för resursen Ă€r uttryckligen angivet, sĂ„ antar requests för denna resurs automatiskt vĂ€rdet som Ă€r lika med limits (detta kan verifieras genom att anropa describe pĂ„ enheten). Det vill sĂ€ga, faktiska driften av containern kommer att begrĂ€nsas till precis sĂ„ mycket resurser som den krĂ€ver för att starta.
  • Om endast requests för resursen Ă€r uttryckligen angivet, sĂ„ sĂ€tts inga begrĂ€nsningar för denna resurs — det vill sĂ€ga, containern Ă€r begrĂ€nsad enbart av nodens resurser.

Det finns ocksÄ möjlighet att justera resurshanteringen inte bara pÄ nivÄn för enskild container, utan Àven pÄ nivÄ av namespace genom hjÀlp av följande enheter:

  • LimitRange — beskriver begrĂ€nsningspolitiken pĂ„ nivĂ„n för containern/podden inom ns och behövs för att beskriva standardbegrĂ€nsningar för en container/podd, samt förhindra skapandet av överdrivet stora containrar/poddar (eller tvĂ€rtom), begrĂ€nsa antalet de kan ha och definiera den möjliga skillnaden i vĂ€rden mellan limits och requests.
  • ResourceQuotas — beskriver restriktionspolitiken överlag för alla containrar i ns och anvĂ€nds vanligtvis för att avgrĂ€nsa resurser efter miljöer (anvĂ€ndbart nĂ€r miljöerna inte Ă€r strikt avgrĂ€nsade pĂ„ nodnivĂ„)

Nedan följer exempel pÄ manifester dÀr resursbegrÀnsningar sÀtts:

  • PĂ„ niveau av en specifik container:

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

    Det vill sÀga, i det hÀr fallet för att starta en container med nginx behöver det finnas minst 1G RAM och 0.2 CPU pÄ noden, och container kan maximalt anvÀnda 0.2 CPU och all tillgÀnglig RAM pÄ noden.

  • PĂ„ niveau av hela ns:

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

    Det vill sÀga, summan av alla container-request i standard ns fÄr inte överstiga 300m för CPU och 1G för RAM, och summan av alla limit fÄr vara 700m för CPU och 2G för RAM.

  • StandardbegrĂ€nsningar för containrar 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 vill sĂ€ga, i standard-namespacet för alla containrar kommer en begĂ€ran som standard att stĂ€llas in pĂ„ 100m för CPU och 1G för RAM, limit — 1 CPU och 2G. Det finns ocksĂ„ en begrĂ€nsning för möjliga vĂ€rden i request/limit för CPU (50m < x < 2) och RAM (500M < x < 4G).

  • BegrĂ€nsningar pĂ„ pod-nivĂ„ i ns:

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

    Det vill sÀga, för varje pod i standard-ns kommer en begrÀnsning att sÀttas till 4 vCPU och 1G.

Nu skulle jag vilja berÀtta om vilka fördelar vi kan fÄ av att sÀtta dessa begrÀnsningar.

Lastbalanseringsmekanism mellan noder

Som bekant ansvarar en sÄdan komponent i k8s som scheduler, som fungerar enligt en specifik algoritm. Denna algoritm gÄr igenom tvÄ steg för att vÀlja den optimala noden för uppstart:

  1. Filtrering
  2. Rankning

Det vill sĂ€ga, enligt den beskrivna policyn vĂ€ljs ursprungligen de noder dĂ€r det Ă€r möjligt att starta en pod baserat pĂ„ en uppsĂ€ttning predicates (dĂ€ribland kontrollen om noden har tillrĂ€ckligt med resurser för att starta podden — PodFitsResources), och sedan för var och en av dessa noder, enligt priorities poĂ€ng tilldelas (inklusive ju fler fria resurser noden har — desto fler poĂ€ng ges — LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) och startas pĂ„ noden med flest poĂ€ng (om flera noder uppfyller detta villkor vĂ€ljs en slumpmĂ€ssigt).

Det Ă€r viktigt att förstĂ„ att schemalĂ€ggaren vid bedömning av tillgĂ€ngliga resurser pĂ„ noden baserar sig pĂ„ data som lagras i etcd — d.v.s. summan av begĂ€rda/reserverade resurser för varje podd som körs pĂ„ denna nod, men inte pĂ„ den faktiska resursanvĂ€ndningen. Denna information kan erhĂ„llas genom kommandot kubectl describe node $NODE, till exempel:

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

HĂ€r ser vi alla poddar som körs pĂ„ en specifik nod, samt de resurser som efterfrĂ„gas av varje podd. SĂ„ hĂ€r ser loggarna frĂ„n schemalĂ€ggaren ut vid start av podden cronjob-cron-events-1573793820-xt6q9 (denna information i schemalĂ€ggarens logg visas vid instĂ€llning av loggnivĂ„ 10 i kommandoradens argument —v=10):

logg

I1115 07:57:21.637791       1 scheduling_queue.go:908] Försöker att schemalÀgga podd nxs-stage/cronjob-cron-events-1573793820-xt6q9                                                                                                                                           
I1115 07:57:21.637804       1 scheduler.go:453] Försöker att schemalÀgga podd: nxs-stage/cronjob-cron-events-1573793820-xt6q9                                                                                                                                                    
I1115 07:57:21.638285       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s5 Àr tillÄten, noden kör endast 16 av 110 poddar.                                                                               
I1115 07:57:21.638300       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s6 Àr tillÄten, noden kör endast 20 av 110 poddar.                                                                               
I1115 07:57:21.638322       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s3 Àr tillÄten, noden kör endast 20 av 110 poddar.                                                                               
I1115 07:57:21.638322       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s4 Àr tillÄten, noden kör endast 17 av 110 poddar.                                                                               
I1115 07:57:21.638334       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s10 Àr tillÄten, noden kör endast 16 av 110 poddar.                                                                              
I1115 07:57:21.638365       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s12 Àr tillÄten, noden kör endast 9 av 110 poddar.                                                                               
I1115 07:57:21.638334       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s11 Àr tillÄten, noden kör endast 11 av 110 poddar.                                                                              
I1115 07:57:21.638385       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s1 Àr tillÄten, noden kör endast 19 av 110 poddar.                                                                               
I1115 07:57:21.638402       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s2 Àr tillÄten, noden kör endast 21 av 110 poddar.                                                                               
I1115 07:57:21.638383       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s9 Àr tillÄten, noden kör endast 16 av 110 poddar.                                                                               
I1115 07:57:21.638335       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s8 Àr tillÄten, noden kör endast 18 av 110 poddar.                                                                               
I1115 07:57:21.638408       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s13 Àr tillÄten, noden kör endast 8 av 110 poddar.                                                                               
I1115 07:57:21.638478       1 predicates.go:1369] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s10 Àr tillÄten, existerande poddar anti-affinity villkor Àr uppfyllda.                                                                         
I1115 07:57:21.638505       1 predicates.go:1369] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s8 Àr tillÄten, existerande poddar anti-affinity villkor Àr uppfyllda.                                                                          
I1115 07:57:21.638577       1 predicates.go:1369] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s9 Àr tillÄten, existerande poddar anti-affinity villkor Àr uppfyllda.                                                                          
I1115 07:57:21.638583       1 predicates.go:829] SchemalÀgg podd nxs-stage/cronjob-cron-events-1573793820-xt6q9 pÄ nod nxs-k8s-s7 Àr tillÄten, noden kör endast 25 av 110 poddar.                                                                               
I1115 07:57:21.638932       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: BalancedResourceAllocation, kapacitet 39900 millicores 66620178432 minnesbyte, totalt begÀran 2343 millicores 9640186880 minnesbyte, poÀng 9        
I1115 07:57:21.638946       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: LeastResourceAllocation, kapacitet 39900 millicores 66620178432 minnesbyte, totalt begÀran 2343 millicores 9640186880 minnesbyte, poÀng 8           
I1115 07:57:21.638961       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: BalancedResourceAllocation, kapacitet 39900 millicores 66620170240 minnesbyte, totalt begÀran 4107 millicores 11307422720 minnesbyte, poÀng 9        
I1115 07:57:21.638971       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: BalancedResourceAllocation, kapacitet 39900 millicores 66620178432 minnesbyte, totalt begÀran 5847 millicores 24333637120 minnesbyte, poÀng 7        
I1115 07:57:21.638975       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: LeastResourceAllocation, kapacitet 39900 millicores 66620170240 minnesbyte, totalt begÀran 4107 millicores 11307422720 minnesbyte, poÀng 8           
I1115 07:57:21.638990       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: LeastResourceAllocation, kapacitet 39900 millicores 66620178432 minnesbyte, totalt begÀran 5847 millicores 24333637120 minnesbyte, poÀng 7           
I1115 07:57:21.639022       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: TaintTolerationPriority, PoÀng: (10)                                                                                                        
I1115 07:57:21.639030       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: TaintTolerationPriority, PoÀng: (10)                                                                                                         
I1115 07:57:21.639034       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: TaintTolerationPriority, PoÀng: (10)                                                                                                         
I1115 07:57:21.639041       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: NodeAffinityPriority, PoÀng: (0)                                                                                                            
I1115 07:57:21.639053       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: NodeAffinityPriority, PoÀng: (0)                                                                                                             
I1115 07:57:21.639059       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: NodeAffinityPriority, PoÀng: (0)                                                                                                             
I1115 07:57:21.639061       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: InterPodAffinityPriority, PoÀng: (0)                                                                                                                   
I1115 07:57:21.639063       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: SelectorSpreadPriority, PoÀng: (10)                                                                                                                   
I1115 07:57:21.639073       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: InterPodAffinityPriority, PoÀng: (0)                                                                                                                    
I1115 07:57:21.639077       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: SelectorSpreadPriority, PoÀng: (10)                                                                                                                    
I1115 07:57:21.639085       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: InterPodAffinityPriority, PoÀng: (0)                                                                                                                    
I1115 07:57:21.639088       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: SelectorSpreadPriority, PoÀng: (10)                                                                                                                    
I1115 07:57:21.639103       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: SelectorSpreadPriority, PoÀng: (10)                                                                                                         
I1115 07:57:21.639109       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: SelectorSpreadPriority, PoÀng: (10)                                                                                                          
I1115 07:57:21.639114       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: SelectorSpreadPriority, PoÀng: (10)                                                                                                          
I1115 07:57:21.639127       1 generic_scheduler.go:781] VÀrd nxs-k8s-s10 => PoÀng 100037                                                                                                                                                                            
I1115 07:57:21.639150       1 generic_scheduler.go:781] VÀrd nxs-k8s-s8 => PoÀng 100034                                                                                                                                                                             
I1115 07:57:21.639154       1 generic_scheduler.go:781] VÀrd nxs-k8s-s9 => PoÀng 100037                                                                                                                                                                             
I1115 07:57:21.639267       1 scheduler_binder.go:269] AntaPodVolymer för podd "nxs-stage/cronjob-cron-events-1573793820-xt6q9", nod "nxs-k8s-s10"                                                                                                               
I1115 07:57:21.639286       1 scheduler_binder.go:279] AntaPodVolymer för podd "nxs-stage/cronjob-cron-events-1573793820-xt6q9", nod "nxs-k8s-s10": alla PVC:er Àr bundna och inget att göra                                                                             
I1115 07:57:21.639333       1 factory.go:733] Försöker att binda cronjob-cron-events-1573793820-xt6q9 till nxs-k8s-s10

HÀr ser vi att schemalÀggaren frÄn början filtrerar och skapar en lista pÄ 3 noder dÀr en start Àr möjlig (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Det gör sedan en poÀngsÀttning baserat pÄ flera parametrar (inklusive BalancedResourceAllocation, LeastResourceAllocation) för var och en av dessa noder för att avgöra den mest lÀmpliga noden. I slutÀndan planeras pÄ noden med flest poÀng (hÀr har tvÄ noder samma poÀng 100037, sÄ en av dem, nxs-k8s-s10, vÀljs slumpmÀssigt).

Utdata: Om det finns pods pÄ noden för vilka inga begrÀnsningar Àr angivna, sÄ kommer det för k8s (utifrÄn resursanvÀndning) att motsvara att dessa pods egentligen inte finns pÄ noden. DÀrför, om du har en pod med en resurskrÀvande process (t.ex. wowza) och inga begrÀnsningar Àr angivna, kan det hÀnda att denna pod faktiskt har tagit all resurs pÄ noden, men för k8s rÀknas noden som outnyttjad och fÄr samma poÀng i rangordningen (just i punkterna för tillgÀngliga resurser) som en nod utan arbetande pods, vilket i slutÀndan kan leda till en ojÀmn belastning mellan noderna.

Utkast av pod

Som kÀnt tilldelas varje pod en av 3 QoS-klasser:

  1. guaranuted — tilldelas dĂ„ för varje container i podden för minne och cpu en begĂ€ran och begrĂ€nsning Ă€r angiven, och dessa vĂ€rden mĂ„ste överensstĂ€mma
  2. burstable — minst en container i podden har en begĂ€ran och en begrĂ€nsning, dĂ€r begĂ€ran < begrĂ€nsning
  3. best effort — nĂ€r ingen container i podden Ă€r begrĂ€nsad nĂ€r det gĂ€ller resurser

Vid brist pÄ resurser (disk, minne) pÄ noden börjar kubelet rangordna och utvisa pods enligt en viss algoritm som tar hÀnsyn till poddens prioritet och dess QoS-klass. Till exempel, nÀr det handlar om RAM, tilldelas poÀng baserat pÄ QoS-klassen enligt följande princip:

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

Dvs, vid samma prioritet kommer kubelet först att utvisa pods med QoS-klassen best effort frÄn noden.

Utdata: Om du vill minska sannolikheten för att en nödvÀndig pod ska utvisas frÄn noden vid brist pÄ resurser, mÄste du ocksÄ se till att för den ges en begÀran/begrÀnsning, pÄ lika villkor med prioritet.

Horinzontell autoskalering av applikationspods (HPA)

NĂ€r uppgiften krĂ€ver automatisk ökning och minskning av antalet pods beroende pĂ„ resursanvĂ€ndning (systemresurser — CPU/RAM eller anvĂ€ndarresurser — rps) kan en sĂ„dan enhet i k8s hjĂ€lpa till HPA (Horizontal Pod Autoscaler). Algoritmen gĂ„r till följande:

  1. Aktuella vÀrden av den observerade resursen (currentMetricValue) definieras
  2. Önskade vĂ€rden för resursen (desiredMetricValue) definieras, vilka för systemresurser sĂ€tts med hjĂ€lp av request
  3. Det aktuella antalet replikat (currentReplicas) definieras
  4. Det önskade antalet replikat (desiredReplicas) berÀknas med följande formel
    desiredReplicas = [ currentReplicas * ( currentMetricValue / desiredMetricValue )]

Vid detta tillfÀlle sker ingen skala om förhÄllandet (currentMetricValue / desiredMetricValue) Àr nÀra 1 (vi kan sjÀlva ange det tillÄtna felet, vilket som standard Àr 0.1).

LÄt oss övervÀga hur hpa fungerar med exemplet pÄ applikationen app-test (beskriven som Deployment), dÀr antalet replikat mÄste Àndras beroende pÄ CPU-anvÀndning:

  • 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 vill sÀga, vi ser att podden med applikationen ursprungligen startas i tvÄ exemplar, dÀr varje innehÄller tvÄ containrar, nginx och nginx-exporter, för vilka en requests för 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 vill sÀga, vi har skapat en hpa som kommer att övervaka Deployment app-test och reglera antalet pods med applikationen baserat pÄ cpu-mÀtningen (vi förvÀntar oss att podden ska konsumera 30% av det begÀrda CPU-n)

    Nu, lÄt oss övervÀga hur hpa fungerar om vi lÀgger belastning pÄ en av pods:

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

Totalt har vi följande:

  • Önskat vĂ€rde (desiredMetricValue) — enligt hpa-instĂ€llningarna Ă€r lika med 30%
  • Nuvarande vĂ€rde (currentMetricValue) — för att berĂ€kna controller-manager berĂ€knar det genomsnittliga resursanvĂ€ndningen i %, dvs. gör ungefĂ€r följande:
    1. Tar absoluta vÀrden för podmetrics frÄn metric-servern, dvs. 101m och 4m
    2. BerÀknar det genomsnittliga absoluta vÀrdet, dvs. (101m + 4m) / 2 = 53m
    3. Tar det absoluta vÀrdet för önskad resursanvÀndning (för detta summeras request för alla containrar) 60m + 30m = 90m
    4. BerÀknar genomsnittlig procentandel av CPU-anvÀndningen relativt podens request, dvs. 53m / 90m * 100% = 59%

Nu har vi allt som behövs för att avgöra om antalet repliker behöver Àndras, för att göra det berÀknar vi förhÄllandet:

ratio = 59% / 30% = 1.96

Det vill sÀga, antalet repliker bör ökas med ~2 gÄnger och bli [2 * 1.96] = 4.

Slutsats: Som man kan se, för att denna mekanism ska fungera Àr det nödvÀndigt att det ocksÄ finns requests för alla containrar i den observerade podden.

Mekanismen för horisontell automatisk skalning av noder (Cluster Autoscaler)

För att mildra den negativa pÄverkan pÄ systemet vid belastningsspikar, Àr det ibland otillrÀckligt att ha en konfigurerad hpa. Till exempel, enligt instÀllningarna i hpa, beslutar controller-manager att antalet repliker mÄste ökas med 2 gÄnger, men det finns inte tillrÀckligt med fria resurser pÄ noderna för att köra sÄ mÄnga pods (dvs. noden kan inte tillhandahÄlla de begÀrda resurserna för podens requests) och dessa pods gÄr in i tillstÄndet Pending.

I detta fall, om leverantören har motsvarande IaaS/PaaS (t.ex. GKE/GCE, AKS, EKS m.fl.), kan vi fÄ hjÀlp av ett verktyg som Node Autoscaler. Det tillÄter att stÀlla in ett maximalt och minimalt antal noder i klustret och automatiskt justera det aktuella antalet noder (genom att anropa API:t för molnleverantören för att bestÀlla/ta bort en nod), nÀr det Àr brist pÄ resurser i klustret och pods inte kan schemalÀggas (Àr i tillstÄndet Pending).

Slutsats: För möjligheten till automatisk skalning av noder Àr det nödvÀndigt att ange requests i containrarna i pods, sÄ att k8s kan utvÀrdera noderna korrekt och dÀrmed meddela att det inte finns nÄgra resurser i klustret för att starta en ny pod.

Slutsats

Det Àr vÀrt att notera att installation av resursbegrÀnsningar för containern inte Àr ett krav för att framgÄngsrikt starta applikationen, men det Àr ÀndÄ bÀttre att göra det av följande skÀl:

  1. För att den schemalÀggning ska fungera mer exakt nÀr det gÀller att balansera belastningen mellan noderna i k8s
  2. För att minska risken för att hÀndelsen "podutdrivning" intrÀffar
  3. För att arbeta med horisontell automatisk skalning av applikationens pods (HPA)
  4. För att arbeta med horisontell automatisk skalning av noder (Cluster Autoscaling) hos molnleverantörer

LÀs Àven andra artiklar i vÄr blogg:

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster