CloudNativePG и Crunchy PGO: честное сравнение

В этой статье сравниваются CloudNativePG и Crunchy PGO — два самых популярных open-source оператора для запуска PostgreSQL в Kubernetes. Рассматриваются архитектура, дизайн образов, стратегия резервного копирования, обновление мажорных версий, наблюдаемость, лицензирование и здоровье сообщества. Как сооснователь и мейнтейнер CloudNativePG, я не претендую на нейтральность и говорю об этом сразу. Что я могу предложить — это осознанную предвзятость, основанную на годах ежедневной работы над проектом и на искреннем уважении к тому, что Crunchy Data создала в этой области.

Долгие годы я сопротивлялся идее написать прямое сравнение CloudNativePG и Crunchy PGO. С моей позиции это казалось неправильным жанром. Но после нескольких лет, за которые оба проекта повзрослели, и особенно после того, как Crunchy Data была приобретена Snowflake, меня всё чаще стали спрашивать, чем эти два оператора отличаются. Теперь я считаю, что время пришло. На прошлой неделе я написал Recipe 24 — ответ на практический вопрос, как выполнить миграцию. Этот пост берётся за нечто более сложное: честную оценку того, почему два оператора различаются и что эти различия значат для команд, выбирающих долгосрочную платформу для PostgreSQL в Kubernetes.

Я признаю наследие Crunchy, объясню архитектурные решения, которые, на мой взгляд, делают CloudNativePG более прочным фундаментом, приведу данные там, где они есть, и обозначу области, где моя точка зрения неизбежно субъективна. Я не буду делать вид, что это нейтральный документ.

Пионерская роль Crunchy

Crunchy Data выпустила первый оператор PostgreSQL для Kubernetes в марте 2017 года — менее чем через два года после дебюта самого Kubernetes и вскоре после того, как CoreOS представила паттерн оператора. Это было по-настоящему опережением своего времени. Моя команда в 2ndQuadrant (позже приобретённой EDB) внимательно следила за экосистемой в тот период, но решила подождать — прежде всего из-за незрелости примитивов хранения в Kubernetes. Переломный момент наступил в апреле 2019 года, когда Kubernetes 1.14 представил стабильную поддержку локальных persistent volumes. Наш первый cloud-native оператор, Cloud Native BDR, появился вскоре после этого — он был создан для active/active нагрузок на базе технологии двунаправленной репликации 2ndQuadrant (ныне EDB Postgres Distributed). Первый коммит в то, что стало CloudNativePG, был сделан 18 февраля 2020 года Leonardo Cecchi, Marco Nenciarini и мной.

Смысл не в том, чтобы преуменьшить то, что построила Crunchy. PGO запускал продакшн-PostgreSQL в Kubernetes ещё до того, как большинство сочло эту идею разумной, и множество команд построили свою инфраструктуру на нём. Этот факт заслуживает признания прежде любого сравнения.

Архитектурный водораздел

Важнейшее различие между двумя операторами — это не какая-то функция. Это философия о том, где должна жить логика управления высокой доступностью (HA) PostgreSQL.

Crunchy PGO делегирует HA проекту Patroni — распределённому HA-менеджеру на Python, который работает как процесс внутри каждого пода. Patroni — уважаемый проект и, на мой взгляд, вершина инженерной мысли в управлении кластерами PostgreSQL в традиционных Linux-окружениях. Patroni координирует переключение (failover) через распределённое хранилище конфигурации — это может быть etcd, Consul, ZooKeeper или сам Kubernetes, — а роль PGO сводится в основном к тому, чтобы подготовить и настроить то, что нужно Patroni. Оператор надстраивается над Patroni, а не заменяет его. В контексте Kubernetes это означает, что рядом друг с другом работают две сложные распределённые системы. Это вполне обоснованный выбор, хотя он несёт компромиссы, которые наша команда взвесила иначе.

На KubeCon в Солт-Лейк-Сити в 2024 году инженер из Crunchy прямо объяснил их логику: зачем писать сложный код распределённых систем с нуля, если Patroni уже существует и проверен в боях? Это разумная позиция, и я её понимаю. Наша команда просто пришла к другому выводу. Мы приняли принципиально иное решение: доверять Kubernetes API ровно тому, для чего он был спроектирован (управлению распределёнными системами и приложениями), и писать HA-логику нативно в самом операторе, а не делегировать её отдельному инструменту.

CloudNativePG проектировался примерно тремя годами позже, и эта посылка легла в его основу: Kubernetes — это control plane, а оператор должен использовать его напрямую. Нет Patroni, нет зависимости от etcd для HA и нет HA-фреймворка, работающего параллельно с Kubernetes. Kubernetes API server — единственный источник истины о состоянии каждого ресурса, включая топологию primary/standby. Документация по контроллеру и документ о технической архитектуре описывают, как это выглядит на практике.

Прямое управление подами

CloudNativePG не использует StatefulSets. Он управляет ресурсами Pod и PVC напрямую, что даёт оператору детальный контроль, недостижимый через StatefulSets. Когда происходит failover, CloudNativePG повышает реплику с наибольшим Log Sequence Number (LSN), гарантируя, что новым primary станет самый актуальный экземпляр — независимо от его имени или порядкового индекса. Логика порядковых номеров, привязанная к StatefulSet, не способна выразить такое решение нативно; для этого нужен отдельный координирующий слой — именно его в случае PGO предоставляет Patroni.

Прямое управление подами также позволяет CloudNativePG координировать изменения конфигурации по всему кластеру в правильном порядке, включая параметры, которые на standby должны быть установлены в значения, равные или большие, чем на primary, прежде чем изменение будет применено. При использовании StatefulSets такое согласованное упорядочивание требует дополнительной логики поверх примитива.

Instance Manager

В CloudNativePG нет sidecar-контейнеров для управления HA. Управляющая логика работает как Instance Manager — Go-бинарник, выступающий в роли PID 1 внутри контейнера PostgreSQL. Он обслуживает полный жизненный цикл Postgres, участвует в самовосстановлении и напрямую общается с Kubernetes API, сообщая о состоянии, задержке репликации и позиции.

Особенно показательно то, как Instance Manager взаимодействует с Kubelet через health-пробы, которые учитывают специфику базы данных, а не являются универсальными. Startup-проба не даёт Kubelet перезапустить под во время инициализации или восстановления. Readiness-проба проверяет, готов ли экземпляр обслуживать трафик, — с учётом задержки репликации на репликах, если это настроено. Liveness-проба на primary выполняет проверку на изоляцию: если одновременно становятся недоступны и API server, и другие экземпляры, проба намеренно завершается неудачей, заставляя Kubelet перезапустить под и вывести изолированный primary из строя. Это снижает риск ситуации split-brain (хотя она в принципе не может возникнуть при синхронной репликации). Patroni ввёл аналогичную возможность в версии 3.0.0 через свой режим DCS failsafe. CloudNativePG независимо реализовал ту же концепцию по-кубернетесовски: вместо опроса других узлов через REST API он поручает работу liveness-пробе и Kubelet. Обсуждение, приведшее к нашей реализации, находится здесь — это хороший пример того, как одна и та же задача может решаться принципиально разными примитивами в зависимости от вашей среды исполнения.

О доступности Kubernetes API server

Распространённое возражение против этой архитектуры звучит так: что происходит во время сбоя Kubernetes API server? Ответ CloudNativePG — приостановить операции failover и поставить во главу угла защиту данных. Но я считаю, что этот вопрос заслуживает откровенного, а не сугубо технического ответа.

Здесь стоит быть точным. Как отмечает документация Kubernetes, существующие поды продолжают работать при недоступности API server, потому что Kubelet управляет ими локально. Останавливаются планирование, реконсиляция и логика оператора, включая контроллер CloudNativePG. Без API server CloudNativePG не может принимать глобальные решения о кластере, такие как запуск failover, а попытка сделать это без надёжного представления о полном состоянии кластера привнесла бы риск, а не устранила его. Поэтому приостановка таких решений и приоритет защиты данных — это не столько ограничение, сколько честное следствие дизайна, который доверяет единственному авторитетному источнику истины. Стоит также отметить, что сам Kubernetes спроектирован для устранения рисков доступности control plane через развёртывание по нескольким зонам доступности, что делает полный сбой API server всё менее вероятным событием в правильно настроенном кластере. На наш взгляд, более надёжный ответ для сценариев, где под угрозой оказывается сам control plane, — это отказоустойчивая мультирегиональная архитектура, которую CloudNativePG поддерживает через распределённую топологию для реплик-кластеров.

Практическое следствие такого подхода, по нашему опыту, — меньшая операционная поверхность: нет дополнительной распределённой системы, которую нужно мониторить, отлаживать или обновлять рядом с оператором, и у сбоев меньше мест, где спрятаться. При этом командам, уже глубоко знакомым с Patroni, может потребоваться некоторая перестройка ментальной модели при операционном переходе.

Дизайн образа, размер и безопасность

Архитектурное решение встроить в образ операнда только PostgreSQL и ничего больше имеет прямые последствия для размера образа и профиля безопасности. Образ операнда Crunchy упаковывает Patroni (и его Python-рантайм), pgBackRest, pgAudit, pgvector, TimescaleDB, pg_cron, pg_partman и другие расширения в единый образ на базе UBI9, потому что все они должны быть размещены вместе, чтобы Patroni работал. Минимальный образ CloudNativePG содержит только PostgreSQL, а расширения доставляются во время выполнения как OCI-тома образов через возможность Kubernetes ImageVolume (требует PostgreSQL 18 или новее и Kubernetes 1.35 или новее, где ImageVolume включён по умолчанию; на 1.33 и 1.34 его можно включить через feature gate) — это подробно разобрано в CNPG Recipe 23. Добавление или удаление расширения — это декларативное изменение манифеста Cluster; оно не требует другого базового образа и, что важно, не нарушает неизменяемость (immutability).

Числа получены командой docker scout quickview для актуальных образов:

Образ Пакеты Critical High

crunchy-postgres:ubi9-17.9-2610

625

2

156

postgresql:18-minimal-trixie

140

0

4

Минимальный образ CNPG minimal-trixie несёт 140 пакетов против 625 у исходного образа Crunchy, ноль критических уязвимостей против двух и четыре high против 156. Его база Debian Trixie Slim не имеет ни одной известной собственной уязвимости. Число пакетов важно операционно: меньше пакетов — меньше радиус поражения при любом будущем раскрытии уязвимости и короче список для аудита. Минимальный образ CNPG также поставляется с полной provenance-аттестацией Software Bill of Materials (SBOM).

По теме лицензирования образов: контейнерные образы Crunchy Data исторически распространялись в рамках Crunchy Data Developer Program, который ограничивает использование в продакшене для организаций с числом сотрудников более 50. Сам оператор — open-source; образы, которые он использует по умолчанию, таковыми были не всегда. Изменилось ли это после приобретения Snowflake — стоит уточнить напрямую у Crunchy перед принятием решения о закупке. Каждый образ в экосистеме CloudNativePG — оператор, операнд, образы расширений — полностью open-source под лицензией Apache License 2.0.

Обновление мажорных версий

Это область, в которую CloudNativePG вложился основательно и где различие конкретно.

Crunchy PGO v6 предоставляет обновление мажорных версий через специальный CRD PGUpgrade. Кластер должен быть полностью остановлен, прежде чем обновление сможет начаться; затем pg_upgrade отрабатывает до конца, и только после этого кластер снова вводится в строй. Окно простоя определяется циклом остановки и перезапуска, а не размером датасета, поскольку pg_upgrade по умолчанию использует жёсткие ссылки и завершается быстро независимо от объёма данных. Процесс в документации явно описан как необратимый: декларативного пути отката нет, и Crunchy рекомендует хранить копию кластера на старой версии, если откат вызывает опасения. Standby-кластеры во время обновления не поддерживаются и после него должны быть удалены и пересозданы с нуля. Несколько пост-обновленческих задач также требуют ручного вмешательства: запуск ANALYZE, обновление расширений и очистка старых каталогов данных.

Как я показал в Recipe 24, CloudNativePG предлагает два пути. Офлайн-путь использует pg_dump / pg_restore через встроенный механизм bootstrap.initdb.import — полностью декларативно, выполняется при bootstrap кластера. Онлайн-путь использует нативную логическую репликацию PostgreSQL с декларативными ресурсами Publication и Subscription, сокращая окно переключения до секунд независимо от размера датасета. Третий путь — in-place обновление мажорной версии через pg_upgrade — был представлен в CNPG Recipe 17 и поддерживает автоматизированный откат при наличии реплик. Все три пути доступны уже сегодня.

Резервное копирование и восстановление

Наша вовлечённость в резервное копирование PostgreSQL существенно предшествует CloudNativePG. Barman зародился в команде 2ndQuadrant и является одним из самых широко используемых инструментов для физического резервного копирования PostgreSQL и архивирования WAL. Этот опыт с самого начала определил наш подход к бэкапам в CloudNativePG.

Crunchy PGO встраивает pgBackRest в образ операнда и настраивает его через спецификацию PostgresCluster. pgBackRest — превосходный инструмент. Следствие встроенной модели в том, что код бэкапа и код базы данных связаны: обновление pgBackRest требует нового образа операнда.

CloudNativePG поддерживает два подхода к резервному копированию, подробно сравниваемых в документации. Первый — нативные для Kubernetes снимки томов (volume snapshots), единственный метод бэкапа, обрабатываемый непосредственно самим оператором. Снимки томов поддерживают как холодные, так и горячие бэкапы, хотя горячие бэкапы требуют наличия архива WAL для согласованного восстановления. На KubeCon Atlanta 2023 мы продемонстрировали 2-минутное восстановление базы данных объёмом 4,5 ТБ с помощью этого подхода.

Второй — CNPG-I, плагинный интерфейс, полностью отвязывающий инструментарий бэкапа от оператора. Barman Cloud Plugin — эталонная реализация и единственная, поддерживаемая сообществом на данный момент, но интерфейс открыт: ничто не мешает сообществу или организациям писать плагины для других инструментов, таких как pgBackRest или WAL-G.

Наблюдаемость

Оба оператора предоставляют метрики PostgreSQL для Prometheus. CloudNativePG идёт дальше, поддерживая декларативные пользовательские метрики, определяемые в ConfigMaps или Secrets и связываемые с ресурсом Cluster, что позволяет командам управлять специфичными для приложения запросами как ресурсами Kubernetes рядом с самим кластером. Документация по мониторингу и поддерживаемая сообществом Grafana-дашборд покрывают полный набор метрик по умолчанию.

Что касается логирования, каждый контейнер, управляемый CloudNativePG, пишет структурированные логи в stdout в формате JSON, как описано в документации по логированию. Это осознанное проектное решение: оно не требует управления файлами логов внутри пода и напрямую интегрируется с любым решением для агрегации логов уровня Kubernetes — будь то стек EFK, Loki, нативное предложение облачного провайдера или специализированный оператор, такой как Logging operator.

Здоровье сообщества и управление проектом

Это раздел, где у меня самый очевидный конфликт интересов, поэтому я дам говорить данным, а не буду редакторствовать.

Я включаю Patroni в приведённый ниже график не как прямого конкурента в пространстве операторов, а как ориентир для более широкого распространения PostgreSQL. Patroni — доминирующее HA-решение для PostgreSQL в традиционных Linux-окружениях и обладает значительным собственным сообществом. То, что CloudNativePG приближается к нему по числу звёзд и пересекает эту отметку, даёт представление о набранном импульсе движения cloud-native Postgres, за пределами более узкой категории операторов. Рост звёзд CloudNativePG полностью органический: никаких кампаний по накрутке звёзд, никакого искусственного усиления.

График истории звёзд GitHub, сравнивающий Patroni, CloudNativePG и Crunchy PGO

Источник: star-history.com

В таблице ниже — сигналы, измеренные за 18 месяцев к маю 2026 года.

Сигнал PGO (CrunchyData) CloudNativePG

Звёзды GitHub (основной репозиторий)

4.4k

8.6k (~10k по всей организации)

Всего коммитов

4 418

4 662 (более молодой проект)

Темп коммитов (среднее за всё время)

~480/год

~745/год

Темп коммитов (последние 3 года)

~235/год

~894/год

Открытые pull request’ы

~18

~174

Контрибьюторы

внутри вендора

200+ из нескольких организаций

GA-релизы (последние 18 месяцев)

~4 (текущая ветка)

~18 (стабильный ритм)

Наибольший разрыв между релизами (последние 18 месяцев)

8 месяцев (март–ноябрь 2025)

без разрывов (ритм 6–8 недель)

Публичное управление проектом

нет

да (инкубация в ожидании)

Публичный roadmap

нет

ROADMAP.md

OpenSSF Best Practices Baseline

нет

да

SECURITY-INSIGHTS.yml

нет

да

Оценка угроз (threat assessment)

нет

да

ADOPTERS.md

нет

да

Восьмимесячный разрыв в истории релизов PGO (с марта по ноябрь 2025 года) выделяется в данных. Отражает ли это осознанную фазу консолидации или нечто более структурное — я честно не знаю. Что я могу сказать: именно сочетание такого темпа, приобретения Snowflake и отсутствия публичного управления проектом чаще всего поднимают команды, когда спрашивают меня о своих вариантах.

Я также буду откровенен относительно стороны CloudNativePG в этой таблице. 174 открытых pull request’а — это большое число, и оно отражает реальную проблему: проект растёт быстрее, чем наша текущая способность рецензировать и вливать изменения. Часть этого роста объясняется всплеском вклада, сгенерированного ИИ, — паттерн, который мы наблюдаем во всей open-source экосистеме. Наша политика по ИИ однозначна: человек-контрибьютор несёт полную ответственность за всё, что он отправляет, мейнтейнеры могут закрывать низкокачественные PR, сгенерированные ИИ, без подробной критики, и мы ценим один вдумчиво проработанный вклад выше десяти поверхностных. Помимо этого, мы находимся в переходной фазе, активно сокращая технический долг в трёх областях, которые сейчас потребляют большую часть нашего когнитивного бюджета: поддержка образов расширений (где работа почти завершена), миграция со встроенной в ядро интеграции Barman Cloud на плагинную модель (тоже близится к завершению) и рефакторинг набора end-to-end тестов для работы с плагинами CNPG-I. Как только эти направления будут завершены, поверхность рецензирования заметно сузится, а бэклог должен последовать за ней.

CloudNativePG — проект CNCF Sandbox, в настоящее время стоящий в очереди на инкубацию, с метриками здоровья, публично доступными на дашборде LFX Insights. У основного репозитория 8,6k звёзд; по всем репозиториям GitHub-организации CloudNativePG суммарно набирается почти 10 000. Большая часть разработки по-прежнему ведётся EDB, что вполне ожидаемо на этой стадии зрелости в CNCF. Инкубация — следующая веха проекта, и главное требование к ней — продемонстрировать широкое продакшн-внедрение, о чём я не беспокоюсь, учитывая насыщенность файла ADOPTERS.md и такие доклады, как тот, что я сделал на KubeCon вместе с Laurent Parodi из HSBC. Graduation — третий шаг, где многоорганизационный вклад становится формальным критерием, и это работа, которая предстоит после того, как мы дойдём до инкубации (надеюсь). Модель управления, roadmap и политика безопасности — всё публично. В число адоптеров входят IBM, Google Cloud, Microsoft Azure, Tesla, GEICO Tech, Novo Nordisk и Mirakl (8 ТБ, 300+ кластеров) — среди прочих, перечисленных в ADOPTERS.md.

Прозрачность в области безопасности также была осознанным фокусом. Open Source Security Foundation (OpenSSF) стала ключевым партнёром в этой работе. CloudNativePG соответствует OpenSSF Best Practices Baseline, а на OpenSSF Security Slam 2026, прошедшем на KubeCon + CloudNativeCon Europe 2026 в Амстердаме, CloudNativePG стал одним из всего трёх проектов, заработавших все пять доступных бейджей (Cleaner, Chronicler, Inspector, Mechanizer и Defender). Результатом работы стали файл SECURITY-INSIGHTS.yml и оценка угроз Gemara для проекта, среди прочих итогов. Оба напрямую релевантны для организаций, работающих в рамках EU Cyber Resilience Act или готовящихся к нему, — этот акт требует от производителей ПО демонстрировать должную осмотрительность в вопросах безопасности на протяжении всего жизненного цикла продукта. Наличие этих артефактов у проекта, являющегося open-source сообществом, — не данность, и оно отражает то долгосрочное мышление, которое вкладывается в сопровождение CloudNativePG.

Мой честный вывод

Crunchy Data была пионером и построила нечто настоящее. Я испытываю к этому искреннее уважение. Но ландшафт 2026 года выглядит иначе, чем в 2017-м: Kubernetes — зрелый control plane, паттерн оператора хорошо изучен, и, на мой взгляд, компромиссы запуска параллельной распределённой системы внутри подов вашей базы данных весят сегодня тяжелее, чем тогда. CloudNativePG с самого начала проектировался, чтобы использовать то, что Kubernetes действительно предлагает, и я считаю, что это решение видно во всём — от архитектуры до размера образа и модели резервного копирования.

Если вы оцениваете операторы PostgreSQL сегодня и ваши главные заботы — долгосрочная архитектурная состоятельность, открытое управление проектом и сообщество с видимым импульсом, то, я думаю, представленные здесь данные стоит внимательно обдумать. Это моё мнение, и я его придерживаюсь, зная, что оно не нейтрально. Оно и не может быть таким, исходя от мейнтейнера и основателя проекта (не подумай мы иначе с самого начала, никакого CloudNativePG сейчас бы не было).

В конечном счёте выбор за вами. Мой честный совет, с признанной предвзятостью, — попробуйте оба и решите, что лучше подходит вашей команде, вашей нагрузке и вашей организации. Именно так и принимаются хорошие инженерные решения.

© 2026 meganuke