Naše izkušnje pri razvoju gonilnika CSI v Kubernetesu za Yandex.Cloud

Naše izkušnje pri razvoju gonilnika CSI v Kubernetesu za Yandex.Cloud

Z veseljem sporočamo, da Flant širi svoj prispevek k odprtokodnim orodjem za Kubernetes z izdajo alfa različica gonilnika CSI (Vmesnik za shranjevanje vsebnikov) za Yandex.Cloud.

Toda preden preidemo na podrobnosti implementacije, odgovorimo na vprašanje, zakaj je to sploh potrebno, ko Yandex že ima storitev Upravljana storitev za Kubernetes.

Predstavitev

Zakaj je to?

V našem podjetju že od samega začetka uporabe Kubernetesa v produkciji (torej že nekaj let) razvijamo lastno orodje (deckhouse), ki ga, mimogrede, nameravamo kmalu dati na voljo tudi kot odprtokodni projekt. . Z njegovo pomočjo enotno konfiguriramo in konfiguriramo vse naše gruče, trenutno jih je že več kot 100, na najrazličnejših strojnih konfiguracijah in v vseh razpoložljivih oblačnih storitvah.

Grozdi, ki uporabljajo krovne hiše, imajo vse potrebne komponente za delovanje: balanserje, spremljanje s priročnimi grafikoni, metrike in opozorila, avtentikacijo uporabnikov prek zunanjih ponudnikov za dostop do vseh nadzornih plošč itd. V upravljano rešitev nima smisla nameščati tako "napolnjene" gruče, saj je to pogosto nemogoče ali pa bo povzročilo potrebo po onemogočitvi polovice komponent.

NB: To je naša izkušnja in je precej specifična. Nikakor ne predlagamo, da bi morali vsi sami namestiti gruče Kubernetes, namesto da uporabljajo že pripravljene rešitve. Mimogrede, nimamo resničnih izkušenj z upravljanjem Kubernetes iz Yandexa in v tem članku ne bomo podali nobene ocene te storitve.

Kaj je in za koga?

Tako smo že govorili o sodobnem pristopu k shranjevanju v Kubernetesu: kako deluje CSI? и kako je prišlo do skupnosti temu pristopu.

Trenutno je veliko velikih ponudnikov storitev v oblaku razvilo gonilnike za uporabo svojih diskov v oblaku kot trajnega nosilca v Kubernetesu. Če dobavitelj nima takega gonilnika, vendar so vse potrebne funkcije zagotovljene prek API-ja, vam nič ne preprečuje, da gonilnik implementirate sami. To se je zgodilo z Yandex.Cloud.

Vzeli smo kot osnovo za razvoj Gonilnik CSI za oblak DigitalOcean in nekaj idej od gonilniki za GCP, saj ima interakcija z API-jem teh oblakov (Google in Yandex) številne podobnosti. Zlasti API in GCPin ob Yandex vrniti predmet Operation za sledenje statusu dolgotrajnih operacij (na primer ustvarjanje novega diska). Za interakcijo z API-jem Yandex.Cloud uporabite Yandex.Cloud Go SDK.

Rezultat opravljenega dela objavljen na GitHubu in je lahko uporabno za tiste, ki iz nekega razloga uporabljajo lastno namestitev Kubernetes na virtualnih strojih Yandex.Cloud (vendar ne že pripravljene upravljane gruče) in bi radi uporabljali (naročali) diske prek CSI.

Реализация

Glavne lastnosti

Trenutno gonilnik podpira naslednje funkcije:

  • Urejanje diskov v vseh conah gruče glede na topologijo vozlišč v gruči;
  • Odstranjevanje predhodno naročenih plošč;
  • Spreminjanje velikosti brez povezave za diske (Yandex.Cloud ne podpirajo povečanje diskov, ki so nameščeni na virtualni stroj). Za informacije o tem, kako je bilo treba spremeniti gonilnik, da bi bilo spreminjanje velikosti čim bolj neboleče, glejte spodaj.

V prihodnje načrtujemo implementacijo podpore za ustvarjanje in brisanje posnetkov diska.

Glavna težava in kako jo premagati

Pomanjkanje zmožnosti povečanja diskov v realnem času v API-ju Yandex.Cloud je omejitev, ki otežuje operacijo spreminjanja velikosti za PV (Persistent Volume): v tem primeru je potrebno, da se aplikacijski pod, ki uporablja disk, ustavi, kar lahko povzroči nedelovanje aplikacij.

Glede na CSI specifikacije, če krmilnik CSI sporoči, da lahko spreminja velikost diskov samo »brez povezave« (VolumeExpansion.OFFLINE), potem bi moral postopek povečanja diska potekati takole:

Če ima vtičnik samo VolumeExpansion.OFFLINE razširitvena zmogljivost in obseg sta trenutno objavljena ali na voljo v vozlišču ControllerExpandVolume MORA biti poklican SAMO po:

  • Vtičnik ima krmilnik PUBLISH_UNPUBLISH_VOLUME zmogljivost in ControllerUnpublishVolume je bil uspešno priklican.

DRUGAČE

  • Vtičnik NIMA krmilnika PUBLISH_UNPUBLISH_VOLUME zmožnost, ima vtičnik vozlišče STAGE_UNSTAGE_VOLUME zmogljivost, in NodeUnstageVolume je bil uspešno zaključen.

DRUGAČE

  • Vtičnik NIMA krmilnika PUBLISH_UNPUBLISH_VOLUME zmogljivost, niti vozlišče STAGE_UNSTAGE_VOLUME zmogljivost, in NodeUnpublishVolume se je uspešno zaključil.

To v bistvu pomeni, da morate disk odklopiti od virtualnega stroja, preden ga razširite.

Vendar pa na žalost izvajanje Specifikacija CSI prek stranskih prikolic ne izpolnjuje teh zahtev:

  • V zabojniku bočne prikolice csi-attacher, ki bi moral biti odgovoren za prisotnost zahtevane vrzeli med nosilci, ta funkcionalnost preprosto ni implementirana pri spreminjanju velikosti brez povezave. O tem se je začela razprava tukaj.
  • Kaj točno je zabojnik z bočno prikolico v tem kontekstu? Sam vtičnik CSI ne sodeluje z API-jem Kubernetes, temveč se odziva le na klice gRPC, ki mu jih pošljejo vsebniki stranske prikolice. Zadnje se razvijajo s strani skupnosti Kubernetes.

V našem primeru (vtičnik CSI) je operacija povečanja diska videti takole:

  1. Prejmemo klic gRPC ControllerExpandVolume;
  2. Poskušamo povečati disk v API-ju, vendar prejmemo napako o nezmožnosti izvedbe operacije, ker je disk nameščen;
  3. Identifikator diska shranimo v mapo, ki vsebuje diske, za katere je treba izvesti operacijo povečanja. V nadaljevanju bomo zaradi kratkosti ta zemljevid imenovali kot volumeResizeRequired;
  4. Ročno odstranite pod, ki uporablja disk. Kubernetes ga bo znova zagnal. Tako da disk nima časa za namestitev (ControllerPublishVolume) preden zaključimo operacijo povečanja pri poskusu priklopa, preverimo, ali je dani disk še vedno v volumeResizeRequired in vrne napako;
  5. Gonilnik CSI poskuša znova izvesti operacijo spreminjanja velikosti. Če je bila operacija uspešna, odstranite disk iz volumeResizeRequired;
  6. Ker ID diska manjka volumeResizeRequired, ControllerPublishVolume poteka uspešno, disk je nameščen, pod se zažene.

Vse je videti dovolj preprosto, a kot vedno obstajajo pasti. Poveča diske zunanji-resizer, ki v primeru napake med delovanjem uporablja čakalno vrsto z eksponentnim povečanjem časovne omejitve do 1000 sekund:

func DefaultControllerRateLimiter() RateLimiter {
  return NewMaxOfRateLimiter(
  NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
  // 10 qps, 100 bucket size.  This is only for retry speed and its only the overall factor (not per item)
  &BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
  )
}

To lahko občasno povzroči, da se operacija razširitve diska podaljša za 15+ minut in tako ustrezna enota ni na voljo.

Edina možnost, ki nam je dokaj enostavno in neboleče omogočila, da zmanjšamo morebitne izpade, je bila uporaba naše različice zunanjega spreminjanja velikosti z najvišjo omejitvijo časovne omejitve v 5 sekundah:

workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)

Ni se nam zdelo potrebno nujno sprožiti razprave in zakrpati external-resizerja, ker je offline spreminjanje velikosti diskov vrnitev, ki bo kmalu izginila pri vseh ponudnikih oblakov.

Kako ga začeti uporabljati?

Gonilnik je podprt v različici Kubernetes 1.15 in novejših. Za delovanje voznika morajo biti izpolnjene naslednje zahteve:

  • Zastava --allow-privileged nastavite na vrednost true za strežnik API in kubelet;
  • Vključeno --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true za strežnik API in kubelet;
  • Razširjanje namestitve (mount razmnoževanje) mora biti omogočen v gruči. Ko uporabljate Docker, mora biti demon konfiguriran tako, da omogoča skupne namestitve.

Vsi potrebni koraki za samo namestitev opisano v README. Namestitev vključuje ustvarjanje predmetov v Kubernetesu iz manifestov.

Za delo voznika boste potrebovali naslednje:

  • Določite identifikator imenika v manifestu (folder-id) Yandex.Cloud (glej dokumentacijo);
  • Za interakcijo z API-jem Yandex.Cloud gonilnik CSI uporablja storitveni račun. V manifestu je treba podati Secret pooblaščeni ključi iz storitvenega računa. V dokumentaciji opisano, kako ustvariti servisni račun in pridobiti ključe.

Glede na vse - poskusi, veseli bomo povratnih informacij in nove številkeče naletite na težave!

Nadaljnja podpora

Kot rezultat bi radi omenili, da tega gonilnika CSI nismo implementirali zaradi velike želje po zabavi pri pisanju aplikacij v Go, temveč zaradi nujne potrebe v podjetju. Ne zdi se nam praktično, da bi vzdrževali lastno implementacijo, zato bomo, če bo Yandex pokazal zanimanje in se odločil, da bo gonilnik še naprej podpiral, z veseljem prenesli repozitorij k njim.

Poleg tega ima Yandex verjetno lastno implementacijo gonilnika CSI v svoji upravljani gruči Kubernetes, ki se lahko izda v odprtokodni različici. Tudi to možnost razvoja vidimo kot ugodno - skupnost bo lahko uporabljala preizkušen gonilnik ponudnika storitev in ne tretjega podjetja.

PS

Preberite tudi na našem blogu:

Vir: www.habr.com

Dodaj komentar