ProHoster > Blog > Stjórnsýsla > Að búa til viðbótar kube-tímaáætlun með sérsniðnu setti af tímasetningarreglum
Að búa til viðbótar kube-tímaáætlun með sérsniðnu setti af tímasetningarreglum
Kube-scheduler er óaðskiljanlegur hluti af Kubernetes, sem er ábyrgur fyrir tímasetningu belg yfir hnúta í samræmi við tilgreindar reglur. Oft, meðan á Kubernetes klasa stendur, þurfum við ekki að hugsa um hvaða reglur eru notaðar til að tímasetja hólf, þar sem sett af reglum sjálfgefna kube-áætlunargerðarmannsins hentar flestum hversdagslegum verkefnum. Hins vegar eru aðstæður þar sem það er mikilvægt fyrir okkur að fínstilla ferlið við að úthluta belgjum og það eru tvær leiðir til að framkvæma þetta verkefni:
Búðu til kube-tímaáætlun með sérsniðnu setti af reglum
Skrifaðu þinn eigin tímaáætlun og kenndu honum að vinna með API netþjónsbeiðnum
Í þessari grein mun ég lýsa framkvæmd fyrsta liðsins til að leysa vandamálið við ójafna tímasetningu eldstæðis á einu af verkefnum okkar.
Stutt kynning á því hvernig kube-scheduler virkar
Það er sérstaklega þess virði að hafa í huga þá staðreynd að kube-scheduler er ekki ábyrgur fyrir að skipuleggja belg beint - hann er aðeins ábyrgur fyrir því að ákvarða hnútinn sem belgurinn á að setja á. Með öðrum orðum, niðurstaðan af vinnu kube-scheduler er nafn hnútsins, sem það skilar til API-þjónsins fyrir tímasetningarbeiðni, og þar lýkur vinnu hans.
Í fyrsta lagi setur kube-scheduler saman lista yfir hnúta sem hægt er að tímasetja fræbelginn á í samræmi við forsendurnarstefnur. Næst fær hver hnútur af þessum lista ákveðinn fjölda punkta í samræmi við forgangsstefnurnar. Fyrir vikið er hnúturinn með hámarksfjölda punkta valinn. Ef það eru hnútar sem hafa sama hámarkseinkunn, er valinn tilviljunarkenndur. Lista og lýsingu á forsendum (síu) og forgangsröðun (stigagjöf) er að finna í skjöl.
Lýsing á vandamálahlutanum
Þrátt fyrir mikinn fjölda mismunandi Kubernetes þyrpinga sem verið er að viðhalda hjá Nixys, lentum við fyrst í vandræðum með að skipuleggja hólf aðeins nýlega, þegar eitt af verkefnum okkar þurfti að keyra mikinn fjölda reglubundinna verkefna (~100 CronJob einingar). Til að einfalda lýsingu á vandamálinu eins mikið og mögulegt er, tökum við sem dæmi eina örþjónustu, þar sem cron verkefni er sett af stað einu sinni á mínútu, sem skapar smá álag á CPU. Til að keyra cron verkefnið var úthlutað þremur hnútum með nákvæmlega eins eiginleika (24 vCPUs á hverjum).
Á sama tíma er ómögulegt að segja með nákvæmni hversu langan tíma CronJob mun taka að keyra, þar sem magn inntaksgagna er stöðugt að breytast. Að meðaltali, meðan á venjulegri notkun kube-scheduler stendur, keyrir hver hnútur 3-4 verktilvik, sem skapa ~20-30% af álaginu á CPU hvers hnúts:
Vandamálið sjálft er að stundum hætti cron verkefnabelg að vera tímasettur á einum af hnútunum þremur. Það er að segja að á einhverjum tímapunkti var ekki einn einasti belg fyrirhugaður fyrir einn af hnútunum, á meðan á hinum tveimur hnútunum voru 6-8 afrit af verkefninu í gangi, sem skapaði ~40-60% af CPU álaginu:
Vandamálið kom upp aftur með algerlega tilviljunarkenndri tíðni og tengdist stundum því augnabliki sem ný útgáfa af kóðanum var sett á markað.
Með því að hækka kube-scheduler skráningarstigið í stig 10 (-v=10), byrjuðum við að skrá hversu mörg stig hver hnút fékk á matsferlinu. Meðan á venjulegum áætlanagerð stendur mátti sjá eftirfarandi upplýsingar í annálunum:
Þeir. miðað við upplýsingarnar sem fengnar voru úr annálunum fékk hver hnútur jafn mörg lokastig og einn af handahófi valinn til skipulagningar. Á þeim tíma sem vandræðalegt skipulag átti sér stað litu dagbókin svona út:
Af því má sjá að einn hnútanna fékk færri lokastig en hinir og því var aðeins skipulagt fyrir þá tvo hnúta sem fengu hámarkseinkunn. Þannig vorum við örugglega sannfærð um að vandamálið liggur einmitt í tímasetningu belganna.
Frekari reikniritið til að leysa vandamálið var augljóst fyrir okkur - greindu annálana, skildu í hvaða forgangi hnúturinn fékk ekki stig og, ef nauðsyn krefur, stilltu stefnu sjálfgefna kube-tímaáætlunarinnar. Hins vegar stöndum við frammi fyrir tveimur mikilvægum erfiðleikum:
Á hámarksskráningarstigi (10) endurspeglast stig sem fæst aðeins fyrir suma forgangsröðun. Í ofangreindum útdrætti af annálum, geturðu séð að fyrir allar forgangsröðun sem endurspeglast í lognum, skora hnútar sama fjölda stiga í venjulegri og vandamálaáætlun, en lokaniðurstaðan þegar um er að ræða vandamálaáætlun er önnur. Þannig getum við komist að þeirri niðurstöðu að fyrir sum forgangsröðun eigi stigagjöf sér stað „á bak við tjöldin“ og við höfum enga leið til að skilja fyrir hvaða forgang hnúturinn fékk ekki stig. Við lýstum þessu vandamáli í smáatriðum í mál Kubernetes geymsla á Github. Þegar þetta var skrifað barst svar frá hönnuði um að skráningarstuðningi verði bætt við í Kubernetes v1.15,1.16, 1.17 og XNUMX uppfærslunum.
Það er engin auðveld leið til að skilja hvaða tiltekna sett af reglum kube-scheduler er að vinna með. Já, inn skjöl þessi listi er skráður, en hann inniheldur ekki upplýsingar um hvaða sérstakt vægi er úthlutað til hverrar forgangsstefnu. Þú getur séð lóðin eða breytt reglum sjálfgefna kube-áætlunarmannsins aðeins í frumkóða.
Það er athyglisvert að einu sinni gátum við skráð að hnútur fékk ekki stig samkvæmt ImageLocalityPriority stefnunni, sem gefur stig til hnút ef hann hefur þegar þá mynd sem nauðsynleg er til að keyra forritið. Það er að segja, á þeim tíma sem ný útgáfa af forritinu var sett út, tókst cron verkefninu að keyra á tveimur hnútum, hlaðið niður nýrri mynd úr docker registry til þeirra, og þar með fengu tveir hnútar hærri lokaeinkunn miðað við þann þriðja .
Eins og ég skrifaði hér að ofan, þá sjáum við ekki upplýsingar um mat á ImageLocalityPriority stefnunni, svo til að athuga forsendur okkar, dumpuðum við myndinni með nýju útgáfunni af forritinu á þriðja hnútinn, eftir það virkaði tímasetning rétt. . Það var einmitt vegna ImageLocalityPriority stefnunnar að tímasetningarvandamálið kom fram frekar sjaldan; oftar var það tengt einhverju öðru. Vegna þeirrar staðreyndar að við gátum ekki villuleit að fullu hverja stefnu á lista yfir forgangsröðun sjálfgefna kube-dagskrárinnar, þá þurftum við sveigjanlega stjórnun á stefnuskrárreglum fyrir pod.
Samsetning vandans
Við vildum að lausn vandans væri eins sértæk og mögulegt er, það er að megineiningar Kubernetes (hér er átt við sjálfgefna kube-tímaáætlun) ættu að vera óbreyttar. Við vildum ekki leysa vandamál á einum stað og búa það til á öðrum. Þannig komumst við að tveimur möguleikum til að leysa vandamálið, sem voru tilkynntir í inngangi greinarinnar - búa til viðbótar tímaáætlun eða skrifa þinn eigin. Aðalkrafan til að skipuleggja cron verkefni er að dreifa álaginu jafnt yfir þrjá hnúta. Þessari kröfu er hægt að fullnægja með núverandi kube-áætlunarstefnu, svo til að leysa vandamál okkar er ekkert mál að skrifa eigin tímaáætlun.
Leiðbeiningar um að búa til og dreifa viðbótar kube-tímaáætlun er lýst í skjöl. Hins vegar virtist okkur að Deployment einingin væri ekki nóg til að tryggja bilanaþol í rekstri jafn mikilvægrar þjónustu eins og kube-scheduler, svo við ákváðum að setja upp nýjan kube-scheduler sem Static Pod, sem yrði fylgst beint með. eftir Kubelet. Þannig höfum við eftirfarandi kröfur fyrir nýja kube-tímaáætlunina:
Þjónustan verður að vera notuð sem Static Pod á alla klasameistara
Veita verður bilunarvikmörk ef virki belgurinn með kube-scheduler er ekki tiltækur
Aðalforgangsatriði við skipulagningu ætti að vera fjöldi tiltækra tilfanga á hnútnum (LeastRequestedPriority)
Innleiðingarlausnir
Það er rétt að taka fram strax að við munum framkvæma alla vinnu í Kubernetes v1.14.7, vegna þess að Þetta er útgáfan sem var notuð í verkefninu. Byrjum á því að skrifa stefnuskrá fyrir nýja kúbe-dagskrána okkar. Við skulum taka sjálfgefna upplýsingaskrána (/etc/kubernetes/manifests/kube-scheduler.yaml) til grundvallar og koma því á eftirfarandi form:
Breytti heiti belgsins og ílátsins í kube-scheduler-cron
Tilgreindi notkun hafna 10151 og 10159 eins og valkosturinn var skilgreindur hostNetwork: true og við getum ekki notað sömu höfn og sjálfgefna kube-tímaáætlun (10251 og 10259)
Með því að nota --config færibreytuna tilgreindum við stillingarskrána sem þjónustan ætti að vera ræst með
Stillt uppsetning á stillingarskránni (scheduler-custom.conf) og tímasetningarstefnuskránni (scheduler-custom-policy-config.json) frá hýsillinum
Ekki gleyma því að kube-dagskrárinn okkar mun þurfa réttindi sem eru svipuð og sjálfgefna. Breyttu klasahlutverki þess:
Nú skulum við tala um hvað ætti að vera í stillingarskránni og tímasetningarstefnuskránni:
Stillingarskrá (scheduler-custom.conf)
Til að fá sjálfgefna kube-áætlunarstillingu verður þú að nota færibreytuna --write-config-to á skjöl. Við munum setja uppsetninguna sem myndast í skrána /etc/kubernetes/scheduler-custom.conf og minnka hana í eftirfarandi form:
Við stillum schedulerName á nafnið á kube-scheduler-cron þjónustunni okkar.
Í breytunni lockObjectName þú þarft líka að stilla heiti þjónustu okkar og ganga úr skugga um að færibreytan leaderElect stillt á satt (ef þú ert með einn aðalhnút geturðu stillt hann á ósatt).
Tilgreindi slóðina að skránni með lýsingu á áætlunarstefnu í færibreytunni algorithmSource.
Það er þess virði að skoða seinni punktinn nánar, þar sem við breytum breytum fyrir lykilinn leaderElection. Til að tryggja bilanaþol höfum við virkjað (leaderElect) ferlið við að velja leiðtoga (meistara) á milli belgjanna í kube-tímaáætluninni okkar með því að nota einn endapunkt fyrir þá (resourceLock) heitir kube-scheduler-cron (lockObjectName) í kube-system nafnrýminu (lockObjectNamespace). Hvernig Kubernetes tryggir mikið framboð á helstu íhlutum (þar á meðal kube-scheduler) má finna í grein.
Skipulagsregluskrá (scheduler-custom-policy-config.json)
Eins og ég skrifaði áðan getum við komist að því hvaða sérstakar stefnur sjálfgefna kube-áætlunarmaðurinn vinnur með aðeins með því að greina kóðann hans. Það er að segja, við getum ekki fengið skrá með tímasetningarreglum fyrir sjálfgefna kube-tímaáætlun á sama hátt og stillingarskrá. Við skulum lýsa áætlunarstefnunum sem við höfum áhuga á í /etc/kubernetes/scheduler-custom-policy-config.json skránni sem hér segir:
Þannig setur kube-scheduler fyrst saman lista yfir hnúta sem hægt er að tímasetja pod í samkvæmt GeneralPredicates stefnunni (sem inniheldur sett af PodFitsResources, PodFitsHostPorts, HostName og MatchNodeSelector stefnum). Og síðan er hver hnút metinn í samræmi við stefnuna í forgangsröðinni. Til að uppfylla skilyrði verkefnis okkar töldum við að slík stefna væri ákjósanleg lausn. Leyfðu mér að minna þig á að sett af stefnum með nákvæmum lýsingum þeirra er fáanlegt í skjöl. Til að framkvæma verkefnið þitt geturðu einfaldlega breytt settinu af reglum sem notaðar eru og úthlutað þeim viðeigandi vægi.
Við skulum kalla upplýsingaskrá nýja kube-scheduler, sem við bjuggum til í upphafi kaflans, kube-scheduler-custom.yaml og setja hana í eftirfarandi slóð /etc/kubernetes/manifests á þremur aðalhnútum. Ef allt er gert á réttan hátt mun Kubelet ræsa hólf á hverjum hnút og í annálum nýja kube-tímaáætlunar okkar munum við sjá upplýsingar um að stefnuskránni okkar hafi verið beitt:
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:{}]'
Nú er allt sem eftir er að gefa til kynna í forskrift CronJob okkar að allar beiðnir um að skipuleggja belg þess ættu að vera afgreiddar af nýja kube-tímaáætluninni okkar:
Á endanum fengum við viðbótartímaáætlunarforrit með einstökum tímasetningarreglum, sem fylgst er með vinnunni beint af kubelet. Að auki höfum við sett upp val á nýjum leiðtoga á milli flokka kube-dagskrárinnar okkar ef gamli leiðtoginn verður ófáanlegur af einhverjum ástæðum.
Regluleg forrit og þjónusta halda áfram að vera tímasett í gegnum sjálfgefna kube-tímaáætlunina og öll cron verkefni hafa verið flutt að fullu yfir í þann nýja. Álagið sem skapast af cron verkefnum er nú jafnt dreift yfir alla hnúta. Miðað við að flest cron verkefnin eru framkvæmd á sömu hnútum og helstu forrit verkefnisins, hefur þetta dregið verulega úr hættu á að flytja belg vegna skorts á fjármagni. Eftir að viðbótarkube-áætlunarmaðurinn var kynntur komu ekki lengur upp vandamál með ójafna tímasetningu cron-verkefna.