etcd-operator присоединяется к Cozystack с новым API v1alpha2
Проект
etcd-operator, который разрабатывает оператор для развёртывания и обслуживания кластеров
etcd в Kubernetes, был передан проекту
Cozystack. Вместе с передачей была опубликована написанная с нуля реализация оператора под новой версией API — etcd-operator.cozystack.io/v1alpha2, которая заменяет прежнюю etcd.aenix.io/v1alpha1. Вместо управления членами через StatefulSet новая реализация напрямую использует нативный Membership API etcd (операции MemberAdd, MemberPromote и MemberRemove), что даёт оператору полный контроль над составом кластера. Новую реализацию написал
Timofei Larkin, один из сопровождающих прежней кодовой базы, которая сохранена в ветке
v1alpha1. Проект написан на Go и распространяется под лицензией Apache 2.0.
Проект был начат компанией Ænix, которая собрала инициативную группу из сообщества Kubernetes для его создания. После завершения базовой реализации была предпринята попытка передать проект в CNCF. Под влиянием этой инициативы проект etcd пришёл к выводу, что нужен официальный оператор, и сформировал собственную рабочую группу, которая, оценив существующие реализации, решила разрабатывать кодовую базу с нуля — так появился etcd-io/etcd-operator. По функциональности официальный оператор пока не догнал aenix etcd-operator, который уже используется в промышленной эксплуатации сообществом и такими проектами, как Cozystack и Kamaji, поэтому проект продолжил собственную независимую линию развития (сравнение с официальным оператором приведено в конце этой статьи).
Оператор управляет кластерами etcd через два ресурса: EtcdCluster описывает желаемое состояние кластера (количество реплик, версия etcd, параметры хранилища, TLS, аутентификация, тюнинг etcd), а EtcdMember создаётся самим оператором для каждого члена кластера и владеет его Pod и PVC. В отличие от типичных решений, оператор не использует StatefulSet — Pod и PVC каждого члена согласуются независимо, а изменения состава кластера проходят через Membership API etcd: новые члены присоединяются в роли learner (MemberAdd) и позже повышаются до голосующих членов (MemberPromote), удаление выполняется с корректным выходом из кворума (MemberRemove), а приостановка кластера сохраняет идентичность членов. Обоснование этой архитектуры описано в concepts.md.
Ключевые возможности
- первичная инициализация кластера и масштабирование в обе стороны по одному члену за раз: присоединение в режиме learner, корректное удаление с выходом из кворума;
- приостановка кластера без потери данных (
spec.replicas: 0) и его возобновление с теми же идентификаторами кластера и членов; - хранение данных в PVC (по умолчанию) или в tmpfs — для данных, которые можно восстановить; члены, работающие в памяти, автоматически пересоздаются при потере их Pod;
- независимая настройка TLS для клиентских и peer-соединений: используйте свои Secret или позвольте оператору выпускать и автоматически обновлять сертификаты через cert-manager;
- аутентификация с единственным пользователем root, учётные данные которого передаются через Secret;
- снимки (snapshot) в S3 или PVC через ресурс EtcdSnapshot и восстановление кластера из снимка при первичной инициализации;
- автоматически создаваемый PodDisruptionBudget, который не даёт операциям drain нарушить кворум;
- валидация spec на стороне apiserver (выражения CEL в CRD) без webhook и зависимости от cert-manager;
- субресурс
/scale, благодаря которому работаютkubectl scaleи VerticalPodAutoscaler, порт метрик 2381, пробросaffinityиtopologySpreadConstraints; - плагин kubectl-etcd для операций day-2, выполняемых после развёртывания кластера.
Что изменилось по сравнению с v1alpha1
По сравнению со старой реализацией etcd.aenix.io/v1alpha1 были внесены следующие изменения:
- группа API изменилась с
etcd.aenix.ioнаetcd-operator.cozystack.io; - вместо StatefulSet используются отдельные ресурсы EtcdMember для каждого члена;
- произвольная карта
spec.optionsзаменена типизированным набором параметров (quota-backend-bytes, режим авто-компакции и срок хранения,snapshot-count) — произвольная карта позволяла передавать флаги, конфликтовавшие с логикой оператора; - ресурс EtcdBackup переименован в EtcdSnapshot с сохранением его семантики;
- валидация перенесена с webhook на правила CEL в CRD;
- Service кластера переведён в headless-режим, который необходим для стабильных DNS-имён отдельных членов.
Миграция выполняется на месте с помощью инструмента etcd-migrate: работающий кластер старого оператора перенимается без переноса данных, перезапуска Pod и потери кворума — изменяются только владение объектами, метки и аннотации, после чего управление берёт на себя новый оператор. Клиенты, которые обращаются к кластеру по DNS-имени, продолжают работать без изменений. Процедура описана в migration.md.
Сравнение с официальным оператором
Реализация покрывает большинство пунктов дорожной карты официального etcd-operator, разрабатываемого проектом etcd. Статус по пунктам дорожной карты:
- Создание нового кластера etcd, например, из 3 или 5 членов заданной версии etcd — реализовано.
- Определение состояния кластера — реализовано.
- Включение TLS-соединений, включая обновление сертификатов — реализовано.
- Обновление в пределах патчей или на одну минорную версию — частично реализовано:
spec.versionприменяется только к вновь создаваемым членам. - Масштабирование вниз и вверх, например, 1 -> 3 -> 5 членов и обратно — реализовано.
- Поддержка настройки параметров etcd (через флаги или переменные окружения) — реализовано, в виде типизированного закрытого набора параметров.
- Восстановление одного отказавшего члена кластера (при сохранении кворума) — частично реализовано: члены с повреждённым PVC пока не заменяются автоматически.
- Восстановление после отказа нескольких членов кластера (потеря кворума) — не реализовано, работа запланирована.
- Создание резервной копии кластера по требованию — реализовано.
- Создание периодических резервных копий кластера — сознательно вне области охвата: регулярные снимки предполагается выполнять с помощью стандартного CronJob.
Помимо этой дорожной карты, v1alpha2 также предоставляет возможности, не перечисленные в официальном плане, продиктованные мультиарендным сценарием использования Cozystack и Kamaji:
- масштабирование до нуля (приостановка/возобновление) с сохранением идентичности кластера и членов;
- хранилище в памяти (tmpfs) с заменой членов силами оператора;
- валидация CEL на стороне apiserver — без webhook и без зависимости от сертификатов;
- автоматически создаваемый PodDisruptionBudget, ограниченный голосующими членами;
- субресурс
/scaleс заполненнымstatus.selector, благодаря чемуkubectl scaleиVerticalPodAutoscaler.targetRefработают напрямую; - проброс параметров планирования (
affinity,topologySpreadConstraints) и объединённыеadditionalMetadataдля всех принадлежащих объектов; - инструмент миграции на месте со старого оператора;
- плагин kubectl-etcd для операций day-2.