На примере оператора резервного копирования и восстановления Vault: от пустого каталога до kubectl apply с реальным CronJob и restore-Job в кластере. Инструмент скаффолдинга — Kubebuilder v4, runtime — controller-runtime.
- Как устроен Kubernetes control loop изнутри: Informer, WorkQueue, Reconcile
- Как спроектировать CRD с OpenAPI-схемой, CEL-правилами, Status subresource и printer columns
- Как написать контроллер на controller-runtime: ветвление, SetControllerReference, финализаторы, обновление статуса
- Как сгенерировать скелет оператора через Kubebuilder и что именно он генерирует
- Как задеплоить оператор в кластер, настроить Vault k8s-auth и проверить работу трёх режимов: scheduled backup, one-shot backup, restore
# macOS
brew install kubectl helm terraform yc go kubebuilder
# Проверить
kubectl version --client
terraform -v
yc --version
go version # нужен >= 1.23
kubebuilder version
docker info- Аккаунт в Yandex Cloud
- Созданный
cloud_idиfolder_id - Квоты: минимум 4 vCPU, 16 GB RAM в папке (Vault HA 3 реплики + оператор)
# Авторизоваться
yc init
yc config list # убедиться, что cloud_id и folder_id заполненыgit clone https://github.com/erlong15/mc-k8s-operator.git
cd mc-k8s-operator/terraform
cp terraform.tfvars.example terraform.tfvars
# Отредактировать terraform.tfvars: заполнить cloud_id и folder_id
export YC_TOKEN=$(yc iam create-token)
terraform init
terraform applyTerraform создаст: MK8S-кластер, Vault HA (3 реплики, Raft, TLS, auto-unseal через KMS), S3-бакет для бэкапов и Secret vault-backup-s3 с S3-кредами в namespace vault.
eval "$(terraform output -raw kubeconfig_command)"
kubectl get nodes# Инициализировать лидера — сохранить unseal keys и root token из вывода!
kubectl -n vault exec -it vault-0 -- vault operator init
# Подключить vault-1 и vault-2 к Raft-кластеру
kubectl -n vault exec -it vault-1 -- vault operator raft join \
-leader-ca-cert=@/vault/userconfig/tls/tls.crt \
https://vault-0.vault-internal:8200
kubectl -n vault exec -it vault-2 -- vault operator raft join \
-leader-ca-cert=@/vault/userconfig/tls/tls.crt \
https://vault-0.vault-internal:8200
# Проверить статус кластера
kubectl get pods -n vault
kubectl -n vault exec -it vault-0 -- vault statusСкрипт включит kubernetes auth в Vault, создаст политику vault-operator (snapshot read + restore force) и роль vault-operator — привязанную к SA vault-snapshot-runner в namespace vault.
export VAULT_TOKEN=<root-токен из vault operator init>
./demo/02-operator/setup-vault-auth.shContainer Registry создаётся terraform'ом, путь образов берём из output'ов — хардкодить registry-id не нужно. Образы собираются под linux/amd64 (см. PLATFORM в Makefile), поэтому совместимы с нодами даже при сборке на Apple Silicon.
# Один раз — настроить docker на работу с cr.yandex
yc container registry configure-docker
# Пути образов из terraform (выполнять из каталога terraform/)
export IMG=$(terraform -chdir=terraform output -raw operator_image)
export BACKUP_IMG=$(terraform -chdir=terraform output -raw backup_image)
cd operator
# Собрать и запушить образ оператора
make docker-build docker-push IMG=$IMG
# Собрать и запушить образ раннера (vault CLI + aws-cli + jq)
make docker-build-backup docker-push-backup BACKUP_IMG=$BACKUP_IMG
# Установить CRD и задеплоить контроллер (BACKUP_IMG прокидывается в env раннера)
make deploy IMG=$IMG BACKUP_IMG=$BACKUP_IMG
# Проверить запуск
kubectl get pods -n vault-operator-system -wНоды кластера уже имеют роль
container-registry.images.pullerна этот реестр (выдаётся в terraform), поэтому отдельный pull-secret не нужен — образ тянется автоматически.
Имя бакета генерируется terraform и уникально. В sample-манифестах spec.storage.bucket захардкожен как vault-backups — перед применением заменить на реальное имя:
# Получить реальное имя бакета
terraform output -raw backup_bucketПрименить пример с бэкапом по расписанию (подставить имя бакета в spec.storage.bucket):
kubectl apply -f operator/config/samples/vaultsnapshot-scheduled.yaml
# Наблюдать за сменой фаз
kubectl get vsnap -n vault -wПосле apply контроллер создаст CronJob. Можно убедиться:
kubectl describe cronjob -n vault.
├── terraform/ # Yandex Cloud: MK8S + Vault HA + S3 + KMS
├── operator/ # Kubebuilder v4: CRD, контроллер, RBAC, Makefile
│ ├── api/v1alpha1/ # Типы VaultSnapshot + DeepCopy
│ ├── internal/controller/ # Reconcile-логика
│ ├── config/ # CRD, RBAC, Deployment, samples, runner SA
│ ├── backup/ # Образ раннера (vault CLI + aws-cli + jq)
│ └── Makefile # manifests / generate / docker / deploy
├── demo/ # Вспомогательные скрипты и манифесты
│ └── 02-operator/ # setup-vault-auth.sh и tokenreview-binding.yaml
├── docs/ # Схемы архитектуры (drawio/excalidraw)
├── slides.md # Слайды мастеркласса (Marp markdown)
├── demo-plan.md # Подробный план демонстрации
└── README.md # Этот файл
kubectl delete vsnap --all -n vault
cd operator
make undeploy
make uninstall
cd ../terraform
terraform destroy