Kubebuilder: фреймворк для написания Kubernetes API

Kubebuilder — это фреймворк для построения Kubernetes-API через custom resource definitions (CRDs).

По аналогии с web-фреймворками вроде Ruby on Rails и SpringBoot, Kubebuilder увеличивает скорость разработки и снижает сложность, которой управляют разработчики, предоставляя:

  • библиотеки и абстракции для построения общих практик

  • scaffolding (генератор) для запуска новых проектов

  • плагин-инфраструктуру для расширения опыта (например, scaffolding для Helm-chart-плагинов).

Kubebuilder поддерживается SIG-API-Machinery как стандартный путь написания операторов и расширений Kubernetes API.

Зачем

Kubernetes-операторы — это способ автоматизировать управление stateful-приложениями в кластере. Классические примеры: оператор Postgres, который сам делает failover; оператор Elastic, который скейлит шарды; оператор Cert-Manager, который выпускает TLS-сертификаты.

Написать оператор «голыми руками» через client-go — большой объём boilerplate-кода: контроллер-loop, очередь, exponential backoff, RBAC, leader election, лог-конфигурация. Kubebuilder делает всё это за вас и оставляет вам только бизнес-логику.

Quick start

1. Создать новый проект

mkdir -p ~/projects/my-operator
cd ~/projects/my-operator
kubebuilder init --domain example.com --repo example.com/my-operator

Это создаёт стандартную раскладку: cmd/, api/, internal/controller/, config/, Dockerfile, Makefile.

2. Сгенерировать CRD и контроллер

kubebuilder create api --group apps --version v1 --kind MyApp

Появляются:

  • api/v1/myapp_types.go — структура CRD (Spec + Status).

  • internal/controller/myapp_controller.go — заготовка reconcile-цикла.

  • config/crd/ — манифесты CRD.

  • config/rbac/ — RBAC, нужное контроллеру.

3. Описать ваш resource

type MyAppSpec struct {
    Replicas int32  `json:"replicas"`
    Image    string `json:"image"`
}

type MyAppStatus struct {
    AvailableReplicas int32       `json:"availableReplicas"`
    Phase             string      `json:"phase,omitempty"`
    LastUpdated       metav1.Time `json:"lastUpdated,omitempty"`
}

4. Заполнить reconcile-логику

func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    var app appsv1.MyApp
    if err := r.Get(ctx, req.NamespacedName, &app); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // Создать/обновить Deployment под наш CRD
    deploy := buildDeployment(&app)
    if err := controllerutil.SetControllerReference(&app, deploy, r.Scheme); err != nil {
        return ctrl.Result{}, err
    }
    if err := r.applyDeployment(ctx, deploy); err != nil {
        return ctrl.Result{}, err
    }

    // Обновить status
    app.Status.Phase = "Ready"
    app.Status.LastUpdated = metav1.Now()
    return ctrl.Result{}, r.Status().Update(ctx, &app)
}

Контроллер автоматически подписывается на изменения MyApp и принадлежащих ему Deployment-ов через owner-references.

5. Тестировать

Kubebuilder ставит envtest — пакет, который поднимает реальный kube-apiserver и etcd в процессе теста. Это значит ваши тесты гоняют против настоящего API, без mock-ов:

it("should create a Deployment", func() {
    app := &appsv1.MyApp{
        ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
        Spec:       appsv1.MyAppSpec{Replicas: 3, Image: "nginx:1.27"},
    }
    Expect(k8sClient.Create(ctx, app)).To(Succeed())

    Eventually(func() int32 {
        var deploy appsv1.Deployment
        k8sClient.Get(ctx, types.NamespacedName{Name: "foo", Namespace: "default"}, &deploy)
        return *deploy.Spec.Replicas
    }, "5s").Should(Equal(int32(3)))
})

6. Запустить

make install        # установить CRD в кластер
make run            # запустить контроллер локально, против текущего kubeconfig

Для прода: make docker-build docker-push deploy IMG=registry/my-operator:v1.

Что внутри

Kubebuilder — это thin wrapper поверх controller-runtime. Под капотом:

  • Informer — кэширует объекты из API-сервера, чтобы reconcile не дёргал etcd на каждое событие.

  • Workqueue — очередь с rate-limiting и dedup-ом.

  • Manager — поднимает все контроллеры, leader election, health checks.

  • Webhook framework — admission/validating webhooks из коробки.

Когда брать

  • Вы пишете оператор для своего приложения — однозначно Kubebuilder.

  • Вам нужен validating webhook для CRD — Kubebuilder уже всё умеет.

  • Production-операторы (Strimzi, OperatorHub) — почти все на Kubebuilder или Operator SDK (тоже на controller-runtime).

Альтернативы

  • Operator SDK (Red Hat) — обёртка вокруг Kubebuilder с поддержкой Helm и Ansible-операторов.

  • Metacontroller — для простых случаев без своего CRD.

  • kubectl + bash — для совсем простых операций (но это уже не оператор).

GitHub: kubernetes-sigs/kubebuilder. Apache-2.0.