Naše skúsenosti s vývojom ovládača CSI v Kubernetes pre Yandex.Cloud
S potešením oznamujeme, že Flant vydaním rozširuje svoj príspevok k nástrojom Open Source pre Kubernetes alfa verzia ovládača CSI (Rozhranie kontajnerového úložiska) pre Yandex.Cloud.
Ale predtým, než prejdeme k detailom implementácie, odpovedzme si na otázku, prečo je to vôbec potrebné, keď Yandex už má službu Spravovaná služba pre Kubernetes.
Úvod
Prečo je toto?
V rámci našej spoločnosti od začiatku používania Kubernetes vo výrobe (t.j. už niekoľko rokov) vyvíjame vlastný nástroj (deckhouse), ktorý mimochodom plánujeme čoskoro sprístupniť aj ako Open Source projekt . S jeho pomocou jednotne konfigurujeme a konfigurujeme všetky naše klastre a momentálne ich je už viac ako 100, na širokej škále hardvérových konfigurácií a vo všetkých dostupných cloudových službách.
Klastre, ktoré využívajú palubovku, majú všetky komponenty potrebné na prevádzku: balancery, monitorovanie pomocou pohodlných grafov, metrík a upozornení, autentifikáciu používateľov prostredníctvom externých poskytovateľov pre prístup ku všetkým dashboardom atď. Nemá zmysel inštalovať takýto „napumpovaný“ klaster v riadenom riešení, pretože to je často buď nemožné, alebo to povedie k potrebe deaktivovať polovicu komponentov.
NB: Toto je naša skúsenosť a je dosť špecifická. V žiadnom prípade nenavrhujeme, aby si každý nasadil klastre Kubernetes sám, namiesto toho, aby používal hotové riešenia. Mimochodom, nemáme žiadne skutočné skúsenosti s prevádzkou Kubernetes od spoločnosti Yandex a v tomto článku nebudeme túto službu hodnotiť.
V súčasnosti mnohí veľkí poskytovatelia cloudových služieb vyvinuli ovládače na používanie svojich cloudových diskov ako trvalý zväzok v Kubernetes. Ak dodávateľ takýto ovládač nemá, ale všetky potrebné funkcie zabezpečuje cez API, tak vám nič nebráni implementovať ovládač sami. Toto sa stalo s Yandex.Cloud.
Brali sme ako základ pre rozvoj Ovládač CSI pre cloud DigitalOcean a pár nápadov od ovládače pre GCP, pretože interakcia s API týchto cloudov (Google a Yandex) má množstvo podobností. Najmä API a GCPa Yandex vrátiť predmet Operation na sledovanie stavu dlho prebiehajúcich operácií (napríklad vytvorenie nového disku). Ak chcete komunikovať s rozhraním Yandex.Cloud API, použite Yandex.Cloud Go SDK.
Výsledok vykonanej práce je k dispozícii na GitHub a môžu byť užitočné pre tých, ktorí z nejakého dôvodu používajú vlastnú inštaláciu Kubernetes na virtuálnych strojoch Yandex.Cloud (nie však hotový riadený klaster) a chceli by používať (objednať) disky cez CSI.
Реализация
Kľúčové vlastnosti
V súčasnosti ovládač podporuje nasledujúce funkcie:
Usporiadanie diskov vo všetkých zónach klastra podľa topológie uzlov v klastri;
Odstránenie predtým objednaných diskov;
Offline zmena veľkosti diskov (Yandex.Cloud nepodporujú zvýšenie diskov, ktoré sú pripojené k virtuálnemu stroju). Informácie o tom, ako bolo potrebné upraviť ovládač, aby bola zmena veľkosti čo najmenej bolestivá, nájdete nižšie.
V budúcnosti plánujeme implementovať podporu pre vytváranie a mazanie snímok disku.
Hlavná ťažkosť a ako ju prekonať
Neschopnosť zväčšiť disky v reálnom čase v rozhraní Yandex.Cloud API je obmedzenie, ktoré komplikuje operáciu zmeny veľkosti pre PV (Persistent Volume): v tomto prípade je potrebné, aby bola zastavená aplikačná podložka, ktorá používa disk, a to môže spôsobiť výpadky aplikácií.
Podľa Špecifikácie CSI, ak radič CSI hlási, že môže meniť veľkosť diskov iba „offline“ (VolumeExpansion.OFFLINE), potom by proces zväčšenia disku mal prebiehať takto:
Ak má plugin iba VolumeExpansion.OFFLINE možnosť rozšírenia a objem je v danom čase zverejnený alebo dostupný v uzle ControllerExpandVolume MUSÍ byť zavolané LEN po:
Plugin má ovládač PUBLISH_UNPUBLISH_VOLUME schopnosti a ControllerUnpublishVolume bol úspešne vyvolaný.
ALEBO INÝ
Plugin NEMÁ ovládač PUBLISH_UNPUBLISH_VOLUME plugin má uzol STAGE_UNSTAGE_VOLUME schopnosti a NodeUnstageVolume bolo úspešne dokončené.
ALEBO INÝ
Plugin NEMÁ ovládač PUBLISH_UNPUBLISH_VOLUME schopnosť, ani uzol STAGE_UNSTAGE_VOLUME schopnosti a NodeUnpublishVolume úspešne dokončil.
To v podstate znamená, že pred rozšírením musíte odpojiť disk od virtuálneho počítača.
Avšak, bohužiaľ uskutočnenie Špecifikácia CSI cez postranné vozíky nespĺňa tieto požiadavky:
V kontajneri postranného vozíka csi-attacher, ktorý by mal byť zodpovedný za prítomnosť požadovanej medzery medzi držiakmi, táto funkcia jednoducho nie je implementovaná v offline zmene veľkosti. Rozbehla sa o tom diskusia tu.
Čo presne je v tomto kontexte kontajner postranného vozíka? Samotný doplnok CSI neinteraguje s Kubernetes API, ale reaguje iba na volania gRPC, ktoré mu posielajú kontajnery sidecar. Najnovšie sa vyvíjajú od komunity Kubernetes.
V našom prípade (CSI plugin) operácia zväčšenia disku vyzerá takto:
Prijímame hovor gRPC ControllerExpandVolume;
Snažíme sa zväčšiť disk v API, ale dostaneme chybu o nemožnosti vykonania operácie, pretože disk je pripojený;
Identifikátor disku uložíme do mapy, ktorá obsahuje disky, pre ktoré je potrebné vykonať operáciu zvýšenia. Nižšie, pre stručnosť, budeme túto mapu nazývať ako volumeResizeRequired;
Manuálne vyberte modul, ktorý používa disk. Kubernetes ho reštartuje. Aby sa disk nestihol pripojiť (ControllerPublishVolume) pred dokončením operácie zvýšenia pri pokuse o pripojenie skontrolujeme, či je daný disk stále in volumeResizeRequired a vráti chybu;
Ovládač CSI sa pokúsi znova vykonať operáciu zmeny veľkosti. Ak bola operácia úspešná, vyberte disk z volumeResizeRequired;
Pretože Chýba ID disku volumeResizeRequired, ControllerPublishVolume úspešne prejde, disk je namontovaný, modul sa spustí.
Všetko vyzerá dosť jednoducho, ale ako vždy existujú úskalia. Zväčšuje disky externý-rezizer, ktorý v prípade chyby počas prevádzky používa rad s exponenciálnym predĺžením časového limitu až na 1000 sekúnd:
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 môže pravidelne viesť k predĺženiu operácie rozšírenia disku na viac ako 15 minút, a teda k nedostupnosti príslušného modulu.
Jedinou možnosťou, ktorá nám celkom ľahko a bezbolestne umožnila znížiť potenciálne prestoje, bolo použitie našej verzie externého resizeru s maximálnym časovým limitom za 5 sekúnd:
Nepovažovali sme za potrebné urgentne iniciovať diskusiu a záplatovať external-resizer, pretože offline zmena veľkosti diskov je návratom, ktorý čoskoro zmizne od všetkých cloudových poskytovateľov.
Ako začať používať?
Ovládač je podporovaný na Kubernetes verzie 1.15 a vyššej. Aby vodič mohol pracovať, musia byť splnené tieto požiadavky:
vlajka --allow-privileged nastaviť na hodnotu true pre server API a kubelet;
Zahrnuté --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true pre server API a kubelet;
Rozšírenie montáže (propagácia montáže) musí byť v klastri povolená. Keď používate Docker, démon musí byť nakonfigurovaný tak, aby umožňoval zdieľané pripojenia.
Všetky potrebné kroky pre samotnú inštaláciu popísané v README. Inštalácia zahŕňa vytváranie objektov v Kubernetes z manifestov.
Aby ovládač fungoval, budete potrebovať nasledovné:
Zadajte identifikátor adresára v manifeste (folder-id) Yandex.Cloud (pozri dokumentáciu);
Na interakciu s rozhraním Yandex.Cloud API používa ovládač CSI servisný účet. V manifeste musí byť odovzdané Tajné autorizované kľúče zo servisného účtu. V dokumentácii popísané, ako si vytvoriť servisný účet a získať kľúče.
Všetko vo všetkom - vyskúšať, a budeme radi, ak dostaneme spätnú väzbu a nové záležitostiak narazíte na nejaké problémy!
Ďalšia podpora
V dôsledku toho by sme chceli poznamenať, že sme tento ovládač CSI implementovali nie z veľkej túžby zabaviť sa písaním aplikácií v Go, ale z naliehavej potreby v rámci spoločnosti. Nezdá sa nám praktické udržiavať vlastnú implementáciu, takže ak Yandex prejaví záujem a rozhodne sa pokračovať v podpore ovládača, radi im prenesieme úložisko.
Okrem toho má Yandex pravdepodobne vlastnú implementáciu ovládača CSI vo svojom spravovanom klastri Kubernetes, ktorý môže byť vydaný v Open Source. Aj túto možnosť vývoja vnímame ako priaznivú – komunita bude môcť použiť osvedčený ovládač od poskytovateľa služieb, a nie od tretej strany.