Нашето искуство во развивање на двигател CSI во Кубернетес за Yandex.Cloud

Нашето искуство во развивање на двигател CSI во Кубернетес за Yandex.Cloud

Задоволство ни е да објавиме дека Flant го проширува својот придонес во алатките со отворен код за Kubernetes со објавување алфа верзија на двигателот CSI (Интерфејс за складирање на контејнер) за Yandex.Cloud.

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

Вовед

Зошто е ова?

Во рамките на нашата компанија, од самиот почеток на користење на Kubernetes во производството (т.е. веќе неколку години) развиваме сопствена алатка (deckhouse), која, патем, планираме наскоро да ја ставиме достапна и како проект со отворен код. . Со негова помош, ние рамномерно ги конфигурираме и конфигурираме сите наши кластери, а моментално веќе ги има повеќе од 100, на широк спектар на хардверски конфигурации и во сите достапни облак услуги.

Кластерите што користат палуба ги имаат сите компоненти неопходни за работа: балансери, следење со пригодни графикони, метрика и предупредувања, автентикација на корисникот преку надворешни провајдери за пристап до сите контролни табли итн. Нема смисла да се инсталира таков „напумпан“ кластер во управувано решение, бидејќи тоа често е или невозможно или ќе доведе до потреба да се оневозможи половина од компонентите.

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

Што е тоа и за кого?

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

Во моментов, многу големи даватели на облак услуги имаат развиено двигатели за користење на нивните облак дискови како постојан волумен во Kubernetes. Ако добавувачот нема таков драјвер, но сите потребни функции се обезбедени преку API, тогаш ништо не ве спречува сами да го имплементирате драјверот. Ова е она што се случи со Yandex.Cloud.

Зедовме како основа за развој CSI двигател за облак DigitalOcean и неколку идеи од двигатели за GCP, бидејќи интеракцијата со API на овие облаци (Google и Yandex) има голем број сличности. Особено, API и GCP, и во Yandex врати предмет Operation за следење на статусот на долготрајните операции (на пример, создавање нов диск). За да комуницирате со Yandex.Cloud API, користете Yandex.Cloud Go SDK.

Резултатот од сработеното објавено на GitHub и може да биде корисно за оние кои поради некоја причина користат сопствена инсталација на Kubernetes на виртуелните машини Yandex.Cloud (но не и готов управуван кластер) и би сакале да користат (нарачуваат) дискови преку CSI.

Реализация

Клучни карактеристики

Во моментов, возачот ги поддржува следните функции:

  • Подредување дискови во сите зони на кластерот според топологијата на јазлите во кластерот;
  • Отстранување на претходно нарачани дискови;
  • Офлајн промена на големината на дисковите (Yandex.Cloud не поддржуваат зголемување на дисковите што се монтирани на виртуелната машина). За информации за тоа како возачот мораше да се измени за да се направи промената на големината што е можно побезболна, видете подолу.

Во иднина, планираме да имплементираме поддршка за креирање и бришење снимки од дискот.

Главната тешкотија и како да се надмине

Недостатокот на можност за зголемување на дисковите во реално време во Yandex.Cloud API е ограничување што ја комплицира операцијата за промена на големината за PV (Постојана јачина): во овој случај, неопходно е подлогата за апликација што го користи дискот да биде запрена, а тоа може да предизвика прекини на апликациите.

Според CSI спецификации, ако контролерот CSI пријави дека може да ја промени големината на дисковите само „офлајн“ (VolumeExpansion.OFFLINE), тогаш процесот на зголемување на дискот треба да оди вака:

Ако приклучокот има само VolumeExpansion.OFFLINE способноста и обемот за проширување моментално се објавени или достапни на јазол тогаш ControllerExpandVolume МОРА да се повика САМО после едно:

  • Приклучокот има контролер PUBLISH_UNPUBLISH_VOLUME способност и ControllerUnpublishVolume е успешно повикан.

ИЛИ ДРУГО

  • Приклучокот НЕМА контролер PUBLISH_UNPUBLISH_VOLUME способност, приклучокот има јазол STAGE_UNSTAGE_VOLUME способност, и NodeUnstageVolume е успешно завршена.

ИЛИ ДРУГО

  • Приклучокот НЕМА контролер PUBLISH_UNPUBLISH_VOLUME способност, ниту јазол STAGE_UNSTAGE_VOLUME способност, и NodeUnpublishVolume заврши успешно.

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

Сепак, за жал имплементација Спецификацијата CSI преку страничните колички не ги исполнува овие барања:

  • Во контејнер за странична кола csi-attacher, кој треба да биде одговорен за присуството на потребниот јаз помеѓу монтирањата, оваа функционалност едноставно не е имплементирана во офлајн промена на големината. За ова беше иницирана дискусија тука.
  • Што точно е контејнер за странична кола во овој контекст? Самиот приклучок CSI не е во интеракција со Kubernetes API, туку само одговара на повиците на gRPC испратени до него преку контејнерите на страничната кола. Најнови се развиваат од заедницата Кубернет.

Во нашиот случај (приклучок CSI), операцијата за зголемување на дискот изгледа вака:

  1. Добиваме повик gRPC ControllerExpandVolume;
  2. Се обидуваме да го зголемиме дискот во API, но добиваме грешка за неможноста да се изврши операцијата бидејќи дискот е монтиран;
  3. Идентификаторот на дискот го складираме во мапа, која ги содржи дисковите за кои треба да се изврши операцијата за зголемување. Подолу, за кратко, оваа карта ќе ја наречеме како volumeResizeRequired;
  4. Рачно отстранете го подлогата што го користи дискот. Kubernetes ќе го рестартира. Така што дискот нема време да се монтира (ControllerPublishVolume) пред да ја завршиме операцијата за зголемување при обид за монтирање, проверуваме дали дадениот диск е сè уште внатре volumeResizeRequired и врати грешка;
  5. Возачот на CSI се обидува повторно да ја изврши операцијата за промена на големината. Ако операцијата беше успешна, тогаш отстранете го дискот од volumeResizeRequired;
  6. Бидејќи Недостасува ID на дискот volumeResizeRequired, ControllerPublishVolume поминува успешно, дискот е монтиран, подлогата започнува.

Сè изгледа доволно едноставно, но како и секогаш има стапици. Ги зголемува дисковите надворешен менувач на големината, што во случај на грешка при операцијата користи редица со експоненцијално зголемување на времето на истекување до 1000 секунди:

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)},
  )
}

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

Единствената опција која многу лесно и безболно ни овозможи да го намалиме потенцијалниот застој беше употребата на нашата верзија на надворешна промена на големината со максимален временски рок. за 5 секунди:

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

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

Како да започнете со користење?

Возачот е поддржан на Kubernetes верзија 1.15 и повисока. За да работи возачот, мора да се исполнат следниве барања:

  • Знаме --allow-privileged поставена на вредност true за API сервер и kubelet;
  • Вклучено --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true за API сервер и kubelet;
  • Монтирај размножување (монтирање размножување) мора да биде овозможено на кластерот. Кога користите Docker, демонот мора да биде конфигуриран да дозволува споделени монтирања.

Сите потребни чекори за самата инсталација опишано во README. Инсталирањето вклучува создавање објекти во Kubernetes од манифестации.

За возачот да работи, ќе ви треба следново:

  • Наведете го идентификаторот на директориумот во манифестот (folder-id) Yandex.Cloud (види документација);
  • За да комуницирате со Yandex.Cloud API, двигателот CSI користи сметка за услуга. Во манифестот, Тајната мора да се пренесе овластени клучеви од сметката на услугата. Во документацијата опишано, како да креирате сметка за услуга и да добиете клучеви.

Се на се - обидете се, и ќе ни биде драго да добиеме повратни информации и нови прашањаако наидете на некакви проблеми!

Понатамошна поддршка

Како резултат на тоа, би сакале да забележиме дека го имплементиравме овој двигател на CSI не од голема желба да се забавуваме со пишување апликации во Go, туку поради итна потреба во рамките на компанијата. Не ни изгледа практично да ја одржуваме сопствената имплементација, па ако Yandex покаже интерес и одлучи да продолжи да го поддржува возачот, со задоволство ќе им го пренесеме складиштето.

Покрај тоа, Yandex веројатно има своја имплементација на двигателот CSI во управуваниот кластер Kubernetes, кој може да биде објавен во отворен код. Оваа развојна опција ја гледаме и како поволна - заедницата ќе може да користи докажан двигател од давател на услуги, а не од трета компанија.

PS

Прочитајте и на нашиот блог:

Извор: www.habr.com

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