Vytvorenie ďalšieho plánovača kube s vlastnou sadou pravidiel plánovania

Vytvorenie ďalšieho plánovača kube s vlastnou sadou pravidiel plánovania

Kube-scheduler je integrálnou súčasťou Kubernetes, ktorá je zodpovedná za plánovanie modulov medzi uzlami v súlade so špecifikovanými politikami. Počas prevádzky klastra Kubernetes často nemusíme premýšľať o tom, ktoré politiky sa používajú na plánovanie modulov, pretože sada pravidiel predvoleného plánovača kube je vhodná pre väčšinu každodenných úloh. Sú však situácie, kedy je pre nás dôležité doladiť proces prideľovania modulov a existujú dva spôsoby, ako túto úlohu splniť:

  1. Vytvorte plánovač kube s vlastnou sadou pravidiel
  2. Napíšte si vlastný plánovač a naučte ho pracovať s požiadavkami servera API

V tomto článku popíšem implementáciu prvého bodu na vyriešenie problému nerovnomerného rozvrhnutia ohnísk na jednom z našich projektov.

Krátky úvod do fungovania plánovača kube

Za zmienku stojí najmä skutočnosť, že kube-scheduler nie je zodpovedný za priame plánovanie modulov - je zodpovedný iba za určenie uzla, na ktorý sa modul umiestni. Inými slovami, výsledkom práce plánovača kube je názov uzla, ktorý vráti serveru API na žiadosť o plánovanie, a tam jeho práca končí.

Najprv kube-scheduler zostaví zoznam uzlov, na ktorých je možné naplánovať pod v súlade s politikami predikátov. Ďalej každý uzol z tohto zoznamu získa určitý počet bodov v súlade s politikami priorít. V dôsledku toho sa vyberie uzol s maximálnym počtom bodov. Ak existujú uzly, ktoré majú rovnaké maximálne skóre, vyberie sa náhodne. Zoznam a popis politík predikátov (filtrovanie) a priorít (bodovanie) nájdete v dokumentáciu.

Popis tela problému

Napriek veľkému počtu rôznych klastrov Kubernetes udržiavaných v spoločnosti Nixys sme sa prvýkrát stretli s problémom plánovania modulov len nedávno, keď jeden z našich projektov potreboval spustiť veľké množstvo periodických úloh (~ 100 entít CronJob). Aby sme čo najviac zjednodušili popis problému, uvedieme ako príklad jednu mikroslužbu, v rámci ktorej sa raz za minútu spúšťa úloha cron, čím dochádza k určitej záťaži CPU. Na spustenie úlohy cron boli pridelené tri uzly s absolútne identickými charakteristikami (24 vCPU na každom).

Zároveň nie je možné s presnosťou povedať, ako dlho bude CronJob trvať, kým sa vykoná, pretože objem vstupných údajov sa neustále mení. V priemere počas normálnej prevádzky plánovača kube každý uzol spúšťa 3-4 inštancie úloh, ktoré vytvárajú ~20-30% zaťaženia CPU každého uzla:

Vytvorenie ďalšieho plánovača kube s vlastnou sadou pravidiel plánovania

Samotný problém je v tom, že niekedy sa pody úloh cron prestali plánovať na jednom z troch uzlov. To znamená, že v určitom čase nebol pre jeden z uzlov naplánovaný ani jeden modul, zatiaľ čo na ostatných dvoch uzloch bežalo 6-8 kópií úlohy, čo vytváralo ~40-60% zaťaženia CPU:

Vytvorenie ďalšieho plánovača kube s vlastnou sadou pravidiel plánovania

Problém sa opakoval s absolútne náhodnou frekvenciou a príležitostne koreloval s momentom uvedenia novej verzie kódu.

Zvýšením úrovne protokolovania plánovača kube na úroveň 10 (-v=10) sme začali zaznamenávať, koľko bodov každý uzol získal počas procesu hodnotenia. Počas normálnej plánovacej operácie je možné v protokoloch vidieť nasledujúce informácie:

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

Tie. súdiac podľa informácií získaných z protokolov, každý z uzlov dosiahol rovnaký počet konečných bodov a na plánovanie bol vybraný jeden náhodný. V čase problematického plánovania vyzerali protokoly takto:

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

Z čoho je vidieť, že jeden z uzlov dosiahol menej konečných bodov ako ostatné, a preto sa plánovalo len pre dva uzly, ktoré dosiahli maximálne skóre. Definitívne sme sa teda presvedčili, že problém spočíva práve v plánovaní strukov.

Ďalší algoritmus na vyriešenie problému bol pre nás zrejmý - analyzovať protokoly, pochopiť, s akou prioritou uzol nezískal body, a v prípade potreby upraviť politiky predvoleného plánovača kube. Tu však čelíme dvom závažným problémom:

  1. Pri maximálnej úrovni ťažby (10) sa odrážajú body získané len za niektoré priority. Vo vyššie uvedenom úryvku protokolov môžete vidieť, že pre všetky priority vyjadrené v protokoloch dosahujú uzly rovnaký počet bodov v normálnom a problémovom plánovaní, ale konečný výsledok v prípade plánovania problémov je odlišný. Môžeme teda dospieť k záveru, že pri niektorých prioritách sa bodovanie vyskytuje „v zákulisí“ a nemáme spôsob, ako pochopiť, za ktorú prioritu uzol nezískal body. Tento problém sme podrobne opísali v otázka Úložisko Kubernetes na Github. V čase písania tohto článku bola od vývojárov prijatá odpoveď, že podpora protokolovania bude pridaná v aktualizáciách Kubernetes v1.15,1.16, 1.17 a XNUMX.
  2. Neexistuje jednoduchý spôsob, ako pochopiť, s ktorou špecifickou sadou politík kube-scheduler momentálne pracuje. Áno, v dokumentáciu tento zoznam je uvedený, ale neobsahuje informácie o tom, aké konkrétne váhy sú priradené každej z prioritných politík. Váhy alebo úpravu pravidiel predvoleného plánovača kube môžete zobraziť iba v zdrojové kódy.

Stojí za zmienku, že raz sa nám podarilo zaznamenať, že uzol nezískal body podľa politiky ImageLocalityPriority, ktorá prideľuje body uzlu, ak už má obraz potrebný na spustenie aplikácie. To znamená, že v čase uvedenia novej verzie aplikácie sa úloha cron podarilo spustiť na dvoch uzloch, pričom sa do nich stiahol nový obrázok z registra dockerov, a teda dva uzly získali vyššie konečné skóre v porovnaní s tretím .

Ako som písal vyššie, v protokoloch nevidíme informácie o vyhodnotení politiky ImageLocalityPriority, takže aby sme skontrolovali náš predpoklad, prehodili sme obrázok s novou verziou aplikácie na tretí uzol, po ktorom plánovanie fungovalo správne. . Práve kvôli politike ImageLocalityPriority bol problém s plánovaním pozorovaný pomerne zriedkavo, častejšie bol spojený s niečím iným. Vzhľadom na to, že sme nemohli úplne odladiť každú z politík v zozname priorít predvoleného plánovača kube, potrebovali sme flexibilnú správu politík plánovania pod.

Vyhlásenie o probléme

Chceli sme, aby riešenie problému bolo čo najkonkrétnejšie, to znamená, že hlavné entity Kubernetes (tu máme na mysli predvolený plánovač kube) by mali zostať nezmenené. Nechceli sme riešiť problém na jednom mieste a vytvárať ho na inom. Dospeli sme teda k dvom možnostiam riešenia problému, ktoré boli oznámené v úvode článku - vytvorenie dodatočného plánovača alebo napísanie vlastného. Hlavnou požiadavkou na plánovanie úloh cronu je rovnomerné rozloženie záťaže medzi tri uzly. Táto požiadavka môže byť splnená existujúcimi politikami plánovača kube, takže na vyriešenie nášho problému nemá zmysel písať svoj vlastný plánovač.

Pokyny na vytvorenie a nasadenie dodatočného plánovača kube sú popísané v dokumentáciu. Zdalo sa nám však, že entita Deployment nestačí na zabezpečenie odolnosti voči poruchám pri prevádzke takej kritickej služby, akou je kube-scheduler, preto sme sa rozhodli nasadiť nový kube-scheduler ako Static Pod, ktorý bude monitorovaný priamo od Kubeleta. Preto máme pre nový plánovač kube nasledujúce požiadavky:

  1. Služba musí byť nasadená ako statický modul na všetkých hlavných serveroch klastra
  2. V prípade, že aktívny modul s plánovačom kube nie je k dispozícii, musí byť poskytnutá odolnosť voči chybám
  3. Hlavnou prioritou pri plánovaní by mal byť počet dostupných zdrojov v uzle (LeastRequestedPriority)

Implementačné riešenia

Okamžite stojí za zmienku, že všetku prácu vykonáme v Kubernetes v1.14.7, pretože Toto je verzia, ktorá bola použitá v projekte. Začnime napísaním manifestu pre náš nový plánovač kube. Vezmime si za základ predvolený manifest (/etc/kubernetes/manifests/kube-scheduler.yaml) a privedieme ho do nasledujúcej podoby:

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

Stručne o hlavných zmenách:

  1. Zmenil sa názov modulu a kontajnera na kube-scheduler-cron
  2. Špecifikovalo použitie portov 10151 a 10159, ako bola definovaná možnosť hostNetwork: true a nemôžeme použiť rovnaké porty ako predvolený plánovač kube (10251 a 10259)
  3. Pomocou parametra --config sme špecifikovali konfiguračný súbor, pomocou ktorého sa má služba spustiť
  4. Konfigurované pripojenie konfiguračného súboru (scheduler-custom.conf) a súboru politiky plánovania (scheduler-custom-policy-config.json) z hostiteľa

Nezabudnite, že náš plánovač kube bude potrebovať práva podobné predvolenému. Upravte jeho rolu klastra:

kubectl edit clusterrole system:kube-scheduler

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

Teraz si povedzme, čo by mal obsahovať konfiguračný súbor a súbor politiky plánovania:

  • Konfiguračný súbor (scheduler-custom.conf)
    Ak chcete získať predvolenú konfiguráciu plánovača kube, musíte použiť parameter --write-config-to z dokumentáciu. Výslednú konfiguráciu umiestnime do súboru /etc/kubernetes/scheduler-custom.conf a zredukujeme ju do nasledujúcej podoby:

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"

Stručne o hlavných zmenách:

  1. Nastavili sme schedulerName na názov našej služby kube-scheduler-cron.
  2. V parametri lockObjectName musíte tiež nastaviť názov našej služby a uistiť sa, že parameter leaderElect nastavte na hodnotu true (ak máte jeden hlavný uzol, môžete ho nastaviť na hodnotu false).
  3. V parametri zadáte cestu k súboru s popisom politík plánovania algorithmSource.

Stojí za to sa bližšie pozrieť na druhý bod, kde upravujeme parametre pre kľúč leaderElection. Na zabezpečenie odolnosti voči chybám sme povolili (leaderElect) proces výberu vedúceho (hlavného) medzi modulmi nášho plánovača kube pomocou jediného koncového bodu (resourceLock) s názvom kube-scheduler-cron (lockObjectName) v priestore názvov systému kube (lockObjectNamespace). Ako Kubernetes zabezpečuje vysokú dostupnosť hlavných komponentov (vrátane plánovača kube) nájdete v článok.

  • Súbor zásad plánovania (scheduler-custom-policy-config.json)
    Ako som už písal, môžeme zistiť, s ktorými konkrétnymi politikami predvolený plánovač kube pracuje, iba analýzou jeho kódu. To znamená, že nemôžeme získať súbor so zásadami plánovania pre predvolený plánovač kube rovnakým spôsobom ako konfiguračný súbor. Popíšme si zásady plánovania, ktoré nás zaujímajú v súbore /etc/kubernetes/scheduler-custom-policy-config.json takto:

{
  "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
}

Preto kube-scheduler najprv zostaví zoznam uzlov, do ktorých možno naplánovať pod podľa zásady GeneralPredicates (ktorá zahŕňa sadu zásad PodFitsResources, PodFitsHostPorts, HostName a MatchNodeSelector). Potom sa každý uzol vyhodnotí v súlade so súborom politík v poli priorít. Na splnenie podmienok našej úlohy sme považovali takýto súbor politík za optimálne riešenie. Dovoľte mi pripomenúť, že súbor pravidiel s ich podrobným popisom je dostupný v dokumentáciu. Na splnenie svojej úlohy môžete jednoducho zmeniť množinu použitých politík a priradiť im vhodné váhy.

Manifest nového plánovača kube, ktorý sme vytvorili na začiatku kapitoly, nazvime kube-scheduler-custom.yaml a umiestnime ho do nasledujúcej cesty /etc/kubernetes/manifests na tri hlavné uzly. Ak je všetko vykonané správne, Kubelet spustí modul na každom uzle a v protokoloch nášho nového plánovača kube uvidíme informáciu, že náš súbor zásad bol úspešne použitý:

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:{}]'

Teraz už zostáva len uviesť v špecifikácii nášho CronJob, že všetky požiadavky na plánovanie jeho modulov by mal spracovať náš nový plánovač kube:

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

Záver

Nakoniec sme dostali ďalší plánovač kube s jedinečnou sadou plánovacích politík, ktorých prácu monitoruje priamo kubelet. Okrem toho sme nastavili voľbu nového lídra medzi modulmi nášho kube-plánovača pre prípad, že by starý líder z nejakého dôvodu nebol dostupný.

Bežné aplikácie a služby sa naďalej plánujú prostredníctvom predvoleného plánovača kube a všetky úlohy cron boli úplne prenesené do nového. Zaťaženie vytvorené úlohami cron je teraz rovnomerne rozdelené medzi všetky uzly. Vzhľadom na to, že väčšina úloh cron sa vykonáva na rovnakých uzloch ako hlavné aplikácie projektu, výrazne sa tým znížilo riziko pohybu modulov v dôsledku nedostatku zdrojov. Po zavedení dodatočného plánovača kube už nevznikali problémy s nerovnomerným plánovaním úloh cron.

Prečítajte si aj ďalšie články na našom blogu:

Zdroj: hab.com

Pridať komentár