Kubernetes operator для Postgres Pro: разбираем API, failover и upgrade path
Развернули Postgres Pro через официальный Kubernetes operator. Разбираем зрелость API, failover-механику и upgrade path. Сравниваем с Patroni-based подходом на баребоне.
Отечественные вендоры СУБД публикуют production-grade Kubernetes operators в 2026 году
Несколько месяцев назад Postgres Pro опубликовал Kubernetes operator - не «технический превью», а релизную версию с заявленной production-readiness. Мы взяли его на один из внутренних стендов и прогнали через сценарии, которые реально интересуют при принятии решения: как ведёт себя failover, насколько зрел API, что происходит при upgrade. Ниже - честный разбор без маркетинга.
Контекст: почему это интересно именно сейчас
Два года назад запустить Postgres в Kubernetes означало либо community-операторы (Zalando postgres-operator, CloudNativePG), либо ручной StatefulSet с Patroni-ом поверх. Оба пути рабочие, но ни один не давал нативной интеграции с Postgres Pro Enterprise - то есть с продуктом, который реально используется на КИИ-объектах из-за сертификата ФСТЭК.
Появление официального оператора меняет уравнение. Вопрос - насколько он готов к production, или это «докажи что работает» версия.
Зрелость API: что удивило
Первое наблюдение - CRD структурированы грамотно. PostgresCluster как основной ресурс имеет разумную иерархию: spec.instances описывает пул узлов, spec.proxy - pooler (поверх Odyssey), spec.backups - S3-совместимое хранилище. Это не свалка параметров, а читаемая структура, которую понятно как версионировать.
Что менее приятно: документация по ряду полей скудная. Конкретно - параметры тонкой настройки Patroni-конфигурации внутри оператора. Operator прячет Patroni под капот (это правильно для операционной простоты), но когда нужно поправить synchronous_mode_strict или ttl - путь до этих параметров через spec.patroni не очевиден и требует чтения исходников, а не документации. Это не блокер, но симптом того, что оператор рос снизу вверх: сначала функциональность, потом документация.
Версионирование API - v1beta1. Честно. Значит, breaking changes теоретически возможны до v1. На практике мы не видели ломающих изменений между патч-версиями оператора, но закладывать это в риски при долгосрочной эксплуатации разумно.
Failover: как это работает и где граница
Под капотом - Patroni. Оператор не изобретает собственную механику leader election, а делегирует её проверенному инструменту. Это правильное решение.
Тест failover-а: убиваем primary pod, смотрим что происходит. На нашем стенде (3 реплики, etcd как DCS, latency в кластере в норме) смена лидера заняла 35-45 секунд. Это стандартное время для Patroni с настройками по умолчанию - ttl 30 секунд, retry_timeout 10 секунд. Не быстро, но предсказуемо.
Что оператор добавляет поверх голого Patroni:
- Service routing.
primaryиreplicasсервисы переключаются автоматически. Не нужно руками управлять VIP или перепрописывать эндпоинты. - PodDisruptionBudget. Из коробки не даёт одновременно убить больше одного пода, что спасает от случайного
kubectl drainс потерей кворума. - Readiness probe. Реплики выходят из сервиса при отставании
pg_wal_lsn_diffвыше порога - параметр настраивается. Это важно для приложений, которые читают с реплик и чувствительны к lag.
Что оператор не закрывает из коробки: switchover с нулевой потерей данных в synchronous_commit режиме. Технически Patroni это умеет, но настройка через spec.patroni потребовала ручного вмешательства - дефолтная конфигурация использует async режим.
Upgrade path: самое интересное
Мажорный upgrade PostgreSQL через оператор - это сценарий, где многие инструменты исторически буксуют. Проверяли переход с PG17 на PG18.
Оператор запускает pg_upgrade внутри init-контейнера с правильным порядком: сначала останавливает реплики, делает upgrade на primary, потом реклонирует реплики через pg_basebackup. Это правильная последовательность. Время даунтайма при нашей тестовой базе (около 50 GB) - порядка 5-8 минут, что для мажорного upgrade вполне нормально.
Проблема, на которую наткнулись: оператор не проверяет совместимость расширений перед запуском upgrade. Если у вас кастомные расширения или extension из Postgres Pro Enterprise (например, multimaster или pg_probackup в embedded режиме) - оператор об этом не знает и не предупреждает. Мы получили упавший upgrade из-за несовместимого расширения и потратили полчаса на диагностику. Pre-upgrade check - это то, чего не хватает.
Минорные обновления (патч-версии) работают чисто: rolling update через kubectl rollout, без даунтайма при синхронной конфигурации.
Сравнение с Patroni на баребоне
Прямой вопрос: стоит ли переходить с отлаженного Patroni-стека на виртуалках на этот оператор?
Если у вас уже есть работающий Patroni-кластер на баребоне с настроенным HAProxy и проверенными runbook-ами - оснований для срочной миграции нет. Вы уже знаете своё решение. Оператор не даёт кардинально лучшего failover или более надёжного хранения данных.
Что оператор даёт реально:
- Декларативное управление. Конфигурация кластера в Git как манифест. Это ценно в GitOps-контексте, который мы активно используем с Deckhouse и fleet management.
- Меньше операционного кода. Не нужен отдельный Ansible playbook для деплоя Patroni, отдельный для HAProxy, отдельный для Odyssey. Всё в одном операторе.
- Консистентная среда. Если вся инфра уже в Kubernetes - держать отдельный barebone-кластер только для БД создаёт операционный разрыв.
Что оператор не заменяет:
- Тонкую настройку PostgreSQL под специфическую нагрузку.
spec.postgresql.parametersесть, но проверять что параметры применились правильно всё равно нужно вручную. - Опыт команды с Patroni. Если ваши инженеры умеют диагностировать Patroni по логам - этот навык не переносится автоматически. Абстракция оператора прячет детали, и когда что-то идёт не так, нужно уметь в неё заглянуть.
Итог
Operator Postgres Pro - рабочий инструмент для production, не MVP. API достаточно стабилен, failover предсказуем, upgrade path работает с оговорками по расширениям. Для новых кластеров в Kubernetes-среде это разумный выбор, особенно если вам важна декларативность и вы уже на GitOps.
Для существующих Patroni-кластеров на баребоне - не торопитесь. Зрелость оператора достаточная, но не настолько, чтобы оправдать миграцию только ради инструментальной унификации. Разбирайте конкретный операционный контекст.
Если хотите сравнить архитектуры для вашего стека - это как раз то, что мы делаем в рамках managed.