
С радостью обявяваме, че компанията "Флант" увеличава своя принос в Open Source инструментите за Kubernetes, пускайки (Container Storage Interface) за Yandex Cloud.
Но преди да преминем към детайлите на реализацията, нека отговорим на въпроса защо всъщност е необходимо това, когато Yandex вече предлага услуга .
Въведение
Защо е това необходимо?
Вътре в нашата компания, още от самото начало на експлоатацията на Kubernetes в продукция (т.е. вече няколко години), се развива собствен инструмент (deckhouse), който, между другото, планираме скоро да направим достъпен като Open Source проект. С негова помощ ние унифицирано конфигурираме и настройваме всичките си клъстери, а в момента вече има над 100, и то на най-различни конфигурации на хардера и във всички налични облачни услуги.
Клъстерите, в които се използва deckhouse, съдържат всички необходими компоненти за работа: балансировчици, мониторинг с удобни графики, метрики и аларми, аутентификация на потребителите чрез външни доставчици за достъп до всички табла и така нататък. Такъв "прокачен" клъстер не е смислено да се поставя в managed решение, тъй като често това е или невъзможно, или ще доведе до необходимостта да се изключат половината компоненти.
NB: Това е нашият опит и той е доста специфичен. Ние по никакъв начин не твърдим, че на всеки му е необходимо самостоятелно да се занимава с разгръщането на клъстери Kubernetes, вместо да използва готови решения. Между другото, нямаме реален опит с експлоатацията на Kubernetes от страна на Yandex и няма да даваме никаква оценка на тази услуга в настоящата статия.
Какво е това и за кого е?
Така че, вече разказахме за съвременния подход към хранилищата в Kubernetes: и до този подход.
В момента много големи доставчици на облачни услуги разработват драйвери за използване на своите "облачни" дискове като Persistent Volume в Kubernetes. Ако обаче такъв драйвер не е наличен при доставчика, но всички необходими функции се предоставят чрез API, нищо не пречи да се реализира драйвер собственоръчно. Тъкмо така се получи и при нас с Yandex.Cloud.
За основа на разработването взехме и няколко идеи от , тъй като взаимодействието с API на тези облаци (Google и Yandex) има редица сходства. По-специално, API и на , и у върщат обект Операция за проследяване на статуса на дългосрочни операции (например, създаване на нов диск). За взаимодействие с API на Yandex.Cloud се използва .
Резултатът от извършената работа и може да бъде полезен на тези, които по някаква причина използват собствена инсталация на Kubernetes на виртуални машини в Yandex.Cloud (но не готов управляван клъстър) и биха искали да използват (поръчват) дискове чрез CSI.
Реализация
Основни възможности
Към момента драйверът поддържа следните функции:
- Поръчка на дискове във всички зони на клъстера според топологията на наличните възли в клъстера;
- Изтриване на по-рано поръчани дискове;
- Offline промяна на размера на дискове (Yandex.Cloud увеличаване на дискове, които са монтирани на виртуалната машина). За това как се наложи да се доработи драйверът, за да се извършва промяната на размера максимално безболезнено, вижте по-долу.
В бъдеще се предвижда реализиране на поддръжка за създаване и изтриване на моментни снимки на дискове.
Основна трудност и нейното преодоляване
Отсъствието на възможност в API на Yandex.Cloud за увеличаване на дискове в реално време — ограничение, което усложнява операцията по промяната на размера за PV (Persistent Volume): в такъв случай е необходимо pod приложението, което използва диска, да бъде спряно, а това може да доведе до временно прекратяване на приложението.
Според , ако 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 чрез sidecar не отговарят на тези изисквания:
- В sidecar контейнера
csi-attacher, който трябва да отговаря за присъствието на необходимия интервал между монтиранията, при офлайн промяна на размера просто не е реализирана тази функционалност. Обсъждането по този въпрос е иницирано . - Какво всъщност е sidecar контейнер в този контекст? Самият CSI плъгин не взаимодейства с Kubernetes API, а само реагира на gRPC повиквания, които му изпращат sidecar контейнерите. Последните в общността на Kubernetes.
В нашия случай (CSI плъгин) операцията за увеличаване на диска изглежда по следния начин:
- Получаваме gRPC повикване
ControllerExpandVolume; - Опитваме се да увеличим диска в API, но получаваме грешка за невъзможност за изпълнение на операцията, тъй като дискът е монтиран;
- Запазваме идентификатора на диска в map, съдържащ дисковете, за които е необходимо да се извърши операцията за увеличаване. По-кратко, ще наричаме този map
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 увеличаването на дискове е архаизъм, който скоро ще изчезне при всички облачни доставчици.
Как да започнете да използвате?
Драйверът се поддържа в Kubernetes версия 1.15 и по-нова. За работата на драйвера трябва да се изпълнят следните изисквания:
- FPIPE
--allow-privilegedустановен на стойностистинноза 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, а от остра необходимост в компанията. Не смятаме за уместно да поддържаме собствена реализация, затова ако Яндекс прояви интерес и реши да продължи подкрепата на драйвера, с удоволствие ще предадем репозитория на тях.
Освен това, вероятно има собствена реализация на CSI драйвера в управлявания кластер на Kubernetes на Яндекс, която може да бъде пусната с отворен код. Този вариант за развитие ни изглежда също благоприятен — общността ще може да ползва изпробван драйвер от доставчика на услуги, а не от трета страна.
P.S.
Прочетете също в нашия блог:
- «»;
- «»;
- «»;
- «».
Източник: habr.com
