Kubernetes: pse është kaq e rëndësishme të vendosni menaxhimin e burimeve të sistemit?

Si rregull, ekziston gjithmonë nevoja për të siguruar një grup të dedikuar burimesh për një aplikacion për funksionimin e tij korrekt dhe të qëndrueshëm. Por, çka nëse disa aplikacione funksionojnë me të njëjtën fuqi? Si t'i siguroni secilit prej tyre burimet minimale të nevojshme? Si mund ta kufizoni konsumin e burimeve? Si të shpërndani saktë ngarkesën midis nyjeve? Si të siguroheni që mekanizmi i shkallëzimit horizontal funksionon nëse rritet ngarkesa e aplikimit?

Kubernetes: pse është kaq e rëndësishme të vendosni menaxhimin e burimeve të sistemit?

Ju duhet të filloni me llojet kryesore të burimeve që ekzistojnë në sistem - kjo, natyrisht, është koha e procesorit dhe RAM. Në manifestimet k8s, këto lloje burimesh maten në njësitë e mëposhtme:

  • CPU - në bërthama
  • RAM - në bajt

Për më tepër, për çdo burim është e mundur të vendosen dy lloje kërkesash - Kërkesat и Afatet. Kërkesat - përshkruan kërkesat minimale për burimet e lira të një nyje për të drejtuar një kontejner (dhe pod në tërësi), ndërsa limitet vendosin një kufi të fortë për burimet në dispozicion të kontejnerit.

Është e rëndësishme të kuptohet se manifesti nuk duhet të përcaktojë në mënyrë eksplicite të dy llojet, por sjellja do të jetë si më poshtë:

  • Nëse vetëm kufijtë e një burimi janë specifikuar në mënyrë eksplicite, atëherë kërkesat për këtë burim marrin automatikisht një vlerë të barabartë me kufijtë (mund ta verifikoni këtë duke thirrur entitetet e përshkruara). Ato. në fakt, kontejneri do të kufizohet në të njëjtën sasi burimesh që kërkon për të funksionuar.
  • Nëse vetëm kërkesat janë të specifikuara në mënyrë eksplicite për një burim, atëherë nuk vendosen kufizime të sipërme për këtë burim - d.m.th. kontejneri kufizohet vetëm nga burimet e vetë nyjës.

Është gjithashtu e mundur të konfiguroni menaxhimin e burimeve jo vetëm në nivelin e një kontejneri specifik, por edhe në nivelin e hapësirës së emrave duke përdorur entitetet e mëposhtme:

  • Gama e Kufirit — përshkruan politikën e kufizimit në nivelin e kontejnerëve/podeve në ns dhe është e nevojshme për të përshkruar kufijtë e paracaktuar në kontejner/pod, si dhe për të parandaluar krijimin e kontejnerëve/podeve dukshëm me yndyrë (ose anasjelltas), për të kufizuar numrin e tyre dhe përcaktoni ndryshimin e mundshëm në vlerat në kufij dhe kërkesa
  • Kuotat e burimeve — përshkruani politikën e kufizimit në përgjithësi për të gjithë kontejnerët në ns dhe përdoret, si rregull, për të kufizuar burimet midis mjediseve (e dobishme kur mjediset nuk janë të përcaktuara rreptësisht në nivelin e nyjeve)

Më poshtë janë shembuj të manifestimeve që vendosin kufijtë e burimeve:

  • Në nivelin specifik të kontejnerit:

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

    Ato. në këtë rast, për të drejtuar një kontejner me nginx, do t'ju duhet të paktën 1G RAM falas dhe 0.2 CPU në nyje, ndërsa më së shumti kontejneri mund të konsumojë 0.2 CPU dhe të gjithë RAM-in e disponueshëm në nyje.

  • Në nivelin e plotë ns:

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

    Ato. shuma e të gjithë kontejnerëve të kërkesave në ns të paracaktuar nuk mund të kalojë 300 m për CPU dhe 1G për OP, dhe shuma e të gjithë kufirit është 700 m për CPU dhe 2G për OP.

  • Kufijtë e parazgjedhur për kontejnerët në 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

    Ato. në hapësirën e emrave të paracaktuar për të gjithë kontejnerët, kërkesa do të vendoset në 100 m për CPU dhe 1G për OP, kufiri - 1 CPU dhe 2G. Në të njëjtën kohë, vendoset një kufi edhe në vlerat e mundshme në kërkesë/kufi për CPU (50m < x < 2) dhe RAM (500M < x < 4G).

  • Kufizimet e nivelit të grupit ns:

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

    Ato. për çdo pod në ns të paracaktuar do të ketë një kufi prej 4 vCPU dhe 1G.

Tani do të doja t'ju tregoja se çfarë avantazhesh mund të na japë vendosja e këtyre kufizimeve.

Mekanizmi i balancimit të ngarkesës midis nyjeve

Siç e dini, komponenti k8s është përgjegjës për shpërndarjen e pods midis nyjeve, si p.sh scheduler, i cili funksionon sipas një algoritmi specifik. Ky algoritëm kalon në dy faza kur zgjedh nyjen optimale për të nisur:

  1. filtrim
  2. Rangimi

Ato. sipas politikës së përshkruar, fillimisht zgjidhen nyjet mbi të cilat është e mundur të lëshohet një pod bazuar në një grup kallëzues (duke përfshirë kontrollin nëse nyja ka burime të mjaftueshme për të ekzekutuar pod - PodFitsResources), dhe më pas për secilën prej këtyre nyjeve, sipas prioritetet jepen pikë (përfshirë, sa më shumë burime të lira të ketë një nyje, aq më shumë pikë i caktohen - LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) dhe pod hapet në nyjen me më shumë pikë (nëse disa nyje e plotësojnë këtë kusht në të njëjtën kohë, atëherë zgjidhet një rastësisht).

Në të njëjtën kohë, duhet të kuptoni se planifikuesi, kur vlerëson burimet e disponueshme të një nyje, udhëhiqet nga të dhënat që ruhen në etcd - d.m.th. për sasinë e burimit të kërkuar/kufizues të çdo pod që funksionon në këtë nyje, por jo për konsumin aktual të burimit. Ky informacion mund të merret nga dalja e komandës kubectl describe node $NODE, për shembull:

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

Këtu shohim të gjitha podet që funksionojnë në një nyje specifike, si dhe burimet që kërkon çdo pod. Dhe ja se si duken regjistrat e programuesit kur hapet pod cronjob-cron-events-1573793820-xt6q9 (ky informacion do të shfaqet në regjistrin e planifikuesit kur të vendosni nivelin e 10-të të regjistrimit në argumentet e komandës së nisjes -v=10):

log

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

Këtu shohim që fillimisht planifikuesi filtron dhe gjeneron një listë me 3 nyje në të cilat mund të lëshohet (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Më pas ai llogarit rezultatet bazuar në disa parametra (përfshirë BalancedResourceAllocation, LeastResourceAllocation) për secilën prej këtyre nyjeve në mënyrë që të përcaktojë nyjen më të përshtatshme. Në fund të fundit, pod është planifikuar në nyjen me numrin më të madh të pikëve (këtu dy nyje njëherësh kanë të njëjtin numër pikash 100037, kështu që zgjidhet një e rastësishme - nxs-k8s-s10).

Prodhim: nëse një nyje ekzekuton pods për të cilat nuk janë vendosur kufizime, atëherë për k8s (nga pikëpamja e konsumit të burimeve) kjo do të jetë ekuivalente sikur të mos kishte fare pods të tillë në këtë nyje. Prandaj, nëse, me kusht, keni një pod me një proces grykës (për shembull, wowza) dhe nuk janë vendosur kufizime për të, atëherë mund të lindë një situatë kur ky pod në të vërtetë hëngri të gjitha burimet e nyjës, por për k8s kjo nyje konsiderohet e shkarkuar dhe do t'i jepet i njëjti numër pikësh kur renditet (pikërisht në pikët që vlerësojnë burimet e disponueshme) si një nyje që nuk ka nyje pune, gjë që në fund mund të çojë në shpërndarje të pabarabartë të ngarkesës midis nyjeve.

Dëbimi i Podit

Siç e dini, çdo pod i është caktuar një nga 3 klasat QoS:

  1. e garantuar — caktohet kur për çdo kontejner në pod specifikohet një kërkesë dhe kufi për memorien dhe CPU, dhe këto vlera duhet të përputhen
  2. i shpërthyeshëm — të paktën një kontejner në pod ka një kërkesë dhe një kufi, me kërkesë < limit
  3. perpjekja me e mire — kur asnjë enë e vetme në pod nuk ka burime të kufizuara

Në të njëjtën kohë, kur një nyje përjeton mungesë burimesh (disk, memorie), kubelet fillon të rendit dhe të nxjerrë podet sipas një algoritmi specifik që merr parasysh përparësinë e pod dhe klasës së tij QoS. Për shembull, nëse po flasim për RAM, atëherë bazuar në klasën QoS, pikët jepen sipas parimit të mëposhtëm:

  • Garantuar: -998
  • Përpjekja më e mirë: 1000
  • I plasur: min (maksimumi (2, 1000 - (1000 * memorieRequestBytes) / makineMemoryCapacityBytes), 999)

Ato. me të njëjtin prioritet, kubelet fillimisht do të nxjerrë podet me klasën më të mirë QoS nga nyja.

Prodhim: nëse doni të zvogëloni gjasat që podi i dëshiruar të dëbohet nga nyja në rast të mungesës së burimeve në të, atëherë së bashku me përparësinë, duhet të kujdeseni edhe për vendosjen e kërkesës/kufizimit për të.

Mekanizmi për shkallëzimin automatik horizontal të podave të aplikacionit (HPA)

Kur detyra është të rritet dhe të zvogëlohet automatikisht numri i pod-ve në varësi të përdorimit të burimeve (sistemi - CPU/RAM ose përdorues - rps), një entitet i tillë k8s si HPA (Horizontal Pod Autoscaler). Algoritmi i të cilit është si më poshtë:

  1. Përcaktohen leximet aktuale të burimit të vëzhguar (Vlera Metrike aktuale)
  2. Përcaktohen vlerat e dëshiruara për burimin (dëshiruarMetricValue), të cilat për burimet e sistemit vendosen duke përdorur kërkesën
  3. Përcaktohet numri aktual i kopjeve (replikat aktuale)
  4. Formula e mëposhtme llogarit numrin e dëshiruar të kopjeve (Replikat e dëshiruara)
    Replikat e dëshiruara = [Replikat aktuale * (Vlera Metrike aktuale / Vlera Metrike e dëshiruar)]

Në këtë rast, shkallëzimi nuk do të ndodhë kur koeficienti (currentMetricValue / dëshiruarMetricValue) është afër 1 (në këtë rast, ne mund ta vendosim vetë gabimin e lejuar; si parazgjedhje është 0.1).

Le të shohim se si funksionon hpa duke përdorur shembullin e aplikacionit të testit të aplikacionit (të përshkruar si Deployment), ku është e nevojshme të ndryshohet numri i kopjeve në varësi të konsumit të CPU:

  • Manifesti i aplikimit

    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

    Ato. ne shohim që pod aplikacioni fillimisht lëshohet në dy raste, secila prej të cilave përmban dy kontejnerë nginx dhe nginx-eksportues, për secilën prej të cilave një specifikim Kërkesat për CPU.

  • Manifesti i 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

    Ato. Ne krijuam një hpa që do të monitorojë testin e aplikacionit të vendosjes dhe do të rregullojë numrin e podeve me aplikacionin bazuar në treguesin e CPU (presim që pod duhet të konsumojë 30% të CPU-së që kërkon), me numrin e kopjeve në diapazoni 2-10.

    Tani, le të shohim mekanizmin e funksionimit të hpa nëse aplikojmë një ngarkesë në një nga vatrat:

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

Në total kemi këto:

  • Vlera e dëshiruar (dëshiruarMetricValue) - sipas cilësimeve të hpa, kemi 30%
  • Vlera aktuale (currentMetricValue) - për llogaritjen, kontrolluesi-menaxher llogarit vlerën mesatare të konsumit të burimeve në %, d.m.th. me kusht bën sa më poshtë:
    1. Merr vlera absolute të metrikës së pod nga serveri metrikë, d.m.th. 101m dhe 4m
    2. Llogarit vlerën mesatare absolute, d.m.th. (101m + 4m) / 2 = 53m
    3. Merr vlerën absolute për konsumin e dëshiruar të burimit (për këtë, kërkesat e të gjithë kontejnerëve janë përmbledhur) 60m + 30m = 90m
    4. Llogarit përqindjen mesatare të konsumit të CPU-së në raport me podin e kërkesës, d.m.th. 53 m / 90 m * 100% = 59%

Tani kemi gjithçka që na nevojitet për të përcaktuar nëse duhet të ndryshojmë numrin e kopjeve; për ta bërë këtë, ne llogarisim koeficientin:

ratio = 59% / 30% = 1.96

Ato. numri i kopjeve duhet të rritet me ~ 2 herë dhe të arrijë në [2 * 1.96] = 4.

Përfundim: Siç mund ta shihni, në mënyrë që ky mekanizëm të funksionojë, një kusht i domosdoshëm është prania e kërkesave për të gjithë kontejnerët në podin e vëzhguar.

Mekanizmi për shkallëzimin automatik horizontal të nyjeve (Cluster Autoscaler)

Për të neutralizuar ndikimin negativ në sistem gjatë rritjeve të ngarkesës, nuk mjafton të kesh një hpa të konfiguruar. Për shembull, sipas cilësimeve në menaxherin e kontrolluesit hpa, ai vendos që numri i kopjeve duhet të rritet me 2 herë, por nyjet nuk kanë burime falas për të ekzekutuar një numër të tillë pods (d.m.th. nyja nuk mund të sigurojë burimet e kërkuara në podin e kërkesave) dhe këto pods kalojnë në gjendjen në pritje.

Në këtë rast, nëse ofruesi ka një IaaS/PaaS përkatës (për shembull, GKE/GCE, AKS, EKS, etj.), Një mjet si Shkallëzuesi automatik i nyjeve. Kjo ju lejon të vendosni numrin maksimal dhe minimal të nyjeve në grup dhe të rregulloni automatikisht numrin aktual të nyjeve (duke thirrur API-në e ofruesit të resë kompjuterike për të porositur/hequr një nyje) kur ka mungesë burimesh në grup dhe në pods nuk mund të planifikohet (janë në gjendje në pritje).

Përfundim: Për të qenë në gjendje të shkallëzoni automatikisht nyjet, është e nevojshme të vendosni kërkesa në kontejnerët e pod, në mënyrë që k8-të të mund të vlerësojnë saktë ngarkesën në nyje dhe në përputhje me rrethanat të raportojnë se nuk ka burime në grup për të nisur podin e ardhshëm.

Përfundim

Duhet të theksohet se vendosja e kufijve të burimeve të kontejnerit nuk është një kërkesë që aplikacioni të funksionojë me sukses, por është akoma më mirë ta bëni këtë për arsyet e mëposhtme:

  1. Për funksionim më të saktë të planifikuesit në drejtim të balancimit të ngarkesës midis nyjeve k8s
  2. Për të reduktuar gjasat e ndodhjes së një ngjarjeje të "dëbimit të pod".
  3. Që të funksionojë shkallëzimi automatik horizontal i podave të aplikacionit (HPA).
  4. Për shkallëzimin automatik horizontal të nyjeve (Cluster Autoscaling) për ofruesit e cloud

Lexoni gjithashtu artikuj të tjerë në blogun tonë:

Burimi: www.habr.com

Shto një koment