Krijimi i njĂ« kube-scheduler’i tĂ« shtuar me njĂ« grup tĂ« zakonshĂ«m rregullash tĂ« planifikimit

Krijimi i njĂ« kube-scheduler’i tĂ« shtuar me njĂ« grup tĂ« zakonshĂ«m rregullash tĂ« planifikimit

Kube-scheduler është një komponent themelor i Kubernetes që merret me planifikimin e pod-eve në nodo duke u bazuar në politikën e caktuar. Shpesh, gjatë përdorimit të klasterit Kubernetes, ne nuk e mendojmë se sipas cilave politikash ndodh planifikimi i pod-eve, pasi grupi i politikave të kube-scheduler-it përkojnë me shumicën e detyrave të përditshme. Megjithatë, ka situata kur është e rëndësishme të menaxhohet me shumë kujdes procesi i shpërndarjes së pod-eve, dhe për të realizuar këtë, ka dy rrugë:

  1. Krijimi i një kube-scheduler me një grup rregullash të personalizuara
  2. Shkrimi i një scheduler-i të vet dhe mësimi i tij për të punuar me kërkesat e serverit API

Në këtë artikull, unë do të përshkruaj zbatimin e pikës së parë për të zgjidhur problemin e planifikimit të pabarabartë të pod-eve në një nga projektet tona.

Një hyrje e shkurtër rreth punës së kube-scheduler-it

ËshtĂ« e rĂ«ndĂ«sishme tĂ« theksohet se kube-scheduler nuk merret me planifikimin e drejtpĂ«rdrejtĂ« tĂ« pod-eve — ai Ă«shtĂ« pĂ«rgjegjĂ«s vetĂ«m pĂ«r pĂ«rcaktimin e nodĂ«s ku duhet tĂ« vendoset pod-i. Me fjalĂ« tĂ« tjera, rezultati i punĂ«s sĂ« kube-scheduler-it Ă«shtĂ« emri i nodĂ«s qĂ« ai i kthen serverit API nĂ« pĂ«rgjigje tĂ« kĂ«rkesĂ«s pĂ«r planifikim, dhe kĂ«tu pĂ«rfundon puna e tij.

Fillimisht, kube-scheduler krijon një listë nodash ku mund të planifikohet pod-i sipas politikave të predikateve. Më pas, secila nodë nga kjo listë merr një numër të caktuar pikësh sipas politikave prioritete. Si rezultat, zgjidhet nodi që ka grumbulluar numrin maksimal të pikëve. Nëse ka nodo me të njëjtin maksimum, zgjidhet njëra rastësisht. Me listën dhe përshkrimin e politikave të predikateve (filtrimi) dhe prioriteteve (vlerësimi) mund të njiheni në dokumentacion.

Përshkrimi i problemit

Megjithëse kemi një numër të madh klasteresh Kubernetes në shërbim në Nixys, për herë të parë me problemin e planifikimit të pod-eve u përballëm vetëm së fundmi, kur për një nga projektet tona u shfaq nevoja për të nisur një numër të madh detyrash periodike (~100 entitete CronJob). Për të thjeshtuar sa më shumë përshkrimin e problemit, do të marrim si shembull një mikroshërbim, në kuadër të cilit një herë në minutë fillohet një detyrë cron që krijon një ngarkesë të caktuar në CPU. Për operimin e detyrës cron, u ndanë tri nodo krejtësisht të njëjta nga ana e karakteristikave (24 vCPU në secilën).

Megjithatë, nuk është e mundur të ecet me saktësi se sa kohë do të marrë ekzekutimi i CronJob-it, pasi volumi i të dhënave hyrëse ndalon të jetë konstant. Në mesatare, gjatë funksionimit normal të kube-scheduler-it, në çdo nodë punojnë 3-4 kopje të detyrës, të cilat krijojnë ~20-30% ngarkesë në CPU-në e secilës nodë:

Krijimi i njĂ« kube-scheduler’i tĂ« shtuar me njĂ« grup tĂ« zakonshĂ«m rregullash tĂ« planifikimit

Problemi qëndron në faktin se ndonjëherë pod-et e detyrave cron ndalonin së planifikuari në një nga tre nodat. Kështu, në një moment, në një nga nodat nuk planifikohej asnjë pod, ndërsa dy nodat e tjera kishin 6-8 kopje të detyrës, duke krijuar ~40-60% ngarkesë në CPU:

Krijimi i njĂ« kube-scheduler’i tĂ« shtuar me njĂ« grup tĂ« zakonshĂ«m rregullash tĂ« planifikimit

Problemi përsëritej me një rastësi të plotë në periudha dhe ndonjëherë ishte i lidhur me momentin e lëshimit të një versioni të ri të kodit.

Duke rritur nivelin e regjistrimit të kube-scheduler-it në nivelin 10 (-v=10), filluam të regjistronim se sa pikë merrte çdo nodë gjatë vlerësimit. Gjatë funksionimi normal të planifikimit, në regjistra mund të shihnim informacionin e mëposhtëm:

resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node03: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1387 millicores 4161694720 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node02: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1347 millicores 4444810240 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node03: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1387 millicores 4161694720 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node01: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1687 millicores 4790840320 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node02: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1347 millicores 4444810240 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node01: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1687 millicores 4790840320 memory bytes, score 9
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: NodeAffinityPriority, Score: (0)                                                                                       
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node01: InterPodAffinityPriority, Score: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: TaintTolerationPriority, Score: (10)                                                                                   
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node02: InterPodAffinityPriority, Score: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: TaintTolerationPriority, Score: (10)                                                                                   
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node01: SelectorSpreadPriority, Score: (10)                                                                                                        
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node03: InterPodAffinityPriority, Score: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: TaintTolerationPriority, Score: (10)                                                                                   
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node02: SelectorSpreadPriority, Score: (10)                                                                                                        
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node03: SelectorSpreadPriority, Score: (10)                                                                                                        
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:781] Host Node01 -> Score 100043                                                                                                                                                                        
generic_scheduler.go:781] Host Node02 -> Score 100043                                                                                                                                                                        
generic_scheduler.go:781] Host Node03 -> Score 100043

Kjo do të thotë se, sipas informacionit të marrë nga logët, çdo nod kishte një numër të barabartë pikësh përfundimtar dhe për planifikimin zgjidhej një rastësore. Në momentin e planifikimit problematik, logët duken si më poshtë:

resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node02: BalancedResourceAllocation, kapacitet 23900 millicores 67167186944 bytes memorie, kërkesa totale 1587 millicores 4581125120 bytes memorie, skori 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node03: BalancedResourceAllocation, kapacitet 23900 millicores 67167186944 bytes memorie, kërkesa totale 1087 millicores 3532549120 bytes memorie, skori 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node02: LeastResourceAllocation, kapacitet 23900 millicores 67167186944 bytes memorie, kërkesa totale 1587 millicores 4581125120 bytes memorie, skori 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node01: BalancedResourceAllocation, kapacitet 23900 millicores 67167186944 bytes memorie, kërkesa totale 987 millicores 3322833920 bytes memorie, skori 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node01: LeastResourceAllocation, kapacitet 23900 millicores 67167186944 bytes memorie, kërkesa totale 987 millicores 3322833920 bytes memorie, skori 9 
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node03: LeastResourceAllocation, kapacitet 23900 millicores 67167186944 bytes memorie, kërkesa totale 1087 millicores 3532549120 bytes memorie, skori 9
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node03: InterPodAffinityPriority, Skori: (0)                                                                                                        
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node02: InterPodAffinityPriority, Skori: (0)                                                                                                        
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node01: InterPodAffinityPriority, Skori: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: TaintTolerationPriority, Skori: (10)                                                                                   
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node03: SelectorSpreadPriority, Skori: (10)                                                                                                        
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node02: SelectorSpreadPriority, Skori: (10)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: TaintTolerationPriority, Skori: (10)                                                                                   
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node01: SelectorSpreadPriority, Skori: (10)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: NodeAffinityPriority, Skori: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: SelectorSpreadPriority, Skori: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: SelectorSpreadPriority, Skori: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: TaintTolerationPriority, Skori: (10)                                                                                   
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: NodeAffinityPriority, Skori: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: NodeAffinityPriority, Skori: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: SelectorSpreadPriority, Skori: (10)                                                                                    
generic_scheduler.go:781] Host Node03 -> Skori 100041                                                                                                                                                                        
generic_scheduler.go:781] Host Node02 -> Skori 100041                                                                                                                                                                        
generic_scheduler.go:781] Host Node01 -> Skori 100038

Nga e cila është e qartë që një nga nodet kishte grumbulluar më pak pikë përfundimtare se të tjerat, dhe për këtë arsye, planifikimi u realizua vetëm në dy nodet që fituan pikun maksimal. Kështu ne u siguruam që problemi ishte pikërisht në planifikimin e podëve.

Algoritmi i mĂ«tejshĂ«m pĂ«r zgjidhjen e problemit ishte i qartĂ« pĂ«r ne — tĂ« analizojmĂ« log-et, tĂ« kuptojmĂ« se pĂ«r cilin prioritet konkret node nuk grumbulloi pikĂ« dhe, nĂ«se Ă«shtĂ« e nevojshme, tĂ« korrektojmĂ« politikat e kube-scheduler default. MegjithatĂ«, kĂ«tu u pĂ«rballĂ«m me dy vĂ«shtirĂ«si tĂ« rĂ«ndĂ«sishme:

  1. Në nivelin maksimal të log-imit (10) reflektohet një grup pikësh vetëm për disa prioritete. Në fragmentin e mësipërm të log-eve mund të vërehet se për të gjitha prioritetet e pasqyruara në log, nodet grumbullojnë të njëjtin numër pikësh në planifikimin normal dhe atë problematik, megjithatë rezultati përfundimtar në rastin e planifikimit problematik ndryshon. Kështu, mund të përfundohet se për disa prioritete, llogaritja e pikëve ndodh "në prapaskenë", dhe nuk kemi asnjë mundësi për të kuptuar se për cilin prioritet konkret node nuk grumbulloi pikë. Ky problem e kemi përshkruar në detaje në çështja repozitorin Kubernetes në Github. Në momentin e shkrimit të artikullit është marrë një përgjigje nga zhvilluesit, se mbështetje për log-imin do të shtohet në përditësimet e Kubernetes v1.15, 1.16 dhe 1.17.
  2. Nuk ka një mënyrë të thjeshtë për të kuptuar me cilin grup politik konkret aktualisht punon kube-scheduler. Po, në dokumentacion këtë listë është përfshirë, por në të nuk ka informacion se cilat konkretisht peshë janë vendosur për secilën nga politikat prioritet. Të shohësh peshat ose të editosh politikat e kube-scheduler default mund të bëhet vetëm në burimet.

ËshtĂ« e rĂ«ndĂ«sishme tĂ« theksohet se njĂ« herĂ« arritĂ«m tĂ« dokumentojmĂ« se nodi nuk merrte pikĂ« sipas politikĂ«s ImageLocalityPriority, e cila akordon pikĂ« nodit nĂ«se njĂ« imazh i nevojshĂ«m pĂ«r funksionimin e aplikacionit Ă«shtĂ« tashmĂ« i pranishĂ«m atje. Pra, nĂ« momentin e lansimit tĂ« versionit tĂ« ri tĂ« aplikacionit, detyra cron arrinte tĂ« ekzekutohej nĂ« dy node, duke i shkarkuar ato me njĂ« imazh tĂ« ri nga docker registry, dhe kĂ«shtu dy node merrnin njĂ« rezultat mĂ« tĂ« lartĂ« nĂ« krahasim me tĂ« tretin.

Siç e kam përmendur më lart, në logjet tona nuk shohim informacion rreth vlerësimit të politikës ImageLocalityPriority, prandaj, për të verifikuar supozimin tim, shkarkuam imazhin me versionin e ri të aplikacionit në nodin e tretë, pas së cilës planifikimi filloi të funksiononte siç duhet. Problemi i planifikimit u vu re mjaft rrallë për shkak të politikës ImageLocalityPriority; më shpesh ishte i lidhur me diçka tjetër. Për shkak se nuk mund të debaguam plotësisht çdo politikë në listën e prioriteteve të kube-scheduler-it standard, na nevojitej një menaxhim më fleksibël të politikave të planifikimit të pods.

Vendosja e detyrës

DĂ«shironim qĂ« zgjidhja e problemit tĂ« ishte sa mĂ« e saktĂ«, pra entitetet kryesore tĂ« Kubernetes (kĂ«tu kam parasysh kube-scheduler-in standard) duhet tĂ« mbeten tĂ« pandryshuara. Nuk donim tĂ« zgjidhnim njĂ« problem nĂ« njĂ« vend dhe ta krijonim atĂ« nĂ« njĂ« tjetĂ«r. KĂ«shtu, arritĂ«m nĂ« dy opsione pĂ«r zgjidhjen e problemit, tĂ« cilat u pĂ«rmendĂ«n nĂ« hyrjen e artikullit — krijimi i njĂ« scheduler-i shtesĂ« ose shkruarja e njĂ« tĂ« vetĂ«. KĂ«rkesa kryesore pĂ«r planifikimin e detyrave cron Ă«shtĂ« shpĂ«rndarja e barabartĂ« e ngarkesĂ«s mbi tre node. Kjo kĂ«rkesĂ« mund tĂ« pĂ«rmbushet me politikat ekzistuese tĂ« kube-scheduler-it, prandaj nuk ka kuptim tĂ« shkruajmĂ« njĂ« scheduler tĂ« vetin pĂ«r tĂ« zgjidhur problemin tonĂ«.

Udhëzimi për krijimin dhe Deployment-in e kube-scheduler-it shtesë është përshkruar në dokumentacion. Megjithatë, ne mendojmë se entitetet e Deployment-it nuk janë të mjaftueshme për të garantuar qëndrueshmërinë e një shërbimi kaq kritik si kube-scheduler, prandaj vendosëm të vendosim një kube-scheduler të ri si Static Pod, i cili do të monitorohej drejtpërdrejt nga Kubelet. kështu, ne kishim kërkesat e mëposhtme për kube-scheduler-in e ri:

  1. Shërbimi duhet të jetë i vendosur si Static Pod në të gjithë masterat e klasterit
  2. Duhet të sigurohet qëndrueshmëria në rast se pod-i aktiv me kube-scheduler është i paqasshëm
  3. Prioriteti kryesor gjatë planifikimit duhet të jetë sasia e të dhënave të disponueshme në nod (LeastRequestedPriority)

Implementimi i zgjidhjes

Duhet të theksohet se të gjitha punët do t'i bëjmë në Kubernetes v1.14.7, pasi pikërisht kjo version është përdorur në projekt. Të fillojmë me hartimin e manifestit për kube-scheduler-in tonë të ri. Do të marrim si bazë manifestin e kube-scheduler-it standard (/etc/kubernetes/manifests/kube-scheduler.yaml) dhe do ta sjellim në formën e mëposhtme:

kind: Pod
metadata:
  labels:
    component: scheduler
    tier: control-plane
  name: kube-scheduler-cron
  namespace: kube-system
spec:
      containers:
      - command:
        - /usr/local/bin/kube-scheduler
        - --address=0.0.0.0
        - --port=10151
        - --secure-port=10159
        - --config=/etc/kubernetes/scheduler-custom.conf
        - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
        - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
        - --v=2
        image: gcr.io/google-containers/kube-scheduler:v1.14.7
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 8
          httpGet:
            host: 127.0.0.1
            path: /healthz
            port: 10151
            scheme: HTTP
          initialDelaySeconds: 15
          timeoutSeconds: 15
        name: kube-scheduler-cron-container
        resources:
          requests:
            cpu: '0.1'
        volumeMounts:
        - mountPath: /etc/kubernetes/scheduler.conf
          name: kube-config
          readOnly: true
        - mountPath: /etc/localtime
          name: localtime
          readOnly: true
        - mountPath: /etc/kubernetes/scheduler-custom.conf
          name: scheduler-config
          readOnly: true
        - mountPath: /etc/kubernetes/scheduler-custom-policy-config.json
          name: policy-config
          readOnly: true
      hostNetwork: true
      priorityClassName: system-cluster-critical
      volumes:
      - hostPath:
          path: /etc/kubernetes/scheduler.conf
          type: FileOrCreate
        name: kube-config
      - hostPath:
          path: /etc/localtime
        name: localtime
      - hostPath:
          path: /etc/kubernetes/scheduler-custom.conf
          type: FileOrCreate
        name: scheduler-config
      - hostPath:
          path: /etc/kubernetes/scheduler-custom-policy-config.json
          type: FileOrCreate
        name: policy-config

Përmbledhje mbi ndryshimet kryesore:

  1. Ndryshuam emrin e pod-it dhe konteinerit në kube-scheduler-cron
  2. Specifikuam përdorimin e porteve 10151 dhe 10159 pasi është përcaktuar opsioni hostNetwork: true dhe nuk mund të përdorim të njëjtat porte si kube-scheduler standard (10251 dhe 10259)
  3. Me parametrin —config specifikuam skedarin e konfigurimit me tĂ« cilin duhet tĂ« fillojĂ« shĂ«rbimi
  4. Konfiguruam montimin e skedarit të konfigurimit (scheduler-custom.conf) dhe skedarit të politikave të planifikimit (scheduler-custom-policy-config.json) nga hosti

Mos harrojmë se kube-scheduler-i ynë do të kërkojë privilegje të ngjashme me ato të kështjellës. Redaktojmë rolin e tij të klasterit:

kubectl edit clusterrole system:kube-scheduler

...
   resourceNames:
    - kube-scheduler
    - kube-scheduler-cron
...

Tani le të flasim mbi përmbajtjen që duhet të ketë skedari i konfigurimit dhe skedari me politikat e planifikimit:

  • Skedari i konfigurimit (scheduler-custom.conf)
    Për të marrë konfigurimin e kube-scheduler default, duhet të përdorim parametrin --write-config-to nga dokumentacion. Konfigurimin e marrë do ta vendosim në skedarin /etc/kubernetes/scheduler-custom.conf dhe do ta formojmë si më poshtë:

apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
schedulerName: kube-scheduler-cron
bindTimeoutSeconds: 600
clientConnection:
  acceptContentTypes: ""
  burst: 100
  contentType: application/vnd.kubernetes.protobuf
  kubeconfig: /etc/kubernetes/scheduler.conf
  qps: 50
disablePreemption: false
enableContentionProfiling: false
enableProfiling: false
failureDomains: kubernetes.io/hostname,failure-domain.beta.kubernetes.io/zone,failure-domain.beta.kubernetes.io/region
hardPodAffinitySymmetricWeight: 1
healthzBindAddress: 0.0.0.0:10151
leaderElection:
  leaderElect: true
  leaseDuration: 15s
  lockObjectName: kube-scheduler-cron
  lockObjectNamespace: kube-system
  renewDeadline: 10s
  resourceLock: endpoints
  retryPeriod: 2s
metricsBindAddress: 0.0.0.0:10151
percentageOfNodesToScore: 0
algorithmSource:
   policy:
     file:
       path: "/etc/kubernetes/scheduler-custom-policy-config.json"

Përmbledhje mbi ndryshimet kryesore:

  1. Ne vendosëm në schedulerName emrin e shërbimit tonë kube-scheduler-cron.
  2. Në parametrin lockObjectName duhet gjithashtu të vendosim emrin e shërbimit tonë dhe të sigurohemi se parametri leaderElect është vendosur në vlerën true (nëse keni vetëm një master-node, mund ta vendosni në false).
  3. Caktojmë rrugën e skedarit me përshkrimin e politikave të planifikimit në parametrin algorithmSource.

Duhet të ndalemi më në detaje te pika e dytë, ku redaktojmë parametrat për çelësin leaderElection. Për të siguruar disponueshmëri të lartë, aktivizuam (leaderElect) procesin e zgjedhjes së liderit (master) ndërmjet pod-ëve të kube-scheduler tonë duke përdorur një endpoint të vetëm për ta (resourceLock) me emrin kube-scheduler-cron (lockObjectName) në hapësirën e emrave kube-system (lockObjectNamespace). Për informacion në lidhje me si Kubernetes siguron disponueshmërinë e lartë të komponentëve kryesorë (përfshirë kube-scheduler), mund të referoheni tek artikullin.

  • Skedari i politikave tĂ« planifikimit (scheduler-custom-policy-config.json)
    Siç e pĂ«rmenda mĂ« parĂ« — duke analizuar kodin e kube-scheduler default, mund tĂ« kuptojmĂ« se cilat politika tĂ« sakta pĂ«rdor. Pra, nuk mund tĂ« marrim njĂ« skedar me politikat e planifikimit tĂ« kube-scheduler default ashtu si me skedarin e konfigurimit. Do t'i pĂ«rshkruajmĂ« politikat e interesit nĂ« skedarin /etc/kubernetes/scheduler-custom-policy-config.json si mĂ« poshtĂ«:

{
  "kind": "Policy",
  "apiVersion": "v1",
  "predicates": [
    {
      "name": "GeneralPredicates"
    }
  ],
  "priorities": [
    {
      "name": "ServiceSpreadingPriority",
      "weight": 1
    },
    {
      "name": "EqualPriority",
      "weight": 1
    },
    {
      "name": "LeastRequestedPriority",
      "weight": 1
    },
    {
      "name": "NodePreferAvoidPodsPriority",
      "weight": 10000
    },
    {
      "name": "NodeAffinityPriority",
      "weight": 1
    }
  ],
  "hardPodAffinitySymmetricWeight" : 10,
  "alwaysCheckAllPredicates" : false
}

Në këtë mënyrë, kube-scheduler fillimisht krijon një listë nodash, ku mund të planifikohet pod-i sipas politikës GeneralPredicates (e cila përfshin një grup politikash si PodFitsResources, PodFitsHostPorts, HostName dhe MatchNodeSelector). Më pas, çdo nodë vlerësohet sipas grupit të politikave në arrayn prioritetet. Për të arritur qëllimet tona, menduam se ky grup politikash do të ishte zgjidhja më optimale. Kujtojmë se grupi i politikave me përshkrimet e tyre është në dispozicion në dokumentacion. Për të përmbushur qëllimin tuaj, thjesht mund të ndryshoni grupin e politikave të përdorur dhe t'u caktoni atyre pesha përkatëse.

Manifesti i kube-scheduler të ri, të cilin e krijuam në fillim të kapitullit, do ta quajmë kube-scheduler-custom.yaml dhe do ta vendosim në rrugën /etc/kubernetes/manifests në tre master-nodes. Nëse gjithçka është bërë siç duhet, Kubelet në çdo nodë do të niste pod-in, dhe në log-et e kube-scheduler të ri do të shohim informacionin se skedari ynë me politikat u aplikua me sukses:

Creating scheduler from configuration: {{ } [{GeneralPredicates }]{[ServiceSpreadingPriority 1 } {EqualPriority 1 } {LeastRequestedPriority 1 } {NodePreferAvoidPodsPriority 10000 } {NodeAffinityPriority 1 }]} [] 10 false}
Registering predicate: GeneralPredicates
Predicate type GeneralPredicates already registered, reusing.
Registering priority: ServiceSpreadingPriority
Priority type ServiceSpreadingPriority already registered, reusing.
Registering priority: EqualPriority
Priority type EqualPriority already registered, reusing.
Registering priority: LeastRequestedPriority
Priority type LeastRequestedPriority already registered, reusing.
Registering priority: NodePreferAvoidPodsPriority
Priority type NodePreferAvoidPodsPriority already registered, reusing.
Registering priority: NodeAffinityPriority
Priority type NodeAffinityPriority already registered, reusing.
Creating scheduler with fit predicates 'map[GeneralPredicates:{}]' and priority functions 'map[EqualPriority:{} LeastRequestedPriority:{} NodeAffinityPriority:{} NodePreferAvoidPodsPriority:{} ServiceSpreadingPriority:{}]'

Tani mbetet vetëm të caktosh në specifikën e CronJob-së sonë, që të gjitha kërkesat për planifikimin e pod-eve të saj duhet të trajtohen nga kube-scheduler i ri:

...
 jobTemplate:
    spec:
      template:
        spec:
          schedulerName: kube-scheduler-cron
...

Përfundimi

Në fund, kemi marrë kube-scheduler të shtuar me një grup unik politikash planifikimi, të cilin e monitoron direkt kubelet. Përveç kësaj, kemi rregulluar zgjedhjen e një lideri të ri ndërmjet pod-eve të kube-scheduler tonë në rast se lideri i vjetër bëhet i paqasshëm për ndonjë arsyes.

Aplikacionet dhe shërbimet e zakonshme vazhdojnë të planifikohen përmes kube-scheduler të paracaktuar, ndërsa të gjitha detyrat cron janë transferuar plotësisht në të riun. Ngarkesa e krijuar nga detyrat cron tani shpërndahet baras mbi të gjitha nodet. Të konsiderojmë se pjesa më e madhe e detyrave cron ekzekutohen në të njëjtat node si aplikacionet kryesore të projektit, kjo ka lejuar një ulje të dukshme të rrezikut të kalimit të podëve për shkak të mungesës së burimeve. Pas zbatimit të kube-scheduler të shtuar, nuk ka pasur më probleme me planifikimin jo të barabartë të detyrave cron.

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

Burimi: habr.com

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster