Krijimi i një planifikuesi shtesë kube me një grup rregullash të personalizuara të planifikimit

Krijimi i një planifikuesi shtesë kube me një grup rregullash të personalizuara të planifikimit

Kube-scheduler është një komponent integral i Kubernetes, i cili është përgjegjës për planifikimin e pods nëpër nyje në përputhje me politikat e specifikuara. Shpesh, gjatë funksionimit të një grupi Kubernetes, nuk duhet të mendojmë se cilat politika përdoren për të planifikuar pods, pasi grupi i politikave të programuesit kube të paracaktuar është i përshtatshëm për shumicën e detyrave të përditshme. Megjithatë, ka situata kur është e rëndësishme për ne që të rregullojmë mirë procesin e ndarjes së podeve dhe ka dy mënyra për ta përmbushur këtë detyrë:

  1. Krijo një kube-scheduler me një grup rregullash të personalizuara
  2. Shkruani planifikuesin tuaj dhe mësoni atë të punojë 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ë vatrave në një nga projektet tona.

Një hyrje e shkurtër se si funksionon kube-scheduler

Vlen të përmendet veçanërisht fakti se kube-scheduler nuk është përgjegjës për planifikimin e drejtpërdrejtë të pods - ai është përgjegjës vetëm për përcaktimin e nyjes në të cilën do të vendoset pod. Me fjalë të tjera, rezultati i punës së kube-scheduler është emri i nyjes, të cilën e kthen në serverin API për një kërkesë planifikimi, dhe këtu përfundon puna e saj.

Së pari, kube-scheduler përpilon një listë të nyjeve në të cilat pod mund të planifikohet në përputhje me politikat e predikatave. Më pas, çdo nyje nga kjo listë merr një numër të caktuar pikësh në përputhje me politikat e prioriteteve. Si rezultat, zgjidhet nyja me numrin maksimal të pikëve. Nëse ka nyje që kanë të njëjtin rezultat maksimal, zgjidhet një e rastësishme. Një listë dhe përshkrim i politikave të kallëzuesve (filtrimit) dhe prioriteteve (pikësimi) mund të gjenden në dokumentacionin.

Përshkrimi i trupit problematik

Pavarësisht nga numri i madh i grupimeve të ndryshme të Kubernetes që mbahen në Nixys, problemin e planifikimit të pods e kemi hasur për herë të parë vetëm kohët e fundit, kur një nga projektet tona duhej të ekzekutonte 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, brenda të cilit niset një detyrë cron një herë në minutë, duke krijuar njëfarë ngarkese në CPU. Për të ekzekutuar detyrën cron, u ndanë tre nyje me karakteristika absolutisht identike (24 vCPU për secilin).

Në të njëjtën kohë, është e pamundur të thuhet me saktësi se sa kohë do të duhet për të ekzekutuar CronJob, pasi vëllimi i të dhënave hyrëse po ndryshon vazhdimisht. Mesatarisht, gjatë funksionimit normal të kube-scheduler, çdo nyje ekzekuton 3-4 raste pune, të cilat krijojnë ~20-30% të ngarkesës në CPU të çdo nyje:

Krijimi i një planifikuesi shtesë kube me një grup rregullash të personalizuara të planifikimit

Problemi në vetvete është se nganjëherë cron task pods ndaluan së planifikuari në një nga tre nyjet. Kjo do të thotë, në një moment në kohë, nuk ishte planifikuar asnjë pod i vetëm për njërën nga nyjet, ndërsa në dy nyjet e tjera po funksiononin 6-8 kopje të detyrës, duke krijuar ~ 40-60% të ngarkesës në CPU:

Krijimi i një planifikuesi shtesë kube me një grup rregullash të personalizuara të planifikimit

Problemi përsëritej me frekuencë absolutisht të rastësishme dhe herë pas here lidhej me momentin kur u shfaq një version i ri i kodit.

Duke rritur nivelin e regjistrimit të kube-scheduler në nivelin 10 (-v=10), filluam të regjistrojmë sa pikë fitoi secila nyje gjatë procesit të vlerësimit. Gjatë funksionimit normal të planifikimit, informacioni i mëposhtëm mund të shihet në regjistra:

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

ato. duke gjykuar nga informacioni i marrë nga regjistrat, secila prej nyjeve shënoi një numër të barabartë pikësh përfundimtare dhe një e rastësishme u zgjodh për planifikim. Në kohën e planifikimit problematik, regjistrat dukeshin kështu:

resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node02: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1587 millicores 4581125120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node03: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1087 millicores 3532549120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node02: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1587 millicores 4581125120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node01: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 987 millicores 3322833920 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node01: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 987 millicores 3322833920 memory bytes, score 9 
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node03: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1087 millicores 3532549120 memory bytes, score 9
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node03: InterPodAffinityPriority, Score: (0)                                                                                                        
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node02: InterPodAffinityPriority, Score: (0)                                                                                                        
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node01: InterPodAffinityPriority, Score: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: TaintTolerationPriority, Score: (10)                                                                                   
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node03: SelectorSpreadPriority, Score: (10)                                                                                                        
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node02: SelectorSpreadPriority, Score: (10)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: TaintTolerationPriority, Score: (10)                                                                                   
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node01: SelectorSpreadPriority, Score: (10)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: TaintTolerationPriority, Score: (10)                                                                                   
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:781] Host Node03 => Score 100041                                                                                                                                                                        
generic_scheduler.go:781] Host Node02 => Score 100041                                                                                                                                                                        
generic_scheduler.go:781] Host Node01 => Score 100038

Nga ku mund të shihet se njëra prej nyjeve ka marrë më pak pikë përfundimtare se të tjerat, dhe për këtë arsye planifikimi është kryer vetëm për dy nyjet që kanë shënuar rezultatin maksimal. Kështu, ne ishim të bindur përfundimisht se problemi qëndron pikërisht në planifikimin e bishtajave.

Algoritmi i mëtejshëm për zgjidhjen e problemit ishte i qartë për ne - analizoni regjistrat, kuptoni se me çfarë përparësie nyja nuk fitoi pikë dhe, nëse është e nevojshme, rregulloni politikat e programuesit kube të paracaktuar. Megjithatë, këtu përballemi me dy vështirësi të rëndësishme:

  1. Në nivelin maksimal të prerjeve (10), pasqyrohen pikët e fituara vetëm për disa prioritete. Në fragmentin e mësipërm të regjistrave, mund të shihni se për të gjitha prioritetet e pasqyruara në regjistra, nyjet fitojnë të njëjtin numër pikësh në planifikimin normal dhe problematik, por rezultati përfundimtar në rastin e planifikimit të problemit është i ndryshëm. Kështu, mund të konkludojmë se për disa prioritete, pikëzimi ndodh "prapa skene" dhe nuk kemi asnjë mënyrë për të kuptuar se për cilin prioritet nyja nuk ka marrë pikë. Ne e përshkruam këtë problem në detaje në çështje Depoja e Kubernetes në Github. Në kohën e shkrimit, u mor një përgjigje nga zhvilluesit se mbështetja e regjistrimit do të shtohet në përditësimet Kubernetes v1.15,1.16, 1.17 dhe XNUMX.
  2. Nuk ka asnjë mënyrë të lehtë për të kuptuar se me cilin grup specifik politikash po punon aktualisht kube-scheduler. Po, në dokumentacionin kjo listë është e listuar, por nuk përmban informacion se çfarë peshash specifike i caktohen secilës prej politikave prioritare. Ju mund të shihni peshat ose të modifikoni politikat e paracaktuar kube-scheduler vetëm në burimet.

Vlen të përmendet se një herë ne ishim në gjendje të regjistronim që një nyje nuk mori pikë sipas politikës ImageLocalityPriority, e cila i jep pikë një nyje nëse ajo tashmë ka imazhin e nevojshëm për të ekzekutuar aplikacionin. Kjo do të thotë, në kohën kur u lëshua një version i ri i aplikacionit, detyra cron arriti të ekzekutohej në dy nyje, duke shkarkuar një imazh të ri nga regjistri i dokerit tek ata, dhe kështu dy nyje morën një rezultat përfundimtar më të lartë në krahasim me të tretin. .

Siç shkrova më lart, në regjistrat nuk shohim informacion në lidhje me vlerësimin e politikës ImageLocalityPriority, kështu që për të kontrolluar supozimin tonë, ne e hodhëm imazhin me versionin e ri të aplikacionit në nyjen e tretë, pas së cilës planifikimi funksionoi si duhet . Ishte pikërisht për shkak të politikës ImageLocalityPriority që problemi i planifikimit vërehej mjaft rrallë; më shpesh shoqërohej me diçka tjetër. Për shkak të faktit se nuk mundëm të korrigjojmë plotësisht secilën nga politikat në listën e prioriteteve të programuesit kube të paracaktuar, kishim nevojë për menaxhim fleksibël të politikave të planifikimit të pod.

Formulimi i problemit

Ne donim që zgjidhja e problemit të ishte sa më specifike që të ishte e mundur, domethënë, entitetet kryesore të Kubernetes (këtu nënkuptojmë kube-scheduler parazgjedhur) të mbeten të pandryshuara. Ne nuk donim të zgjidhnim një problem në një vend dhe ta krijonim atë në një vend tjetër. Kështu, arritëm në dy opsione për zgjidhjen e problemit, të cilat u njoftuan në hyrje të artikullit - krijimin e një planifikuesi shtesë ose shkrimin tuaj. Kërkesa kryesore për planifikimin e detyrave cron është shpërndarja e ngarkesës në mënyrë të barabartë në tre nyje. Kjo kërkesë mund të plotësohet nga politikat ekzistuese të programuesit kube, kështu që për të zgjidhur problemin tonë nuk ka kuptim të shkruani planifikuesin tuaj.

Udhëzimet për krijimin dhe vendosjen e një planifikuesi shtesë kube janë përshkruar në dokumentacionin. Sidoqoftë, na u duk se entiteti Deployment nuk ishte i mjaftueshëm për të siguruar tolerancën e gabimeve në funksionimin e një shërbimi kaq kritik si kube-scheduler, kështu që vendosëm të vendosim një kube-scheduler të ri si një Pod Static, i cili do të monitorohej drejtpërdrejt. nga Kubelet. Kështu, ne kemi kërkesat e mëposhtme për programuesin e ri kube:

  1. Shërbimi duhet të vendoset si një Pod Static në të gjithë masterat e grupimeve
  2. Duhet të sigurohet toleranca ndaj gabimeve në rast se podi aktiv me kube-scheduler nuk është i disponueshëm
  3. Prioriteti kryesor gjatë planifikimit duhet të jetë numri i burimeve të disponueshme në nyje (LeastRequestedPriority)

Zgjidhjet e zbatimit

Vlen të përmendet menjëherë se ne do të kryejmë të gjithë punën në Kubernetes v1.14.7, sepse Ky është versioni që është përdorur në projekt. Le të fillojmë duke shkruar një manifest për programuesin tonë të ri kube. Le të marrim manifestin e paracaktuar (/etc/kubernetes/manifests/kube-scheduler.yaml) si bazë dhe ta sjellim atë 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

Shkurtimisht për ndryshimet kryesore:

  1. Ndryshoi emrin e pod dhe kontejnerit në kube-scheduler-cron
  2. Përcaktoi përdorimin e porteve 10151 dhe 10159 si opsion i përcaktuar hostNetwork: true dhe ne nuk mund të përdorim të njëjtat porte si kube-scheduler parazgjedhur (10251 dhe 10259)
  3. Duke përdorur parametrin --config, ne specifikuam skedarin e konfigurimit me të cilin duhet të fillohet shërbimi
  4. Montimi i konfiguruar i skedarit të konfigurimit (scheduler-custom.conf) dhe skedari i politikës së planifikimit (scheduler-custom-policy-config.json) nga hosti

Mos harroni se programuesi ynë kube do të ketë nevojë për të drejta të ngjashme me atë të paracaktuar. Redakto rolin e tij të grupimit:

kubectl edit clusterrole system:kube-scheduler

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

Tani le të flasim për atë që duhet të përmbahet në skedarin e konfigurimit dhe skedarin e politikës së planifikimit:

  • Skedari i konfigurimit (scheduler-custom.conf)
    Për të marrë konfigurimin e paracaktuar të kube-scheduler, duhet të përdorni parametrin --write-config-to nga dokumentacionin. Ne do ta vendosim konfigurimin që rezulton në skedarin /etc/kubernetes/scheduler-custom.conf dhe do ta reduktojmë në formën e mëposhtme:

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"

Shkurtimisht për ndryshimet kryesore:

  1. Ne vendosëm schedulerName në emrin e shërbimit tonë kube-scheduler-cron.
  2. Në parametrin lockObjectName ju gjithashtu duhet të vendosni emrin e shërbimit tonë dhe të siguroheni që parametri leaderElect vendoseni në true (nëse keni një nyje kryesore, mund ta vendosni në false).
  3. Përcaktoi rrugën drejt skedarit me një përshkrim të politikave të planifikimit në parametër algorithmSource.

Vlen të hedhim një vështrim më të afërt në pikën e dytë, ku ne modifikojmë parametrat për çelësin leaderElection. Për të siguruar tolerancën ndaj gabimeve, ne kemi aktivizuar (leaderElect) procesi i zgjedhjes së një drejtuesi (master) midis grupeve të programuesit tonë kube duke përdorur një pikë të vetme përfundimtare për ta (resourceLock) me emrin kube-scheduler-cron (lockObjectName) në hapësirën e emrave të sistemit kube (lockObjectNamespace). Mënyra se si Kubernetes siguron disponueshmëri të lartë të komponentëve kryesorë (përfshirë kube-scheduler) mund të gjendet në artikull.

  • Skedari i politikave të planifikimit (scheduler-custom-policy-config.json)
    Siç shkrova më herët, ne mund të zbulojmë se me cilat politika specifike funksionon kube-scheduler i paracaktuar vetëm duke analizuar kodin e tij. Kjo do të thotë, ne nuk mund të marrim një skedar me politika planifikimi për kube-scheduler parazgjedhur në të njëjtën mënyrë si një skedar konfigurimi. Le të përshkruajmë politikat e planifikimit që na interesojnë 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
}

Kështu, kube-scheduler së pari përpilon një listë nyjesh në të cilat një pod mund të planifikohet sipas politikës GeneralPredicates (e cila përfshin një grup politikash PodFitsResources, PodFitsHostPorts, HostName dhe MatchNodeSelector). Dhe më pas çdo nyje vlerësohet në përputhje me grupin e politikave në grupin e prioriteteve. Për të përmbushur kushtet e detyrës sonë, ne konsideruam se një grup i tillë politikash do të ishte zgjidhja optimale. Më lejoni t'ju kujtoj se një grup politikash me përshkrimet e tyre të hollësishme janë të disponueshme në dokumentacionin. Për të përmbushur detyrën tuaj, thjesht mund të ndryshoni grupin e politikave të përdorura dhe t'u caktoni atyre pesha të përshtatshme.

Le ta quajmë manifestin e kube-scheduler-it të ri, të cilin e krijuam në fillim të kapitullit, kube-scheduler-custom.yaml dhe ta vendosim në shtegun e mëposhtëm /etc/kubernetes/manifests në tre nyje kryesore. Nëse gjithçka është bërë në mënyrë korrekte, Kubelet do të nisë një pod në secilën nyje dhe në regjistrat e programuesit tonë të ri kube do të shohim informacionin se skedari ynë i politikave është zbatuar me sukses:

Creating scheduler from configuration: {{ } [{GeneralPredicates <nil>}] [{ServiceSpreadingPriority 1 <nil>} {EqualPriority 1 <nil>} {LeastRequestedPriority 1 <nil>} {NodePreferAvoidPodsPriority 10000 <nil>} {NodeAffinityPriority 1 <nil>}] [] 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ë tregojmë në specifikimet e CronJob-it tonë që të gjitha kërkesat për planifikimin e pod-eve të tij duhet të përpunohen nga programuesi ynë i ri kube:

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

Përfundim

Në fund të fundit, ne morëm një kube-scheduler shtesë me një grup unik politikash planifikimi, puna e të cilave monitorohet drejtpërdrejt nga kubelet. Përveç kësaj, ne kemi vendosur zgjedhjen e një drejtuesi të ri midis grupeve të programuesit tonë kube në rast se lideri i vjetër bëhet i padisponueshëm për ndonjë arsye.

Aplikacionet dhe shërbimet e rregullta vazhdojnë të planifikohen përmes kube-scheduler parazgjedhur, dhe të gjitha detyrat cron janë transferuar plotësisht në atë të re. Ngarkesa e krijuar nga detyrat cron tani shpërndahet në mënyrë të barabartë në të gjitha nyjet. Duke marrë parasysh që shumica e detyrave të cron ekzekutohen në të njëjtat nyje si aplikacionet kryesore të projektit, kjo ka ulur ndjeshëm rrezikun e lëvizjes së pods për shkak të mungesës së burimeve. Pas prezantimit të kube-scheduler shtesë, problemet me planifikimin e pabarabartë të detyrave të cron nuk u shfaqën më.

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

Burimi: www.habr.com

Shto një koment