Не поймите меня неправильно, мы являемся убежденными сторонниками Kubernetes. Она является важной частью нашей архитектуры и обеспечивает огромную ценность при правильном использовании. Но Kubernetes изначально предназначалась для работы в качестве платформы оркестровки контейнеров для рабочих нагрузок без статических данных, а не для приложений с статическими данными.
За последние несколько лет сообщество Kubernetes проделало огромную работу по развитию проекта для поддержки stateful рабочих нагрузок, создав StatefulSets, который является ответом Kubernetes на рабочие нагрузки, ориентированные на хранение данных.
pluralsh / plural
Развертывание открытого ПО на kubernetes в рекордные сроки. 🚀
Самый быстрый способ создания отличной инфраструктуры
Plural дает вам возможность создавать и поддерживать облачно-нативную и готовую к производству инфраструктуру с открытым исходным кодом на Kubernetes.
Plural развернет приложения с открытым исходным кодом на Kubernetes в вашем облаке, используя такие общие стандарты, как Helm и Terraform.
Платформа Plural обеспечивает следующее:
- Управление зависимостями между модулями Terraform/Helm с развертыванием и обновлением с учетом зависимостей.
- Аутентифицированный реестр docker и прокси chartmuseum для каждого репозитория.
- Шифрование секретов с использованием AES-256 (чтобы вы могли хранить весь рабочий процесс в git).
Кроме того, Plural также обрабатывает:
- Выдачу сертификатов.
- Настройка службы DNS для регистрации полностью определенных доменов под onplural.sh, чтобы избавить пользователей от необходимости регистрации DNS.
- Быть провайдером OIDC, чтобы обеспечить безопасность входа «без касания» для всех приложений Plural.
Платформа plural получает все артефакты развертывания, необходимые для развертывания…
Наборы StatefulSets используются в самых разных областях — от баз данных, очередей и хранилищ объектов до старых дряхлых веб-приложений, которым по каким-либо причинам необходимо изменять локальную файловую систему. Они предоставляют разработчикам набор довольно мощных гарантий:
- Последовательная сетевая идентификация для каждой капсулы: Это позволяет вам легко настроить DNS-адрес для pod в вашем приложении. Это отлично подходит для строк подключения к базе данных или настройки сложных клиентов Kafka. Иногда мы также используем его для настройки mesh-сети erlang.
- Автоматизация постоянных томов: Всякий раз, когда pod перезапускается, даже если он перепланирован на другой узел, постоянный том снова подключается к узлу, на котором он был размещен. Это несколько ограничено возможностями используемого вами интерфейса CSI (Container Storage Interface). Например, в AWS это работает только в пределах одной региональной AZ, поскольку тома EBS привязаны к AZ.
- Последовательные скользящие обновления: Обновления StatefulSet разработаны так, чтобы быть скользящими и последовательными. Он всегда будет обновляться в одном и том же порядке, что может помочь сохранить системы с тонкими протоколами координации.
Эти гарантии покрывают множество операций, необходимых для выполнения рабочих нагрузок с состоянием. В частности, он почти полностью решает проблему доступности. Учитывая, что гарантии работоспособности и избыточности EBS чрезвычайно сильны, автоматизация изменения расписания StatefulSet почти тривиально гарантирует вам высокую доступность сервиса. Однако здесь есть некоторые оговорки (например, наличие места в кластере и отсутствие ошибок при настройке AZ).
Kubernetes имеет много перспектив в этой области и теоретически может превратиться в платформу, позволяющую легко запускать рабочие нагрузки с состоянием наряду с рабочими нагрузками без состояния, для которых большинство разработчиков ее используют.
Чего не хватает в Kubernetes StatefulSet?
Итак, почему мы считаем, что StatefulSet не работает? Если вы мысленно представите себе операционные потребности рабочей нагрузки с состоянием, вы заметите, что один ключевой компонент отсутствует:
Что вы делаете, когда вам нужно изменить размер базового диска?
Набор данных — это обычное хранилище базы данных, которое обычно растет с довольно постоянной положительной скоростью. Если вы не поддерживаете горизонтальное масштабирование и разбиение на разделы, вам придется увеличивать пространство на диске по мере роста набора данных. Именно здесь Kubernetes не справляется со своей задачей.
В настоящее время контроллер StatefulSet не имеет встроенной поддержки изменения размера тома. И это несмотря на то, что почти все реализации CSI имеют встроенную поддержку изменения размера тома, к которой контроллер может подключиться. Существует обходной путь, но он почти до смешного обходной:
- Удалите StatefulSet во время осиротевших стручков, чтобы избежать простоя: kubectl delete sts —cascade=orphan.
- Вручную отредактируйте постоянный том для каждой капсулы в соответствии с новым размером хранилища
- Вручную отредактируйте утверждение тома StatefulSet с новым размером хранилища и добавьте фиктивную аннотацию pod для принудительного скользящего обновления.
- Пересоздайте StatefulSet с новой спецификацией, что позволит контроллеру вернуть контроль над осиротевшими стручками и начать скользящее обновление, которое запустит CSI для применения изменения размера тома.
Мы фактически автоматизировали весь этот процесс как часть оператора Plural. Мы знали, что нам нужно будет создать автоматизацию изменения размера хранилища для того, чтобы приложения с состоянием, работающие с Plural, могли работать под управлением специалистов, не являющихся экспертами Kubernetes. В действительности это нетривиальный объем логики, и если бы кого-то попросили сделать это в сценарии высокого давления, шансы на неудачу были бы невероятно высоки.
Итак, в Kubernetes StatefulSets есть довольно примечательный недостаток, но есть обходной путь, даже если он несколько нестандартный.
Это не должно быть слишком плохо, верно?
Но все становится еще хуже!
Ситуация становится прямо-таки болезненной, когда вы осознаете влияние этого ограничения и то, что многие операторы Kubernetes были созданы для управления рабочими нагрузками с состоянием.
Хорошим примером является оператор Prometheus, который является отличным проектом как для инициализации баз данных Prometheus, так и для создания рабочего процесса на основе CRD для настройки метрик, скреперов и оповещений.
Проблема возникает потому, что встроенный контроллер для оператора не имеет логики для управления изменением размера StatefulSet, но у него есть логика для воссоздания своего базового StatefulSet, если он видит событие, которое вызвало его удаление. Это означает, что у вас фактически нет возможности использовать описанное выше обходное решение, поскольку в тот момент, когда вы выполняете каскадное удаление orphan, оператор воссоздаст StatefulSet по старому образцу и не позволит правильно изменить размер. Единственное решение — удалить весь CRD или найти твик, который может обмануть оператора, чтобы он не согласовывал объект (иногда для этого используется масштабирование до нуля).
Как бы то ни было, в результате этого недостатка фактически не существует способа изменить размер экземпляра Prometheus с помощью оператора без значительного простоя или потери данных. Учитывая, насколько надежна автоматизация в StatefulSets во всех остальных случаях, довольно шокирует, что это все еще потенциальный способ отказа.
Наш руководитель сообщества, Абхи, действительно столкнулся с этой проблемой взаимодействия между операторами и изменением размера тома StatefulSet при реализации ее в операторе Vitess с открытым исходным кодом.
«Учитывая естественную сложность развертывания Vitess, можно сделать вывод, что изменение размера диска является пропорционально сложным. Vitess — это система разделения баз данных, которая находится поверх MySQL, а это значит, что изменение размера тома должно было быть как с учетом разделов, так и с учетом шардов. Нам пришлось вручную написать собственные безопасные для шарда перезагрузки, создать каскадное условие, которое работало бы со структурой «родитель-ребенок» пользовательских ресурсов Vitess, и решить все возможные проблемы, чтобы предотвратить простои. Выражаем благодарность известному разработчику Kubernetes enisoc за разработку этой функции».
Другие широко используемые и известные операторы баз данных, такие как оператор Postgres от Zalando, фактически повторно реализуют ту же процедуру, которую мы реализовали в операторе Plural, в своей собственной кодовой базе. Это приводит к тонне потраченных впустую циклов разработчиков на решение проблемы, которую нужно устранить только один раз.
Потенциал Kubernetes
В целом, мы очень высоко оцениваем потенциал Kubernetes, который позволит сделать практически любую рабочую нагрузку практически тривиальной, и огромная часть нашей миссии в Plural заключается в том, чтобы сделать это возможным.
При этом нам также необходимо четко осознавать пробелы, которые все еще остаются в экосистеме Kubernetes, чтобы мы могли либо обойти их, либо устранить в процессе развития. Я думаю, совершенно ясно, что это существенный пробел, и если расставить приоритеты, его можно будет легко устранить в одном из будущих выпусков Kubernetes.
Если вам показалось это интересным, посмотрите, что мы делаем с Kubernetes здесь. Спасибо за чтение!