Нашият опит в разработването на CSI драйвер в Kubernetes за Yandex.Cloud

Нашият опит в разработването на CSI драйвер в Kubernetes за Yandex.Cloud

Имаме удоволствието да съобщим, че Flant разширява своя принос към инструментите с отворен код за Kubernetes, като пуска алфа версия на CSI драйвера (Интерфейс за съхранение на контейнери) за Yandex.Cloud.

Но преди да преминем към подробностите за изпълнението, нека отговорим на въпроса защо изобщо е необходимо това, когато Yandex вече има услуга Управлявана услуга за Kubernetes.

въведение

Защо е това?

В рамките на нашата компания, от самото начало на използването на Kubernetes в производството (т.е. от няколко години насам), ние разработваме собствен инструмент (палубна рубка), който, между другото, също планираме скоро да предоставим като проект с отворен код . С негова помощ ние равномерно конфигурираме и конфигурираме всички наши клъстери, като в момента вече има повече от 100 от тях, на голямо разнообразие от хардуерни конфигурации и във всички налични облачни услуги.

Клъстерите, които използват палубна рубка, имат всички компоненти, необходими за работа: балансьори, мониторинг с удобни диаграми, показатели и предупреждения, удостоверяване на потребителя чрез външни доставчици за достъп до всички табла за управление и т.н. Няма смисъл да се инсталира такъв „напомпан“ клъстер в управлявано решение, тъй като това често е невъзможно или ще доведе до необходимостта от деактивиране на половината от компонентите.

NB: Това е нашият опит и той е доста специфичен. Ние по никакъв начин не предполагаме, че всеки трябва да разположи Kubernetes клъстери сам, вместо да използва готови решения. Между другото, нямаме реален опит в работата с Kubernetes от Yandex и няма да даваме оценка на тази услуга в тази статия.

Какво е и за кого?

И така, вече говорихме за модерния подход към съхранението в Kubernetes: как работи CSI? и как дойде общността към този подход.

В момента много големи доставчици на облачни услуги са разработили драйвери за използване на своите облачни дискове като постоянен том в Kubernetes. Ако доставчикът няма такъв драйвер, но всички необходими функции се предоставят чрез API, тогава нищо не ви пречи да внедрите драйвера сами. Това се случи с Yandex.Cloud.

Взехме като основа за развитие CSI драйвер за облак DigitalOcean и няколко идеи от драйвери за GCP, тъй като взаимодействието с API на тези облаци (Google и Yandex) има редица прилики. По-специално, API и GCP, и Yandex върнете обект Operation за проследяване на състоянието на продължителни операции (например създаване на нов диск). За да взаимодействате с API на Yandex.Cloud, използвайте Yandex.Cloud Go SDK.

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

Изпълнение

Основни характеристики

В момента драйверът поддържа следните функции:

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

В бъдеще планираме да внедрим поддръжка за създаване и изтриване на моментни снимки на дискове.

Основната трудност и как да я преодолеем

Липсата на възможност за увеличаване на дисковете в реално време в API на Yandex.Cloud е ограничение, което усложнява операцията за преоразмеряване за PV (Persistent Volume): в този случай е необходимо подът на приложението, който използва диска, да бъде спрян, и това може да доведе до прекъсване на приложенията.

Според 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 плъгин не взаимодейства с API на Kubernetes, а отговаря само на gRPC извиквания, изпратени до него от странични контейнери. Последен се разработват от общността Kubernetes.

В нашия случай (CSI плъгин) операцията по увеличаване на диска изглежда така:

  1. Получаваме gRPC обаждане ControllerExpandVolume;
  2. Опитваме се да увеличим диска в API, но получаваме грешка за невъзможността за извършване на операцията, тъй като дискът е монтиран;
  3. Ние съхраняваме идентификатора на диска в map, който съдържа дисковете, за които трябва да се извърши операцията за увеличаване. По-долу за краткост ще наричаме тази карта като 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+ минути и по този начин съответният модул да бъде недостъпен.

Единствената опция, която доста лесно и безболезнено ни позволи да намалим потенциалния престой, беше използването на нашата версия на external-resizer с максимално ограничение за изчакване за 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 (вижте документацията);
  • За да взаимодейства с API на Yandex.Cloud, CSI драйверът използва акаунт за услуга. В манифеста трябва да се предаде Secret оторизирани ключове от сервизния акаунт. В документацията описано, как да създадете сервизен акаунт и да получите ключове.

Всичко на всичко - Опитвам, и ще се радваме да получим обратна връзка и нови проблемиако срещнете проблеми!

Допълнителна поддръжка

В резултат на това бихме искали да отбележим, че внедрихме този CSI драйвер не от голямо желание да се забавляваме с писането на приложения в Go, а поради спешна нужда в компанията. Не ни се струва практично да поддържаме нашата собствена реализация, така че ако Yandex прояви интерес и реши да продължи да поддържа драйвера, ще се радваме да прехвърлим хранилището към тях.

В допълнение, Yandex вероятно има своя собствена реализация на CSI драйвера в своя управляван Kubernetes клъстер, който може да бъде пуснат в отворен код. Ние също виждаме тази опция за развитие като благоприятна - общността ще може да използва доказан драйвер от доставчик на услуги, а не от трета компания.

PS

Прочетете също в нашия блог:

Източник: www.habr.com

Добавяне на нов коментар