Мало скопировать чужой код, чтобы оператор работал как надо. Перед этим стоит узнать, как устроен Kubernetes: что делать, если оператор ведёт себя странно, как изменить его поведение и где искать проблему. Без теории не получится написать оператора, который работает так, как задумывали разработчики Kubernetes.
Меня зовут Иван, я техлид в Outlines Tech. Это первая часть цикла про создание собственного K8S-оператора. Чтобы сразу не перегружать вас информацией, ниже будет только база про Kubernetes: как он устроен, из чего состоит, как управляет состоянием и зачем это всё знать перед тем, как писать оператора.
Во второй части я углублюсь в оператора: расскажу про локальный кластер, Java‑клиенты, framework, CRD, права доступа и реализацию логики через Reconciler. В третьей расскажу, как довести оператора до продакшн‑уровня: сделать логику устойчивой, учесть ошибки, добавить тесты, логи, метрики и безопасно выкатить оператора в кластер.
Предисловие. Когда я начинал писать своего K8s-оператора, мне не хватало единого материала, который бы объяснял, как работает Kubernetes. Я знал только, что у него на логотипе штурвал и через него можно запускать микросервисы. Этот цикл — попытка собрать в одном месте всё важное о разработке операторов, которые не стыдно выпускать в production, чтобы вам не пришлось искать эту информацию по кусочкам.
База: что такое Kubernetes и что он умеет делать
Kubernetes или K8s — open‑source платформа, которая управляет контейнерами в кластере. Она запускает нужное количество экземпляров приложения, распределяет их по рабочим узлам и следит, чтобы они были в рабочем состоянии.
В основе Kubernetes — контроль желаемого состояния. Это работает так: разработчик описывает, что хочет получить: сколько pods запустить, из каких контейнеров, с какими параметрами. Затем Kubernetes сравнивает это описание с реальным состоянием и при необходимости что-то меняет.
Например, если должен быть один pod, а работает ноль, то Kubernetes создаст новый. А если pod есть, но он работает с ошибкой — K8s это заметит и перезапустит его, потому что текущее состояние не соответствует желаемому.
За контроль желаемого состояния отвечают встроенные контроллеры. Например, контроллер deployment следит, чтобы нужное количество pods было в нужном состоянии. Если что-то меняется, он восстанавливает порядок.
Иногда встроенных контроллеров не хватает. Например, если нужно управлять внешней базой или сторонним сервисом. Для этого пишут K8S‑оператора — программу, которая работает как контроллер: сравнивает желаемое состояние ресурса с текущим и приводит систему в порядок. Пользователь описывает желаемое состояние в ресурсе, оператор следит, чтобы оно соответствовало действительному состоянию и выполняет автоматическое приведение.
Kubernetes управляет всем, что нужно продукту для работы:
следит за количеством экземпляров,
балансирует нагрузку,
обновляет приложение без простоя,
мониторит состояние.
Без K8s возникает путаница: где что работает, как это масштабируется и что делать, если что-то перестало работать. Например, если несколько экземпляров приложения развёрнуты на разных worker nodes и один из них выходит из строя, Kubernetes сам перезапустит pod на другом узле. Без него всё это пришлось бы отслеживать и перезапускать вручную.
«Окружение в широком смысле»: из чего состоит K8s
Kubernetes управляет всем что нужно для запуска и работы приложений: от кода и конфигураций до сетей и железа. Я называю это «окружением в широком смысле». Термин придумал сам, чтобы объяснить, как работает K8s.

«Окружение в широком смысле» состоит из четырёх слоёв:
Железо, Hardware: процессоры, диски, сетевые порты. Это для админов, нам как разработчикам это неинтересно.
Инфраструктура, Infrastructure: базы данных, identity‑провайдеры, мониторинг, Prometheus, Grafana, конфиги, секреты. Всё, что поддерживает приложение.
Система, System: сеть, DNS, Persistent Volume, безопасность. Слой соединяет инфраструктуру с железом.
Приложения, Application: микросервисы, jobs, cron jobs. Это то, что пишет разработчик.
Все четыре слоя вместе формируют рабочее окружение, которым Kubernetes управляет.
Оператор работает с приложением, инфраструктурой или системой. От этого зависит, какие ресурсы описывать и какую логику в него закладывать. Например, оператор для Keycloak работает на уровне инфраструктуры: он создаёт OAuth2 клиентов, назначает роли и управляет секретами. А PersistentVolumeController — на системном уровне управляет дисковым пространством и доступом к нему.
Как работает Kubernetes
K8s управляет системой через три ключевых элемента: ресурс, субъект с состоянием, контроллер или оператор. Вместе они реализуют контроль желаемого состояния. Ниже разберу каждый подробнее и объясню связь между ними.

Ресурс — декларация для Kubernetes в виде JSON или YAML. В ней мы описываем желаемое состояние субъекта: например, сколько копий приложения запустить, из какого контейнера и с какими настройками.
Под ресурсом в Kubernetes понимается всё, с чем работает пользователь: pods, deployments, services, roles, gateways, database. Пользовательские сущности, описанные через Custom Resource Definition (CRD) — это тоже ресурсы.
Субъект с состоянием, stateful subject — то, что появляется в кластере после применения ресурса. Это к примеру контейнеры, базы данных, сервисы, порты. Kubernetes самостоятельно создаёт субъекты по декларации и следит, чтобы всё работало. Например, если в YAML-ресурсе мы описали, что нужно запустить три контейнера, то K8s сам их запустит.
Контроллер (или оператор) следит за соответствием между ресурсом и субъектом. Он проверяет, совпадает ли текущее состояние в кластере с тем, что описано в декларации. Например, если в YAML указано три контейнера, а работает два — контроллер сам поднимет третий.
Контроллер и оператор по сути одно и то же. Разница в том, что контроллеры управляют встроенными ресурсами, а операторы работают с пользовательскими через Custom Resource Definition (CRD). Например, с базами данных, провайдерами авторизации, очередями.
Kubernetes работает по следующему принципу:
Разработчик описывает желаемое состояние через ресурс.
Контроллер или оператор отслеживает изменения и сравнивает с текущим состоянием субъектов.
В конце состояние субъекта приводится к желаемому.
Если что-то меняется или ломается — система автоматически возвращает всё в нужное состояние. Этот процесс идёт постоянно, без остановки.
Оператор позволяет разработчику расширять возможности Kubernetes: создавать ресурсы через CRD, добавлять собственные субъекты и управлять ими, как будто это встроенные pod или deployment.
Как Kubernetes поддерживает согласованность состояния: о Reconciliation
Reconciliation — паттерн, по которому работает Kubernetes. Он постоянно сравнивает описанное разработчиком желаемое состояние ресурса с текущим состоянием в кластере и вносит изменения, если что-то не совпадает.

Паттерн Reconciliation состоит из четырех компонент:
1. Desired state: это описание ресурса. К примеру, пишем, что нужно запустить три pods и это цель, к которой Kubernetes должен привести систему.
2. Current state: то, что работает в кластере в данный момент. Например, сейчас запущено только два pods, потому что один упал или не стартовал.
3. Difference (Diff): разница между желаемым состоянием и текущим. Например, хотим три pods, а работает два. Kubernetes автоматически исправляет разницу, выполняя корректирующие действия.
4. Actions: корректирующие действия, которые выполняет контроллер или оператор, чтобы устранить расхождение. Например, запустить недостающий pod, чтобы привести систему к нужному состоянию.
Reconciliation позволяет оператору принимать решения самостоятельно. Например, если в ресурсе сменился статус с Active на Failed, оператор может перезапустить связанный сервис или обновить статус в другой системе.
В итоге Kubernetes поддерживает согласованность благодаря Reconciliation, который автоматически замечает отклонения и исправляет их. Чтобы реализовать этот процесс, K8s использует паттерн Controller — об этом в следующем блоке.
Как реализован Reconciliation в K8s: про паттерн Controller
В основе оператора или контроллера лежит поведенческий паттерн Controller. Он помогает Kubernetes следить за состоянием ресурсов и автоматически приводит систему в порядок.
Если оператор работает нестабильно, важно понимать, как устроен паттерн Controller. Это поможет быстрее разобраться, например, почему не приходит событие, почему не обновился ресурс или почему логика не сработала.
Паттерн Controller состоит из двух элементов:
1. Watcher — отслеживает изменения в ресурсах. Он подключается к API-серверу Kubernetes и получает уведомления, когда ресурс создают, меняют или удаляют. Watcher уже входит в состав K8s-клиента, писать его самому не нужно.
В Kubernetes есть надстройка над Watcher — SharedInformer. Он кэширует ресурсы, восстанавливает соединение при сбоях и передаёт только изменения, а не весь список событий. Это снижает нагрузку на API и ускоряет работу.
2. Reconciler — реагирует на изменения. Он получает события от Watcher, сравнивает желаемое состояние с действительным и выполняет нужные корректирующие действия: пересоздаёт контейнер, обновляет конфигурацию или поднимает базу.
Когда мы пишем своего оператора, мы реализуем только Reconciler — логику, по которой система будет реагировать на изменения. Остальное уже есть в Kubernetes.

Коротко, что нужно знать о Kubernetes, чтобы написать своего оператора
В основе Kubernetes — контроль желаемого состояния: разработчик описывает, что хочет получить, а Kubernetes сам приводит систему к этому состоянию.
Ресурс — это декларация с желаемым состоянием. Kubernetes читает её и создаёт нужные объекты.
Stateful subject — это то, что появляется в кластере после применения ресурса: контейнер, база, сервис.
Контроллер или оператор следит, чтобы текущее состояние субъекта соответствовало описанному в ресурсе.
Контроллер и оператор по сути одно и то же. Только контроллер управляет встроенными ресурсами, а оператор — пользовательскими, описанными через CRD.
Reconciliation — паттерн, по которому Kubernetes сравнивает желаемое и текущее состояние и вносит изменения.
Reconciliation Loop — это непрерывный цикл, в котором оператор или контроллер замечает отклонения и сам всё исправляет.
Оператор состоит из Reconciler и Watcher. Watcher отслеживает изменения, а Reconciler решает, что делать.
Оператор может работать с приложением, инфраструктурой или системой. Это влияет на логику, которую мы в него закладываем.
Этой базы хватит, чтобы перейти к созданию собственного оператора. Про него подробнее я расскажу во второй части.
Если было интересно, заглядывайте в Telegram-канал Outlines Tech. Там пишем о карьере в IT, выкладываем вакансии и мемы, иногда говорим умные вещи.
Спасибо за внимание. Если у вас остались вопросы о Kubernetes — готов на них ответить в комментариях.
Xexa
Наверное познавательно. Было бы, если бы одно по одному из параграфа в параграф не было. Две трети смело снести и не потеряется смысл.
Имхо
dekabr1st Автор
Спасибо за обратную связь