Skip to content

Repository files navigation

Мастеркласс: Kubernetes Operators — пишем оператор с нуля

На примере оператора резервного копирования и восстановления 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

  • Аккаунт в Yandex Cloud
  • Созданный cloud_id и folder_id
  • Квоты: минимум 4 vCPU, 16 GB RAM в папке (Vault HA 3 реплики + оператор)
# Авторизоваться
yc init
yc config list   # убедиться, что cloud_id и folder_id заполнены

Быстрый старт

1. Поднять инфраструктуру

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 apply

Terraform создаст: MK8S-кластер, Vault HA (3 реплики, Raft, TLS, auto-unseal через KMS), S3-бакет для бэкапов и Secret vault-backup-s3 с S3-кредами в namespace vault.

2. Подключиться к кластеру

eval "$(terraform output -raw kubeconfig_command)"
kubectl get nodes

3. Инициализировать Vault (один раз)

# Инициализировать лидера — сохранить 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

4. Настроить Vault k8s-auth для оператора (один раз)

Скрипт включит 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.sh

5. Собрать и задеплоить оператор

Container 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 не нужен — образ тянется автоматически.

6. Узнать имя S3-бакета и создать первый бэкап

Имя бакета генерируется 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

Ссылки

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages