
Kube-scheduler գործառույթը Kubernetes-ի անբաժանելի բաղադրիչն է, որը պատասխանատու է նոդերի վրա պոդերի ծրագրավորման համար կազմված քաղաքականությունների համաձայն: Հաճախ, Kubernetes կլաստերի շահագործման ընթացքում մեր կողմից չի պահանջվում մտածել, թե որ քաղաքականությունների համաձայն է պոդերի ծրագրավորումը, քանի որ մուտքային kube-scheduler-ի նախնական կոմպլեկտը համապատասխանում է յուրաքանչյուրօրյա խնդիրների մեծամասնությանը: Սակայն լինում են իրավիճակներ, երբ կարևոր է ավելի մանրակրկիտ կառավարել պոդերի բաշխման պրոցեսը, և այս խնդրի լուծման համար կան երկու ճանապարհ.
- Ստեղծել kube-scheduler՝ անհատական կարգավորումներով
- Գրել սեփական ծրագիրը և սովորեցնել այն աշխատել API-ծառի հետ
Այս հոդվածում ես կբացատրեմ առաջին կետի իրականացումը՝ մեր նախագծերից մեկում պոդերի անհավասար ծրագրավորման խնդրի լուծման համար:
Kube-scheduler-ի աշխատանքի մասին կարճ ներկայացում
Առանձնահատուկ կարեւոր է նշել, որ kube-scheduler-ը չի պատասխանաբանում անմիջական պոդերի ծրագրավորմանը՝ այն միայն պատասխանատու է որոշելու համար, թե ո՞ր նոդի վրա պետք է տեղադրել պոդը: Այլ կերպ ասած, kube-scheduler-ի աշխատանքի արդյունքը վերադարձվող նոդի անունն է API-ծառի կողմից ծրագրավորման հարցման համար, և այդ ժամանակ նրա աշխատանքը ավարտվում է.
Նախ kube-scheduler-ը կազմում է ցանկ նոդերի, որոնց վրա կարող է պլանավորել պոդը՝ համաձայն predicates քաղաքականությունների: Այնուհետեւ այդ ցանկի յուրաքանչյուր նոդն ստանում է որոշակի քանակի միավորներ՝ կախված priorites քաղաքականություններից: Այդ արդյունքում ընտրվում է նոդը, որը հասել է առավելագույն միավորների: Եթե կան նոդեր, որոնք ստացել են նույն առավելագույն միավորները, ապա մեկը պատահականորեն է ընտրվում: Predicates (համաձայնեցում) և priorites (գնահատում) քաղաքականությունների ցանկով և նկարագրությամբ կարող եք ծանոթանալ .
Կատարված խնդրի նկարագրություն
Միեւնույն ժամանակ, pese Nixys-ի վրա սպասարկվող բազմաթիվ տարբեր Kubernetes կլաստերների, մենք առաջին անգամ պոդերի ծրագրավորման խնդրին հանդիպեցինք միայն վերջերս, երբ մեր նախագծերից մեկի համար անհրաժեշտություն առաջացավ աշխատացնել մեծ քանակությամբ ժամանակացույցային խնդիրներ (~100 CronJob զանգվածներ): Որպես խնդրի նկարագրության հնարավորինս պարզեցնելու համար, օրինակ կբերենք մեկ միկրասերվիս, որի շրջանակներում ամեն րոպե աշխատացնելու է cron-խնդիր, որը մի определенная нагрузка է ստեղծում CPU-ի վրա: Cron-Խնդրի աշխատելու համար հատկացվել են երեք լիովին նմանացված հատկություններով նոդեր (24 vCPU յուրաքանչյուրում).
Միաժամանակ, հնարավոր չէ ճշգրտորեն ասել, որքան ժամանակ կտեւի CronJob-ը, քանի որ մուտքային տվյալների ծավալը մշտապես փոխվում է: Ուսումնասիրելով, միջինում, երբ kube-scheduler-ը աշխատում է նորմալ, յուրաքանչյուր նոդում աշխատում է 3-4 օրինակ խնդիր, որոնք ստեղծում են ~20-30% ծանրաբեռնվածություն յուրաքանչյուր նոդի CPU-ի վրայ:

Զուգահեռ խնդիրն այն է, որ soms cron-պոդերը դադարեցին պլանավորվել երեք հանգույցներից մեկում: Այսինքն,某些时刻,某个节点上 не было պլանավորված ոչ մի պոդ, մինչդեռ երկու այլ հանգույցներում աշխատում էին 6-8 օրինակներ, ստեղծելով ~40-60% բեռ CPU-ում:

Խնդիրը կրկնվում էր իհարկե պատահական հաճախականությամբ և հազվադեպ կապվում էր նոր կոդի տարբերակի թողարկման պահի հետ:
kube-scheduler-ի լոգավորման մակարդակը բարձրացնելով մինչև 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Հայտնի է, որ մի կայան ավելի քիչ միավորներ է հավաքել, քան մյուսները, ուստի պլանավորումը իրականացվել է միայն երկու կայանի համար, որոնք ունեին առավելագույն միավորներ: Այս կերպ մենք վստահաբար համոզվեցինք, որ խնդիրը գտնվում է կայանների պլանավորման մեջ:
Չարագործության խնդիրների լուծման հաջորդ ալգորիթմը մեզ համար ակնհայտ էր՝ վերլուծել գրառումները, հասկանալ, թե ի՞նչ առաջնահերթության պատճառով կայանը չի հավաքել միավորներ և, անհրաժեշտության դեպքում, корректировать նախադրյալ kube-scheduler-ի քաղաքականությունները: Սակայն այստեղ մենք բախվեցինք երկու էական դժվարությունների:
- Մաքսիմալ գրLoggingման մակարդակում (10) արտացոլվում է միավորների հավաքածու միայն որոշ առաջնահերթությունների համար: Կատակին ներկայացված գրառման հատվածում նկատվում է, որ բոլոր առաջնահերթություններով, որոնք արտացոլված են գրառման մեջ, կայանները հավաքում են նույն աստիճանի միավորներ սովորական և խնդիրներով պլանավորման ընթացքում, սակայն խնդրային պլանավորման դեպքում վերջնական արդյունքը տարբերվում է: Այսպիսով, կարելի է որոշում կայացնել, որ որոշ առաջնահերթությունների համար միավորների հաշվարկը տեղի է ունենում "թիկունքից", և մենք չունենք որևէ հնարավորություն հասկանալու, թե ի՞նչ առաջնահերթությամբ կայանը չի հավաքել միավորներ: Այս խնդիրը մանրամասնորեն նկարագրված է Kubernetes-ի բանկում GitHub-ում: Գրելիս հոդվածը, պատասխան ենք ստացել զարգացողների կողմից, որLoggingման աջակցության ավելացումը կպայմանավորված լինի Kubernetes-ի v1.15, 1.16 և 1.17 թարմացումներում:
- Չկա պարզ միջոց հասկանալու, թե կոնկրետ քաղաքականությունների հետ ինչ համադրությամբ աշխատում է kube-scheduler-ը: Այո, այս ցուցակում ցուցադրվում է, բայց դրա մեջ չկա տեղեկություն, թե կոնկրետ ինչ քաշեր են դրված յուրաքանչյուր քաղաքականության համար: Քաշերը տեսնելու կամ kube-scheduler-ի նախնական քաղաքականությունները խմբագրելու հնարավորություն կա միայն գործարկման աղբյուրներում: .
Ինչպես արդեն նշեցի, փաստաթղթերում մենք չենք տեսնում տեղեկություն ImageLocalityPriority քաղաքականության գնահատման մասին, ուստի, մեր ենթադրությունը ստուգելու համար, մենք նոր տարբերակի նկարը փոխեցինք երրորդ կայանի վրա, հետո պլանավորումը սկսեց աշխատել ճիշտ: Հատկապես ImageLocalityPriority քաղաքականության պատճառով պլանավորման խնդիրը նկատվում էր բավականին հազվագյուտ, ավելի հաճախ այն կապված էր ինչ-որ այլ գաղափարի: Այն պատճառով, որ չենք կարողանում լիովին դեբագար հսկելու յուրաքանչյուր քաղաքականություն kube-scheduler-ի նախնական ցուցակում, մենք ունեինք անհրաժեշտություն պահանջում պլանավորման քաղաքականությունների ճկուն կառավարման:
Как я уже писал выше, в логах мы не видим информации об оценке политики ImageLocalityPriority, поэтому, чтобы проверить своё предположение, мы спулили образ с новой версией приложения на третью ноду, после чего планирование заработало корректно. Именно из-за политики ImageLocalityPriority проблема планирования наблюдалась достаточно редко, чаще она была связана с чем-то другим. Из-за того, что мы не могли полноценно дебажить каждую из политик в списке priorites дефолтного kube-scheduler’a, у нас появилась необходимость в гибком управлении политиками планирования подов.
Պատասխանատվության ներկայացում
Մենք ցանկանում էինք, որ խնդրի լուծումն առավելագույնս նպատակային լինի, այսինքն՝ հիմնական Kubernetes էությունների (այստեղ նկատվում է լռելյայն kube-scheduler-ը) փոփոխությունները չլինեն: Մեզ չէր ցանկանում լուծել խնդիրը մեկ տեղում և ստեղծել այն ուրիշ տեղում: Այդպես, մենք առաջարկեցինք երկու տարբերակ, որոնք նշված էին հոդվածի մուտքում՝ լրացուցիչ scheduler-ի ստեղծումը կամ մեր սեփականը գրել: Cron-նախագծերի պլանավորման հիմնական պահանջը՝ բեռի համաչափ բաժանումը երեք նոդերի միջև: Այս պահանջը կարող է ապահովվել արդեն գոյություն ունեցող kube-scheduler-ի քաղաքականություններով, այդ իսկ պատճառով մեր խնդրի լուծման համար իմաստ չունի գրել մեր սեփական scheduler-ը।
Լրացուցիչ kube-scheduler-ի ստեղծման և Deployment-ի հրահանգները շարադրված են . Սակայն, մեզ այն թվաց, որ Deployment-ի միությունները բավարար չեն kube-scheduler-ի նման կրիտիկական ծառայության աշխատանքը ապահովելու համար, այդ պատճառով մենք որոշեցինք նոր kube-scheduler-ը ներդնել որպես Static Pod, որի վրա անմիջապես Kubelet-ը հաճախակի հետևի: Այդպիսով, մեզ ստեղծվեցին հետևյալ պահանջները նոր kube-scheduler-ի համար:
- Ծառայությունը պետք է ներդրվել որպես Static Pod բոլոր դասակարգային վարպետներում
- Պետք է նախատեսվի նախազգուշական միջոց տվյալ kube-scheduler-ի ակտիվ pod-ի անհասանելիության դեպքում
- Պլանավորման հիմնական առաջնահերթությունն լինել պետք է ռեսուրսների կատարելու քանակը նոդում (LeastRequestedPriority)
Լուծման իրականացումը
Հայտարարում եմ, որ բոլոր աշխատանքներն անցկացնելու ենք Kubernetes v1.14.7-ում, քանի որ հենց այդ տարբերակը օգտագործվել է նախագծում: Կսկսենք մեզ նոր kube-scheduler-ի համար մանիֆեստի գրությունից: Հիմզբում կօգտագործենք լռելյայն մանիֆեստը (\/etc\/kubernetes\/manifests\/kube-scheduler.yaml) և դրան կհասցնենք հետևյալ տեսքի:
թիպ: Pod
բարելավումներ:
պիտակներ:
բաղադրիչ: scheduler
աստիճան: control-plane
անվանում: kube-scheduler-cron
անունի տարածք: kube-system
մասնագիտություն:
կոնտեյներներ:
- հրահանգ:
- /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
պատկեր: gcr.io/google-containers/kube-scheduler:v1.14.7
պատկերPullPolicy: IfNotPresent
կենսունակությանՀետազոտություն:
թերությանԵզրակացություն: 8
httpGet:
հյուրը: 127.0.0.1
ճանապարհ: /healthz
նավահանգիստ: 10151
կարգ: HTTP
սկզբնականDelaySeconds: 15
timeoutSeconds: 15
անվանում: kube-scheduler-cron-container
աղբյուրներ:
պահանջներ:
cpu: '0.1'
ծավալMounts:
- mountPath: /etc/kubernetes/scheduler.conf
անվանում: kube-config
ընթերցողՄիայն: true
- mountPath: /etc/localtime
անվանում: localtime
ընթերցողՄիայն: true
- mountPath: /etc/kubernetes/scheduler-custom.conf
անվանում: scheduler-config
ընթերցողՄիայն: true
- mountPath: /etc/kubernetes/scheduler-custom-policy-config.json
անվանում: policy-config
ընթերցողՄիայն: true
հյուրըNetwork: true
առաջնահերթության className: system-cluster-critical
ծավալներ:
- hostPath:
ճանապարհ: /etc/kubernetes/scheduler.conf
տեսակը: FileOrCreate
անվանում: kube-config
- hostPath:
ճանապարհ: /etc/localtime
անվանում: localtime
- hostPath:
ճանապարհ: /etc/kubernetes/scheduler-custom.conf
տեսակը: FileOrCreate
անվանում: scheduler-config
- hostPath:
ճանապարհ: /etc/kubernetes/scheduler-custom-policy-config.json
տեսակը: FileOrCreate
անվանում: policy-configԿարճ անդրադարձ հիմնական փոփոխություններին:
- Փոփոխեցինք pod-ի և կոնտեյներների անվանումները kube-scheduler-cron-ով
- Ուսացրեցինք 10151 և 10159 նավահանգիստների օգտագործումը, քանի որ որոշված է ընտրանք
hostNetwork: trueև չենք կարող օգտագործել նույն նավահանգիստները, ինչ նպատակային kube-scheduler (10251 և 10259) - Առանց կարգի օրենքով կիրառեցինք config պարամետրով այն ֆայլը, որով պետք է աշխատի ծառայությունը
- Կարգավորեցինք config ֆայլի (scheduler-custom.conf) և պլանավորման քաղաքականության ֆայլի (scheduler-custom-policy-config.json) մոնտաժումը հյուրը:
Не забудем, что нашему kube-scheduler’у потребуются права, аналогичные дефолтному. Редактируем его кластерную роль:
kubectl edit clusterrole system:kube-scheduler...
resourceNames:
- kube-scheduler
- kube-scheduler-cron
...Այժմ խոսենք այն մասին, ինչ պետք է լինի config և պլանավորման քաղաքականության ֆայլում:
- Config ֆայլ (scheduler-custom.conf)
Դառնալու համար config ստանալու համար պետք է օգտագործել պարամետրը--write-config-toԱյս հոդվածից . Ստացված config-ը կարող ենք դնել ֆոլդերում /etc/kubernetes/scheduler-custom.conf և բերել հաջորդ տեսքի:
apiVersion: kubescheduler.config.k8s.io/v1alpha1
թիպ: KubeSchedulerConfiguration
schedulerName: kube-scheduler-cron
bindTimeoutSeconds: 600
clientConnection:
acceptContentTypes: ""
burst: 100
contentType: application/vnd.kubernetes.protobuf
kubeconfig: /etc/kubernetes/scheduler.conf
qps: 50
հաղորդակցումըPreemption: false
միալոգարարայինProfiling: false
հնարավորProfiling: false
մահվան տարածքներ: kubernetes.io/hostname,failure-domain.beta.kubernetes.io/zone,failure-domain.beta.kubernetes.io/region
hardPodAffinitySymmetricWeight: 1
healthzBindAddress: 0.0.0.0:10151
նախագահական ընտրություն:
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"Կարճ անդրադարձ հիմնական փոփոխություններին:
- Ստեղծեցինք schedulerName մեր ծառայության անունը kube-scheduler-cron։
- Параметр
lockObjectNameփոքր շարժման անվանմանը մեր ծառայության անունը կարգաբերման անհրաժեշտ է և համոզվել, որ պարամետրըleaderElectնշանակված է true (եթե ձեզ մոտ մեկ մայիսի պարամետր է, կարելի է նշանակել false). - Կարևոր է նշել քաղաքականության նկարագրության ֆայլի ճանապարհը
algorithmSource.
Պարամետրերի շտկումների երկրորդ կետի վրա ավելի մանրամասն կանգ առնելն անհրաժեշտ է leaderElection. Վստահության ապահովման համար մենք վերագործարկեցինք (leaderElect) ղեկավարի (մայստերի) ընտրության գործընթացը մեր kube-scheduler-ի միջև, օգտագործելով մի ընդհանուր endpoint (resourceLock) անունով kube-scheduler-cron (lockObjectName) kube-system անունաձևում (lockObjectNamespace). Kubernetes-ում բարձր հասանելիության ապահովման մասին (այդ թվում՝ kube-scheduler) կարող եք ծանոթանալ .
- Նախագծման քաղաքականության ֆայլը (scheduler-custom-policy-config.json)
Ինչպես արդեն նշեցի, պարզելու համար՝ հատկապես որ քաղաքականություններով է աշխատում նորմալ kube-scheduler-ը, մենք կարող ենք միայն վերլուծելով նրա կոդը: Այսինքն, մենք չենք կարող ստանալ ֆայլ, որը պարունակում է նորմալ kube-scheduler-ի քաղաքականությունը՝ նման ֆայլի կոնֆիգուրացիայի: Մենք կբնորոշենք մեզ հետաքրքրող քաղաքականությունները ֆայլում /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-scheduler-ը նախ կազմել է այն նոդերը, որոնց վրա կարող է պլանում լինել ենթակառուցվածքը՝ ըստ GeneralPredicates քաղաքականության ( որը ներառում է PodFitsResources, PodFitsHostPorts, HostName և MatchNodeSelector քաղաքականությունները): Այնուհետև յուրաքանչյուր նոդը գնահատվում է ´priorities´ կոդի քաղաքականությունների համադրմամբ: Մեր առաջադրանքի պահանջների բավարարում համար մենք կարծում ենք, որ այդ քաղաքականությունների կաղապարը լավագույն լուծումն է: Հիշեցնելով, որ քաղաքականությունների համադրման նկարագիրը հասանելի է . Ձեր առաջադրանքը իրականացնելու համար դուք կարող եք պարզապես փոխել օգտագործվող քաղաքականությունների համադրությունը և նշանակել նրանց համապատասխան բեռները.
Այսպես, նոր kube-scheduler-ի մանիֆեստը, որ ստեղծեցինք գլխում, անվանելու ենք kube-scheduler-custom.yaml և տեղադրելու ենք /etc/kubernetes/manifests հասցեում երեք մայսեր-ի վրա: Եթե ամեն ինչ ճիշտ է արվել, Kubelet-ը յուրաքանչյուր նոդում կընդունի ենթակառուցվածքը, իսկ մեր նոր kube-scheduler-ի անվանումը կտեսնենք, որ մեր քաղաքականության ֆայլը հաջողությամբ կիրառվել է:
Կարգավորումից օրացույցի ստեղծում՝ {{ } [{GeneralPredicates }] [{ServiceSpreadingPriority 1 } {EqualPriority 1 } {LeastRequestedPriority 1 } {NodePreferAvoidPodsPriority 10000 } {NodeAffinityPriority 1 } ] [] 10 falseՀիմա մնում է միայն նշել մեր CronJob-ի հատուկ տվյալներում, որ նրա pod-երի պլանավորման բոլոր հարցումները պետք է մշակել մեր նոր kube-scheduler-ով:
...
jobTemplate:
spec:
template:
spec:
schedulerName: kube-scheduler-cron
...Ավարտ
Վերջապես մենք ստացանք լրացուցիչ kube-scheduler, որն ունի յուրահատուկ պլանավորման քաղաքականության հավաքածու, որի աշխատանքի համար անմիջականորեն հետևում է kubelet-ը: Բացի այդ, մենք կարգավորեցինք նոր ղեկավարի ընտրությունը մեր kube-scheduler-ի pod-երի միջև, եթե հինը ինչ-ինչ պատճառներով դառնա անվճռական:
Սովորական ծրագրերն ու ծառայությունները շարունակում են պլանավորվել խորը kube-scheduler-ի միջոցով, իսկ բոլոր cron-հարցեր լիովին անց հայկական նորին: Cron-հարցերի ստեղծած բեռը այժմ հավասարաչափ բաժանվում է բոլոր հանգույցների միջև: Քանի որ մեծ մասի cron-հարցերը իրականացվում են նույն հանգույցներում, ինչ խորը ծրագրերն, դա թույլատրեց զգալիորեն նվազեցնել ռիսկեր pod-երի տեղափոխման հետ կապված ռեսուրսների պակասի պատճառով: Լրացուցիչ kube-scheduler-ի ներդրումից հետո, cron-հարցերի անհավասար պլանավորման խնդիրներ այլևս գոյություն չունեին:
Շարունակեք կարդալ մեր բլոգի մյուս հոդվածները՝
Ընտանիք: habr.com
