
С радостией съобщаваме, че компанията «Флант» допринася за Open Source инструментите за Kubernetes с пускането на (Container Storage Interface) за Yandex.Cloud.
Но преди да преминем към подробностите на реализацията, нека отговорим на въпроса защо това е нужно, когато Яндекс вече предлага услуга .
Въведение
Защо е нужно?
В нашата компания, още от самото начало на експлоатацията на Kubernetes в продукция (т.е. вече няколко години), се развива собствен инструмент (deckhouse), който, между другото, в близко бъдеще също планираме да направим достъпен като Open Source проект. С него конфигурираме и настройваме единообразно всички свои клъстери, а в момента те вече са над 100, и то на най-различни хардуерни конфигурации и във всички налични облачни услуги.
Клъстерите, в които се използва deckhouse, разполагат с всички необходими компоненти за работа: балансьори, мониторинг с удобни графики, метрики и аларми, автентикация на потребители чрез външни доставчици за достъп до всички дашбордове и така нататък. Такъв „усилен“ клъстер няма смисъл да се поставя в managed решение, тъй като често това е невъзможно или ще наложи деактивирането на половината компоненти.
NB: Това е нашият опит и той е доста специфичен. Ние по никакъв начин не твърдим, че всеки трябва самостоятелно да се занимава с разгръщането на клъстери Kubernetes вместо да ползва готови решения. Между другото, нямаме реален опит с експлоатация на Kubernetes от Яндекс и няма да даваме оценка на тази услуга в настоящата статия.
Какво е това и за кого?
И така, вече говорихме за съвременния подход към хранилищата в Kubernetes: и до такъв подход.
В момента много големи доставчици на облачни услуги са разработили драйвери за използване на своите „облачни“ дискове като Persistent Volume в Kubernetes. Ако обаче такава драйвер не съществува при доставчика, но всички необходими функции се предоставят чрез API, нищо не пречи на реализирането на драйвер със собствени усилия. Именно така се случи и с Яндекс.Облака.
За основа на разработката взехме и няколко идеи от , тъй като взаимодействието с API на тези облаци (Google и Яндекс) има редица прилики. По-конкретно, API-то и при , и при връща обект Операция за проследяване на статуса на дълготрайни операции (например, създаване на нов диск). За взаимодействие с API на Yandex.Cloud се използва .
Резултат от извършената работа и може да е полезен за тези, които по някаква причина използват собствена инсталация на Kubernetes на виртуални машини в Yandex.Cloud (но не готов управляем клъстер) и искат да използват (поръчат) дискове през CSI.
Реализация
Основни възможности
В момента драйверът поддържа следните функции:
- Поръчка на дискове във всички зони на клъстера в съответствие с топологията на наличните в клъстера възли;
- Изтриване на вече поръчани дискове;
- Offline увеличаване на дискове (Yandex.Cloud увеличаване на дискове, които са монтирани на виртуална машина). Как точно се преработи драйверът, за да се извърши увеличаването по възможно най-безболезнен начин, вижте по-долу.
В бъдеще е планирано да се реализира поддръжка за създаване и изтриване на моментни снимки на дискове.
Основната трудност и нейното преодоляване
Липсата на възможност в API на Yandex.Cloud за увеличаване на дискове в реално време — ограничение, което усложнява операцията на увеличаване за PV (Persistent Volume): при такава ситуация е необходимо pod приложението, което използва диска, да бъде спряно, а това може да доведе до престой на приложението.
Според , ако CSI-контролерът съобщава, че може да изпълнява увеличаване на дискове само „в offline“ (VolumeExpansion.OFFLINE), то процесът на увеличаване на диска трябва да протича така:
Ако плъгинът има само
VolumeExpansion.OFFLINEвъзможност за увеличаване и обемът в момента е публикуван или наличен на възел, тоControllerExpandVolumeТРЯБВА да бъде извикан САМО след:
- Плъгинът има контролер
PUBLISH_UNPUBLISH_VOLUMEвъзможност иControllerUnpublishVolumeе бил успешно извикан.ИЛИ
- Ако плъгинът НЯМА контролер
PUBLISH_UNPUBLISH_VOLUMEвъзможност, плъгинът има възелSTAGE_UNSTAGE_VOLUMEвъзможност иNodeUnstageVolumeе бил успешно завършен.ИЛИ
- Ако плъгинът НЯМА контролер
PUBLISH_UNPUBLISH_VOLUMEвъзможност, нито възелSTAGE_UNSTAGE_VOLUMEвъзможност иNodeUnpublishVolumeе бил успешно завършен.
По същество това означава, че трябва да се отдели дискът от виртуалната машина, преди да може да бъде увеличен.
Въпреки това, за съжаление, реализация спецификациите на CSI чрез sidecar не отговарят на тези изисквания:
- В sidecar контейнера
csi-attacher, който трябва да отговаря за необходимото време между монтиранията, при offline-резайз просто не е реализиран този функционал. Дискусията по този въпрос беше иницирана . - Какво всъщност е sidecar контейнер в този контекст? Самият CSI плъгин не взаимодействат с Kubernetes API, а просто отговаря на gRPC повиквания, изпратени от sidecar контейнери. Последните общността на Kubernetes.
В нашия случай (CSI плъгин) операцията за увеличаване на диска изглежда по следния начин:
- Получаваме gRPC повикване
ControllerExpandVolume; - Опитваме се да увеличим диска в API, но получаваме грешка за невъзможност за изпълнение на операцията, тъй като диска е монтиран;
- Записваме идентификатора на диска в карта, съдържаща дискове, за които е необходимо да се извърши операцията за увеличаване. По-късно за краткост ще наричаме тази карта
volumeResizeRequired; - Ръчно изтриваме pod, който използва диска. Kubernetes ще го рестартира. За да предотвратим диска да бъде монтиран (
ControllerPublishVolume) преди приключване на операцията по увеличаване при опит за монтиране, проверяваме дали този диск все още е вvolumeResizeRequiredи връщаме грешка; - CSI драйвера се опитва да повтори операцията по resize. Ако операцията е успешна, изтриваме диска от
volumeResizeRequired; - Тъй като идентификаторът на диска отсъства в
volumeResizeRequired,ControllerPublishVolumeпреминава успешно, дискът се монтира, pod-ът се стартира.
Всё изглежда доста просто, но както винаги има подводни камъни. Увеличаването на дисковете отговаря на , който в случай на грешка при изпълнението на операцията с експоненциално увеличаване на времето за изчакване до 1000 секунди:
func DefaultControllerRateLimiter() RateLimiter {
return NewMaxOfRateLimiter(
NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
// 10 qps, 100 bucket size. Това е само за скорост на повторение и е само общ фактор (не на елемент)
&BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
)
}Това може периодично да доведе до това, че операцията по увеличаване на диска се проточва над 15+ минути и по този начин става недостъпен съответния pod.
Единственият вариант, който достатъчно лесно и безболезнено ни позволи да намалим потенциалното време на простои, беше използването на наша версия на external-resizer с максимално ограничение на времето за изчакване :
workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)Не преценихме за необходимо да инициираме спешна дискусия и да патчим external-resizer, защото offline resize на дисковете — е атисъм, който скоро ще изчезне при всички облачни доставчици.
Как да започнем да използваме?
Драйверът се поддържа в Kubernetes версия 1.15 и по-нови. За работата на драйвера трябва да се изпълняват следните изисквания:
- Знаме
--allow-privilegedустановен на стойностtrueза API-сървъра и kubelet; - Активирани
--feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=trueза API-сървъра и kubelet; - Разпространение на монтирането () трябва да бъде включено в кластера. При използване на Docker, демонът трябва да бъде конфигуриран така, че да са разрешени споделени обекти за монтиране (shared mounts).
Всички необходими стъпки за самата инсталация . Инсталацията представлява създаване на обекти в Kubernetes от манифести.
За да работи драйвера, ви е необходимо следното:
- Да посочите в манифеста идентификатора на директорията (
folder-id) на Яндекс.Облака (); - За взаимодействие с API на Яндекс.Облака в CSI-драйвера се използва сервисен акаунт. В манифеста Secret трябва да предадете от сервисния акаунт. В документацията , как да създадете сервисен акаунт и да получите ключовете.
Общо взето — , а ние ще се радваме на обратна връзка и , ако се сблъскате с някакви трудности!
Допълнителна поддръжка
В заключение, бихме искали да подчертаем, че този CSI-драйвер не е създаден от голямо желание за забавление с разработката на приложения на Go, а поради остра необходимост вътре в компанията. Няма да смятаме, че поддържането на собствена реализация е целесъобразно, така че, ако Яндекс прояви интерес и реши да продължи поддръжката на драйвера, с удоволствие предадем репозитория на тях.
Освен това, сигурно Яндекс в управляваните клъстери Kubernetes има собствена реализация на CSI-драйвера, която може да бъде пусната като Open Source. Тази възможност изглежда благоприятна за нас — общността ще може да се възползва от тестван драйвер от доставчика на услуги, а не от трета страна.
P.S.
Прочетете също в нашия блог:
- «»;
- «»;
- «»;
- «».
Източник: habr.com
