- PVSM.RU - https://www.pvsm.ru -

Рады объявить, что компания «Флант» пополняет свой вклад в Open Source-инструменты для Kubernetes, выпустив альфа-версию драйвера CSI [1] (Container Storage Interface) для Яндекс.Облака.
Но перед тем, как перейти к деталям реализации, ответим на вопрос, зачем это вообще нужно, когда у Яндекса уже есть услуга Managed Service for Kubernetes [2].
Внутри нашей компании, ещё с самого начала эксплуатации Kubernetes в production (т.е. уже несколько лет), развивается собственный инструмент (deckhouse), который, кстати, мы тоже планируем в скором времени сделать доступным как Open Source-проект. С его помощью мы единообразно конфигурируем и настраиваем все свои кластеры, а в настоящий момент их уже более 100, причём на самых различных конфигурациях железа и во всех доступных облачных сервисах.
Кластеры, в которых используется deckhouse, имеют в себе все необходимые для работы компоненты: балансировщики, мониторинг с удобными графиками, метриками и алертами, аутентификацию пользователей через внешних провайдеров для доступа ко всем dashboard’ам и так далее. Такой «прокачанный» кластер нет смысла ставить в managed-решение, так как зачастую это либо невозможно, либо приведёт к необходимости отключать половину компонентов.
NB: Это наш опыт, и он довольно специфичен. Мы ни в коем случае не утверждаем, что всем стоит самостоятельно заниматься разворачиванием кластеров Kubernetes вместо того, чтобы пользоваться готовыми решениями. К слову, реального опыта эксплуатации Kubernetes от Яндекса у нас нет и давать какую-либо оценку этому сервису в настоящей статье мы не будем.
Итак, мы уже рассказывали о современнем подходе к хранилищам в Kubernetes: как устроен CSI [3] и как сообщество пришло [4] к такому подходу.
В настоящее время многие крупные поставщики облачных услуг разработали драйверы для использования своих «облачных» дисков в качестве Persistent Volume в Kubernetes. Если же такого драйвера у поставщика нет, но при этом все необходимые функции предоставляются через API, то ничто не мешает реализовать драйвер собственными силами. Так и получилось у нас с Яндекс.Облаком.
За основу для разработки мы взяли CSI-драйвер для облака DigitalOcean [5] и пару идей из драйвера для GCP [6], так как взаимодействие с API этих облаков (Google и Яндекс) имеет ряд сходств. В частности, API и у GCP [7], и у Yandex [8] возвращают объект Operation для отслеживания статуса длительных операций (например, создания нового диска). Для взаимодействия с API Яндекс.Облака используется Yandex.Cloud Go SDK [9].
Результат проделанной работы опубликован на GitHub [1] и может пригодиться тем, кто по какой-то причине использует собственную инсталляцию Kubernetes на виртуальных машинах Яндекс.Облака (но не готовый managed-кластер) и хотел бы использовать (заказывать) диски через CSI.
На текущий момент драйвер поддерживает следующие функции:
В будущем планируется реализовать поддержку создания и удаления снапшотов дисков.
Отсутствие в API Яндекс.Облака возможности увеличивать диски в реальном времени — ограничение, которое усложняет операцию resize’а для PV (Persistent Volume): ведь в таком случае необходимо, чтобы pod приложения, который использует диск, был остановлен, а это может вызвать простой приложения.
Согласно спецификации CSI [11], если CSI-контроллер сообщает о том, что умеет делать resize дисков только «в offline» (VolumeExpansion.OFFLINE), то процесс увеличения диска должен проходить так:
If the plugin has only
VolumeExpansion.OFFLINEexpansion capability and volume is currently published or available on a node thenControllerExpandVolumeMUST be called ONLY after either:
- The plugin has controller
PUBLISH_UNPUBLISH_VOLUMEcapability andControllerUnpublishVolumehas been invoked successfully.OR ELSE
- The plugin does NOT have controller
PUBLISH_UNPUBLISH_VOLUMEcapability, the plugin has nodeSTAGE_UNSTAGE_VOLUMEcapability, andNodeUnstageVolumehas been completed successfully.OR ELSE
- The plugin does NOT have controller
PUBLISH_UNPUBLISH_VOLUMEcapability, nor nodeSTAGE_UNSTAGE_VOLUMEcapability, andNodeUnpublishVolumehas completed successfully.
По сути это означает необходимость отсоединить диск от виртуальной машины перед тем, как его увеличивать.
Однако, к сожалению, реализация спецификации CSI через sidecar’ы не соответствует этим требованиям:
csi-attacher, который и должен отвечать за наличие нужного промежутка между монтированиями, при offline-ресайзе попросту не реализован этот функционал. Дискуссию об этом инициировали здесь [12].В нашем случае (CSI-плагин) операция увеличения диска выглядит следующим образом:
ControllerExpandVolume;volumeResizeRequired;ControllerPublishVolume) до завершения операции увеличения при попытке монтирования, проверяем, что данный диск всё ещё находится в volumeResizeRequired и возвращаем ошибку;volumeResizeRequired;volumeResizeRequired, ControllerPublishVolume проходит успешно, диск монтируется, pod запускается.Всё выглядит достаточно просто, но как всегда есть подводные камни. Увеличением дисков занимается external-resizer [14], который в случае ошибки при выполнении операции использует очередь [15] с экспоненциальным увеличением времени таймаута до 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+ минут и, таким образом, недоступности соответствующего pod’а.
Единственным вариантом, который достаточно легко и безболезненно позволил нам уменьшить потенциальное время простоя, стало использование своей версии external-resizer с максимальным ограничением таймаута в 5 секунд [16]:
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;Все необходимые шаги по самой установке описаны в README [18]. Инсталляция представляет собой создание объектов в Kubernetes из манифестов.
Для работы драйвера вам понадобится следующее:
folder-id) Яндекс.Облака (см. документацию [19]);В общем — попробуйте [1], а мы будем рады обратной связи и новым issues [22], если столкнетесь с какими-то проблемами!
В качестве итога нам хотелось бы отметить, что этот CSI-драйвер мы реализовывали не от большого желания развлечься с написанием приложений на Go, а ввиду острой необходимости внутри компании. Поддерживать свою собственную реализацию нам не кажется целесообразным, поэтому, если Яндекс проявит интерес и решит продолжить поддержку драйвера, то мы с удовольствием передадим репозиторий в их распоряжение.
Кроме того, наверное, у Яндекса в managed-кластере Kubernetes есть собственная реализация CSI-драйвера, которую можно выпустить в Open Source. Такой вариант развития для нас также видится благоприятным — сообщество сможет пользоваться проверенным драйвером от поставщика услуг, а не от сторонней компании.
Читайте также в нашем блоге:
Автор: Андрей Климентьев
Источник [24]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/open-source/345097
Ссылки в тексте:
[1] альфа-версию драйвера CSI: https://github.com/flant/yandex-csi-driver
[2] Managed Service for Kubernetes: https://cloud.yandex.ru/docs/managed-kubernetes/
[3] как устроен CSI: https://habr.com/ru/company/flant/blog/424211/
[4] как сообщество пришло: https://habr.com/ru/company/flant/blog/465417/
[5] CSI-драйвер для облака DigitalOcean: https://github.com/digitalocean/csi-digitalocean
[6] драйвера для GCP: https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver
[7] GCP: https://cloud.google.com/compute/docs/api/how-tos/api-requests-responses#handling_api_responses
[8] Yandex: https://cloud.yandex.ru/docs/api-design-guide/concepts/about-async
[9] Yandex.Cloud Go SDK: https://github.com/yandex-cloud/go-sdk
[10] не поддерживает: https://cloud.yandex.ru/docs/compute/operations/disk-control/update#change-disk-size
[11] спецификации CSI: https://github.com/container-storage-interface/spec
[12] здесь: https://github.com/kubernetes-csi/external-attacher/issues/207
[13] разрабатываются: https://kubernetes-csi.github.io/docs/sidecar-containers.html
[14] external-resizer: https://kubernetes-csi.github.io/docs/external-resizer.html
[15] использует очередь: https://github.com/kubernetes-csi/external-resizer/blob/master/vendor/k8s.io/client-go/util/workqueue/default_rate_limiters.go#L41
[16] в 5 секунд: https://github.com/flant/external-resizer/blob/faster-workqueue/pkg/controller/controller.go#L81
[17] mount propagation: https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation
[18] описаны в README: https://github.com/flant/yandex-csi-driver#installing-driver
[19] см. документацию: https://cloud.yandex.ru/docs/resource-manager/operations/folder/get-id
[20] авторизованные ключи: https://cloud.yandex.com/docs/iam/concepts/authorization/key
[21] описано: https://cloud.yandex.ru/docs/iam/quickstart-sa
[22] новым issues: https://github.com/flant/yandex-csi-driver/issues
[23] Готовить Kubernetes-кластер просто и удобно? Анонсируем addon-operator: https://habr.com/ru/company/flant/blog/455543/
[24] Источник: https://habr.com/ru/post/486190/?utm_source=habrahabr&utm_medium=rss&utm_campaign=486190
Нажмите здесь для печати.