ADG Оставить заявку
Блог DevOps 5 мин чтения

Kubernetes Operators: CoreOS объясняет как управлять stateful-приложениями через Custom Resources

Разбираем паттерн Kubernetes Operator на примере Etcd Operator и Prometheus Operator: Custom Resources, контроллеры и зачем это нужно для stateful-сервисов.

Контекст момента

CoreOS развивает концепцию Kubernetes Operators - управление stateful-приложениями через Custom Resource Definitions и контроллеры

Мы давно присматриваемся к тому что CoreOS называет Operators - паттерн появился ещё в 2016-м в их блоге, но только сейчас, когда Kubernetes 1.9 дал стабильный Workloads API и StatefulSet в GA, это перестало выглядеть как академическая идея и начало ощущаться как практический инструмент. На прошлой неделе мы наконец сели и потратили несколько дней на нормальный разбор: что это такое, как работает Etcd Operator и Prometheus Operator, и есть ли нам от этого польза прямо сейчас.

Что такое Operator и зачем он нужен

Идея в следующем. Kubernetes умеет управлять stateless-приложениями более-менее из коробки: Deployment следит за количеством реплик, делает rolling update, рестартует упавшие поды. Это работает потому что stateless-приложения идемпотентны - любой экземпляр заменяем любым.

С stateful-приложениями всё сложнее. Etcd-кластер - это не три одинаковых пода. Там есть лидер, есть quorum, есть процедура добавления члена и процедура вывода из кластера. Prometheus в кластере с Alertmanager тоже требует специфической конфигурации. Если просто завернуть это в StatefulSet и надеяться на лучшее - рано или поздно получишь split-brain или потерянный член кластера.

Operator - это по сути способ закодировать операционное знание о конкретном приложении прямо в Kubernetes. Он состоит из двух частей:

  • Custom Resource Definition (CRD). Это новый тип объекта в Kubernetes API, который вы определяете сами. Например, EtcdCluster - объект который описывает желаемый etcd-кластер: количество узлов, версия, параметры TLS.
  • Контроллер. Обычный Pod в кластере, который смотрит на объекты вашего типа через Kubernetes Watch API и приводит реальное состояние к желаемому. Именно контроллер знает как правильно добавить узел в etcd-кластер, как провести rolling upgrade без потери quorum, что делать если один из подов пропал.

Это расширяет «примирение желаемого и реального состояния» - ту же механику что использует встроенный контроллер Deployment - на произвольно сложные stateful-приложения.

Etcd Operator: смотрим на реальный код

CoreOS выложил Etcd Operator как открытый проект на GitHub. Мы развернули его в тестовом кластере и посмотрели как это работает изнутри.

После установки оператора в кластере появляется новый тип: EtcdCluster. Создаёшь вот такой объект:

apiVersion: "etcd.database.coreos.com/v1beta2"
kind: "EtcdCluster"
metadata:
  name: "example-etcd-cluster"
spec:
  size: 3
  version: "3.2.13"

И всё - через несколько секунд в кластере появляются три пода с etcd, настроенные как кластер. Operator сам разобрался с первоначальной конфигурацией, bootstrap-токенами, peer-URL-ами.

Дальше интереснее. Если удалить один из подов - operator замечает это через Watch API и добавляет новый член в кластер через etcdctl member add, а не просто запускает новый pod как это сделал бы голый StatefulSet. Разница принципиальная: правильная процедура вступления в кластер вместо грубого рестарта.

Масштабирование: меняем spec.size: 5 в объекте EtcdCluster - operator по одному добавляет два новых члена, дожидаясь между добавлениями пока кластер вернётся в здоровое состояние. Это именно та логика которую обычно пишут в runbook для ручного масштабирования.

Prometheus Operator: другой уровень абстракции

Prometheus Operator от CoreOS решает немного другую задачу. Prometheus сам по себе не особо сложен в запуске - проблема в конфигурации. Когда у вас несколько команд, каждая хочет свой набор метрик, своих alerting-правил, и при этом вы не хотите чтобы одна команда случайно сломала конфигурацию другой - без автоматики начинается боль.

Prometheus Operator вводит несколько CRD:

  • Prometheus - сам экземпляр Prometheus с параметрами хранения, retention, ресурсами.
  • ServiceMonitor - описывает какие сервисы мониторить и как. Ссылается на сервисы через label selector.
  • PrometheusRule - набор alerting-правил.

Механика красивая. Каждая команда создаёт ServiceMonitor в своём namespace - описывает свои сервисы. Prometheus Operator видит эти объекты, генерирует конфиг Prometheus и перезапускает его (через /-/reload). Команда инфраструктуры контролирует сам экземпляр Prometheus, но не становится бутылочным горлышком для каждой новой цели мониторинга.

На нашей managed-инфраструктуре мы как раз сталкивались с этой проблемой: одна команда хочет добавить мониторинг нового сервиса, обращается к нам, мы правим конфиг Prometheus руками. Не масштабируется. Prometheus Operator выглядит как внятное решение.

Что нам это даёт и где пока трётся

После нескольких дней экспериментов мнение двоякое.

Плюсы реальные. Operator действительно инкапсулирует операционную сложность. Etcd Operator знает про quorum - вы про quorum думать не должны. Prometheus Operator убирает ручную правку конфигов. Декларативный API через Custom Resources органично вписывается в kubectl - kubectl get etcdclusters работает как ожидаешь.

Сложности тоже реальные. CRD это расширение API Kubernetes, и если оператор упадёт или зависнет - ваши объекты EtcdCluster будут существовать в etcd кластера, но никто не будет на них реагировать. Это не так страшно пока оператор просто не работает - страшнее если оператор работает неправильно и начинает принимать автоматические решения которых вы не ожидали. Нужно хорошо понимать что происходит внутри, прежде чем доверять ему production.

Второй момент: версионирование CRD. Etcd Operator сейчас в v1beta2 - это не production-стабильный контракт. API может поменяться между версиями оператора. Нам уже пришлось один раз мигрировать объекты при обновлении версии в тестовом кластере - ничего критичного, но следить нужно.

Третье: отладка. Когда что-то идёт не так - смотришь в логи оператора, а не в привычный kubectl describe pod. Добавляется ещё один слой, за которым надо уметь смотреть.

Где мы сейчас

Etcd Operator пока остаётся в тестовом кластере - хотим понять его поведение при различных сценариях отказа прежде чем трогать что-то клиентское. Prometheus Operator выглядит более зрелым и более понятным в части операционных рисков - планируем попробовать его на одном из кластеров в апреле.

Паттерн в целом кажется правильным ответом на вопрос «как управлять сложными stateful-вещами в Kubernetes». Не единственный возможный ответ, но логичный. Посмотрим как это будет работать за пределами тестового стенда.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.