Создавање дополнителен кубе-распоредувач со прилагоден сет на правила за распоред

Создавање дополнителен кубе-распоредувач со прилагоден сет на правила за распоред

Кубе-распоредувачот е интегрална компонента на Kubernetes, кој е одговорен за распоредување на места низ јазлите во согласност со наведените политики. Често, за време на работењето на кластерот Kubernetes, не мора да размислуваме за тоа кои политики се користат за закажување на подлоги, бидејќи множеството политики на стандардниот распоред на kube е погодно за повеќето секојдневни задачи. Сепак, постојат ситуации кога ни е важно да го прилагодиме процесот на распределба на мешунките, и постојат два начини да се постигне оваа задача:

  1. Создадете кубе-распоредувач со прилагоден сет на правила
  2. Напишете свој распоредувач и научете го да работи со барањата на серверот API

Во оваа статија, ќе ја опишам имплементацијата на првата точка за решавање на проблемот со нерамномерно распоредување на огништата на еден од нашите проекти.

Краток вовед за тоа како функционира кубе-распоредувачот

Посебно вреди да се напомене фактот дека кубе-распоредувачот не е одговорен за директно закажување на подлоги - тој е одговорен само за одредување на јазолот на кој ќе се постави подлогата. Со други зборови, резултатот од работата на kube-распоредувачот е името на јазолот, кој го враќа на API-серверот за барање за распоред, и тука завршува неговата работа.

Прво, kube-scheduler составува листа на јазли на кои може да се закаже подлогата во согласност со политиките за предикати. Следно, секој јазол од оваа листа добива одреден број поени во согласност со политиките за приоритети. Како резултат на тоа, се избира јазолот со максимален број поени. Ако има јазли кои имаат ист максимален резултат, се избира случаен избор. Список и опис на политиките за предикати (филтрирање) и приоритети (бодување) може да се најдат во документација.

Опис на проблематичното тело

И покрај големиот број различни кластери на Kubernetes што се одржуваат во Nixys, за прв пат наидовме на проблемот со закажување подлоги дури неодамна, кога еден од нашите проекти требаше да изврши голем број периодични задачи (~ 100 CronJob ентитети). За да го поедноставиме описот на проблемот што е можно повеќе, ќе земеме како пример еден микросервис, во кој cron задача се активира еднаш во минута, создавајќи одредено оптоварување на процесорот. За извршување на задачата cron, беа доделени три јазли со апсолутно идентични карактеристики (24 vCPU на секој).

Во исто време, невозможно е да се каже со точност колку време ќе биде потребно за извршување на CronJob, бидејќи обемот на влезните податоци постојано се менува. Во просек, за време на нормалното функционирање на kube-распоредувачот, секој јазол работи 3-4 случаи на работни места, кои создаваат ~ 20-30% од оптоварувањето на процесорот на секој јазол:

Создавање дополнителен кубе-распоредувач со прилагоден сет на правила за распоред

Самиот проблем е што понекогаш cron task pods престанаа да се закажуваат на еден од трите јазли. Односно, во одреден момент во времето, не беше планирано ниту еден pod за еден од јазлите, додека на другите два јазли работеа 6-8 копии од задачата, создавајќи ~ 40-60% од оптоварувањето на процесорот:

Создавање дополнителен кубе-распоредувач со прилагоден сет на правила за распоред

Проблемот се повторуваше со апсолутно случајна фреквенција и повремено беше во корелација со моментот кога беше објавена нова верзија на кодот.

Со зголемување на нивото на евиденција на kube-распоредувач на ниво 10 (-v=10), почнавме да бележиме колку поени добил секој јазол за време на процесот на евалуација. За време на нормалното планирање, следните информации може да се видат во дневниците:

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

Оние. судејќи според информациите добиени од дневниците, секој од јазлите освои еднаков број на финални поени и по случаен избор беше избран за планирање. За време на проблематичното планирање, дневниците изгледаа вака:

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

Од што може да се види дека еден од јазлите освоил помалку конечни поени од другите, и затоа се планирало само за двата јазли кои постигнале максимален резултат. Така, дефинитивно се уверивме дека проблемот лежи токму во распоредот на мешунките.

Понатамошниот алгоритам за решавање на проблемот ни беше очигледен - анализирајте ги дневниците, разберете со кој приоритет јазолот не освоил поени и, доколку е потребно, прилагодете ги политиките на стандардниот кубе-распоредувач. Меѓутоа, овде се соочуваме со две значајни тешкотии:

  1. На максималното ниво на сеча (10), бодовите добиени само за некои приоритети се рефлектираат. Во горенаведениот извадок од дневници, можете да видите дека за сите приоритети рефлектирани во дневниците, јазлите добиваат ист број поени при нормално и распоредување на проблеми, но конечниот резултат во случај на планирање на проблеми е различен. Така, можеме да заклучиме дека за некои приоритети, бодирањето се случува „зад сцената“ и немаме начин да разбереме за кој приоритет јазолот не добил поени. Детално го опишавме овој проблем прашање Кубернетес складиште на Github. Во моментот на пишувањето, беше добиен одговор од програмерите дека поддршката за евиденција ќе биде додадена во ажурирањата на Kubernetes v1.15,1.16, 1.17 и XNUMX.
  2. Не постои лесен начин да се разбере со кој специфичен сет на политики кубе-распоредувач моментално работи. Да, во документација оваа листа е наведена, но не содржи информации за тоа какви специфични тежини се доделуваат на секоја од приоритетните политики. Може да ги видите тежините или да ги уредувате политиките на стандардниот распоред на kube само во извори.

Вреди да се напомене дека откако можевме да снимиме дека јазолот не добива поени според политиката ImageLocalityPriority, која доделува поени на јазол ако веќе ја има сликата неопходна за да ја изврши апликацијата. Односно, во моментот кога беше објавена новата верзија на апликацијата, задачата cron успеа да работи на два јазли, преземајќи нова слика од докер-регистарот на нив, и на тој начин два јазли добија повисока конечна оценка во однос на третиот .

Како што напишав погоре, во дневниците не гледаме информации за евалуација на политиката ImageLocalityPriority, па за да ја провериме нашата претпоставка, ја фрливме сликата со новата верзија на апликацијата на третиот јазол, по што распоредот функционираше правилно. . Токму поради политиката ImageLocalityPriority проблемот со распоредот се забележуваше доста ретко; почесто беше поврзан со нешто друго. Поради фактот што не можевме целосно да ги отстраниме грешките на секоја од политиките во списокот со приоритети на стандардниот кубе-распоредувач, имавме потреба од флексибилно управување со политиките за распоред на подлоги.

Проблем изјава

Сакавме решението на проблемот да биде што е можно поконкретно, односно главните ентитети на Kubernetes (тука мислиме на стандардниот kube-распоредувач) да останат непроменети. Не сакавме да решаваме проблем на едно место, а да го создаваме на друго. Така, дојдовме до две опции за решавање на проблемот, кои беа објавени во воведот на статијата - создавање дополнителен распоредувач или пишување свој. Главниот услов за закажување на задачите на cron е рамномерно да се дистрибуира оптоварувањето низ три јазли. Ова барање може да биде задоволено со постојните правила на кубе-распоредувач, така што за да се реши нашиот проблем, нема смисла да пишувате сопствен распоредувач.

Инструкциите за креирање и распоредување на дополнителен кубе-распоредувач се опишани во документација. Сепак, ни се чинеше дека ентитетот Deployment не е доволен за да обезбеди толеранција на грешки во работењето на таква критична услуга како што е kube-scheduler, па решивме да распоредиме нов kube-распоредувач како Static Pod, кој директно ќе се следи од Кубелет. Така, ги имаме следниве барања за новиот kube-распоредувач:

  1. Услугата мора да биде распоредена како статична подлога на сите господари на кластери
  2. Мора да се обезбеди толеранција на грешки во случај ако активниот под со kube-распоредувач е недостапен
  3. Главниот приоритет при планирањето треба да биде бројот на достапни ресурси на јазолот (LeastRequestedPriority)

Решенија за имплементација

Вреди да се напомене веднаш дека ќе ја извршиме целата работа во Kubernetes v1.14.7, бидејќи Ова е верзијата што беше користена во проектот. Да почнеме со пишување манифест за нашиот нов распоредувач на кубе. Да го земеме стандардниот манифест (/etc/kubernetes/manifests/kube-scheduler.yaml) како основа и да го доведеме во следнава форма:

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

Накратко за главните промени:

  1. Го смени името на подлогата и контејнерот во kube-scheduler-cron
  2. Наведена е употребата на портите 10151 и 10159 како што беше дефинирана опцијата hostNetwork: true и не можеме да ги користиме истите порти како стандардниот кубе-распоредувач (10251 и 10259)
  3. Користејќи го параметарот --config, ја одредивме конфигурациската датотека со која треба да се стартува услугата
  4. Конфигурирано монтирање на конфигурациската датотека (scheduler-custom.conf) и датотека со политика за закажување (scheduler-custom-policy-config.json) од домаќинот

Не заборавајте дека на нашиот кубе-распоредувач ќе му требаат права слични на стандардните. Уредете ја неговата улога во кластерот:

kubectl edit clusterrole system:kube-scheduler

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

Сега да разговараме за тоа што треба да биде содржано во конфигурациската датотека и датотеката за политика за распоред:

  • Конфигурациска датотека (scheduler-custom.conf)
    За да ја добиете стандардната конфигурација на кубе-распоредувач, мора да го користите параметарот --write-config-to на документација. Добиената конфигурација ќе ја поставиме во датотеката /etc/kubernetes/scheduler-custom.conf и ќе ја намалиме на следната форма:

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"

Накратко за главните промени:

  1. Го поставивме schedulerName на името на нашата услуга kube-scheduler-cron.
  2. Во параметарот lockObjectName исто така треба да го поставите името на нашата услуга и да бидете сигурни дека параметарот leaderElect поставено на точно (ако имате еден главен јазол, можете да го поставите на неточно).
  3. Наведена е патеката до датотеката со опис на политиките за распоред во параметарот algorithmSource.

Вреди да се разгледа подетално втората точка, каде што ги уредуваме параметрите за клучот leaderElection. За да обезбедиме толеранција на грешки, овозможивме (leaderElect) процесот на избор на водач (господар) помеѓу деловите на нашиот кубе-распоредувач користејќи единствена крајна точка за нив (resourceLock) именуван како kube-scheduler-cron (lockObjectName) во именскиот простор на кубе системот (lockObjectNamespace). Како Kubernetes обезбедува висока достапност на главните компоненти (вклучувајќи кубе-распоредувач) може да се најде во Член.

  • Датотека со политика за закажување (scheduler-custom-policy-config.json)
    Како што напишав претходно, можеме да дознаеме со кои специфични политики работи стандардниот kube-распоредувач само со анализа на неговиот код. Односно, не можеме да добиеме датотека со политики за закажување за стандардниот кубе-распоредувач на ист начин како конфигурациската датотека. Ајде да ги опишеме политиките за распоред што нè интересираат во датотеката /etc/kubernetes/scheduler-custom-policy-config.json на следниов начин:

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

Така, kube-распоредувачот најпрво составува листа на јазли на кои може да се закаже pod според политиката GeneralPredicates (која вклучува збир на политики PodFitsResources, PodFitsHostPorts, HostName и MatchNodeSelector). И тогаш секој јазол се оценува во согласност со множеството политики во низата приоритети. За исполнување на условите на нашата задача, сметавме дека таквиот сет на политики ќе биде оптимално решение. Дозволете ми да ве потсетам дека сет на политики со нивните детални описи се достапни во документација. За да ја исполните вашата задача, можете едноставно да го промените множеството користени политики и да им доделите соодветни тежини.

Да го наречеме манифестот на новиот kube-scheduler, кој го создадовме на почетокот на поглавјето, kube-scheduler-custom.yaml и да го поставиме на следната патека /etc/kubernetes/manifests на три главни јазли. Ако сè е направено правилно, Kubelet ќе стартува подлога на секој јазол и во дневниците на нашиот нов kube-распоредувач ќе видиме информации дека нашата датотека со политики е успешно применета:

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

Сега останува само да укажеме во спецификациите на нашиот CronJob дека сите барања за закажување на неговите подлоги треба да бидат обработени од нашиот нов кубе-распоредувач:

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

Заклучок

На крајот, добивме дополнителен кубе-распоредувач со уникатен сет на политики за распоред, чија работа се следи директно од кубелет. Дополнително, го поставивме изборот на нов лидер помеѓу подлогите на нашиот кубе-распоредувач во случај стариот лидер да стане недостапен поради некоја причина.

Редовните апликации и услуги продолжуваат да се закажуваат преку стандардниот кубе-распоредувач, а сите cron задачи се целосно префрлени на новиот. Оптоварувањето создадено од cron задачите сега е рамномерно распределено низ сите јазли. Имајќи предвид дека повеќето од задачите на cron се извршуваат на истите јазли како и главните апликации на проектот, ова значително го намали ризикот од поместување подови поради недостаток на ресурси. По воведувањето на дополнителниот кубе-распоредувач, веќе не се појавија проблеми со нерамномерно распоредување на задачите на cron.

Прочитајте и други написи на нашиот блог:

Извор: www.habr.com

Додадете коментар