Где-то в ноябре ко мне пришёл запрос на ревью: «Мы подняли постгрес в k8s, всё работает, но иногда падает - помоги разобраться». Я открыл конфиг - ни PodDisruptionBudget, ни anti-affinity, ни нормального бэкапа. Только StatefulSet и PVC на NFS. Это не исключение: большинство команд, запускающих PostgreSQL в Kubernetes, делают это без понимания, что именно могут потерять.
Эта статья - не про «k8s плохой». Это про честный разбор: когда stateful БД в оркестраторе контейнеров создаёт больше рисков, чем пользы, а когда - оправдана.
Что такое stateful-нагрузка в Kubernetes и почему с БД сложнее
Чем StatefulSet отличается от Deployment
Kubernetes строился вокруг идеи stateless-приложений - тех, где каждый под взаимозаменяем. Для баз данных это не работает: у каждой реплики PostgreSQL есть своё состояние (WAL, данные на диске), своя роль (primary/standby) и своя идентичность.
StatefulSet решает часть проблемы: он даёт подам стабильные имена (pg-0, pg-1), отдельный PersistentVolumeClaim каждому и предсказуемый порядок запуска. Но StatefulSet - это примитив. Он не знает, кто из подов primary, не переключает роли при падении ноды и не проверяет согласованность WAL перед promote.
Именно поэтому для production PostgreSQL в k8s нужен оператор - дополнительный слой логики поверх Kubernetes API.
Три вещи, которые K8s не даёт БД из коробки
Kubernetes, даже с правильно настроенным StatefulSet, не управляет тремя критичными для PostgreSQL вещами:
- Автоматический failover - выбор нового primary при падении текущего, без split-brain.
- Управление WAL при переключении - старый primary должен прекратить запись до promote реплики, иначе возможна потеря данных.
- Расширение PVC - изменение размера тома в работающем StatefulSet требует ручных операций и потенциально - удаления StatefulSet с
--cascade=orphan.
Всё это - зона ответственности Patroni, CloudNativePG, Zalando-оператора или DBA. Если в команде этого нет, начинаются проблемы.
Пять сценариев, когда PostgreSQL в Kubernetes - плохая идея
Ниже - конкретные ситуации, в которых запуск PostgreSQL в k8s создаёт неоправданные риски. Это не запрет: это контрольные вопросы, которые стоит задать себе до деплоя.
Нет выделенного DBA или SRE с опытом stateful
Без человека, который понимает Patroni, PVC-резайз и CSI-драйверы, PostgreSQL в k8s - это риск потери данных, а не удобство. Типичный сценарий: оператор автоматически делает promote реплики, та пишет данные, старый primary поднимается - и возникает split-brain.
Сам Yandex Cloud в документации прямо пишет: «Мы не рекомендуем запускать stateful-сервисы с постоянными томами в Kubernetes. Для работы с базами данных используйте управляемые базы данных Yandex Cloud». Это не маркетинг - это честная оценка операционной сложности.
Если в команде нет человека, для которого Patroni и операторы PostgreSQL - родная тема, даже в нерабочее время, - managed-сервис дешевле по совокупной стоимости.
Хранилище не даёт нужных IOPS
PostgreSQL пишет WAL синхронно (по умолчанию fsync=on). Каждая транзакция ждёт подтверждения записи на диск. Если CSI-бэкенд - сетевой NFS или медленный сетевой диск, fsync-задержка убивает производительность.
Блочное хранилище с ReadWriteOnce (RWO) - единственный надёжный вариант для PostgreSQL в k8s. RWO-диск подключается к одному поду одновременно - это означает, что реплики не могут читать с общего тома primary. Каждая реплика должна иметь свой PVC с потоковой репликацией.
Проверьте StorageClass перед деплоем:
kubectl get storageclass
# Смотри PROVISIONER и RECLAIMPOLICY
Если провайдер - nfs.csi.k8s.io или подобный, PostgreSQL там будет страдать.
Команда меньше пяти человек без K8s-эксперта
Это, пожалуй, самый частый антипаттерн. Стартап или небольшая продуктовая команда видит Kubernetes как «современный способ деплоя» и запускает туда всё - включая PostgreSQL.
Проблема не в K8s, а в операционных расходах: настройка PodDisruptionBudget, мониторинг лага репликации, обновление оператора, тестирование failover - это полноценная работа. Managed-сервис снимает её с команды и даёт время на продукт.
На российском рынке доступны Yandex Managed Service for PostgreSQL и VK Cloud Managed PostgreSQL. Оба поддерживают автоматический failover, бэкапы и мониторинг из коробки.
RPO/RTO лучше 1 минуты - без проверенного DR-плана
Многие команды верят, что оператор «сам разберётся» при падении ноды. Это ошибка.
Failover CloudNativePG и Patroni требует обнаружения падения (обычно 30–60 секунд через liveness/readiness probe), проверки состояния WAL, promote реплики и перенаправления трафика через PgBouncer или сервисный эндпойнт. Итого - минуты, а не секунды при неудачном стечении обстоятельств.
Если RPO < 1 минуты и RTO < 2 минут - критичные бизнес-требования, необходимы: задокументированный runbook, регулярные учения (chaos testing), синхронная репликация и независимое тестирование DR не реже раза в квартал.
Без этого цифры RPO/RTO - иллюзия.
OLAP / тяжёлая аналитика
K8s оптимизирован для многих небольших рабочих нагрузок, которые можно быстро запускать и останавливать. OLAP - ровно наоборот: долгие тяжёлые запросы, высокий IOPS, большие объёмы хранилища.
Для аналитики на PostgreSQL в k8s придётся выделять ноды с тегами (nodeSelector/taints), настраивать отдельный StorageClass с высоким IOPS и изолировать нагрузку от OLTP. Это реально, но сложно. Проще взять ClickHouse или Greenplum в managed-варианте.
Когда PostgreSQL в Kubernetes всё-таки оправдан
Не хочу оставить впечатление, что PostgreSQL в k8s - всегда плохо. Это инструмент, и у него есть правильные сценарии применения.
Dev, staging, CI/CD-окружения
Здесь - отлично. Быстрый spin-up через Helm или оператор, изоляция через namespace, лёгкое удаление. Потеря данных в dev не критична, а унификация инфраструктуры (всё в одном кластере) упрощает работу разработчиков.
Крупная платформа с DBaaS-командой
Авито запускает stateful-базы в Kubernetes. Zalando переехал туда несколько лет назад и написал собственный оператор. Но у обоих - выделенные платформенные команды, которые это сопровождают.
Если у вас есть 3+ инженера, для которых stateful K8s - основная специализация, PostgreSQL в k8s - разумный выбор. Без этого - нет.
Единая инфраструктура без managed-сервисов
Если команда работает только в собственном on-premise кластере или в регионе без нормальных managed-сервисов, PostgreSQL через оператор - оправданный путь. Лучший выбор по состоянию на 2026 год: CloudNativePG (CNCF Sandbox-проект) или Percona Operator for PostgreSQL.
Как снизить риски, если решили запускать
Выбор оператора: CloudNativePG, Zalando, Percona
Три основных оператора отличаются архитектурой:
| Оператор | HA-механизм | Особенность | Когда выбрать |
|---|---|---|---|
| CloudNativePG | Собственный failover, без StatefulSets | CNCF Sandbox, активное развитие | Новые проекты, cloud-native подход |
| Zalando postgres-operator | Patroni + StatefulSet | Зрелый, проверен в production | Знакомы с Patroni |
| Percona Operator | Patroni + StatefulSet | Совместим с Percona PMM | Нужен мониторинг из коробки |
| KubeDB | Собственный | Платная поддержка | Корпоративный сектор |
Хранилище: только block storage, отдельный StorageClass
Правило простое: PostgreSQL - только на блочном хранилище с RWO. Проверь, что StorageClass использует SSD, а не HDD. Настрой отдельный StorageClass с reclaimPolicy: Retain - тогда PVC не удалится при случайном удалении пода.
Если кластер в Yandex Cloud - используй yc-network-ssd как минимальный вариант.
Обязательный чеклист перед production
Без этих пунктов PostgreSQL в k8s - не production:
- PodDisruptionBudget - minAvailable: 1 для primary, чтобы дренаж ноды не убил всё сразу.
- Pod Anti-Affinity - разноси primary и реплики на разные ноды и зоны доступности.
- Resource limits - обязательно memory limit для PostgreSQL-контейнера, иначе OOM Killer убьёт под в самый неподходящий момент.
- Readiness probe - настрой корректно: PostgreSQL, принимающий соединения, но не готовый к записи, не должен получать трафик.
- Бэкап в S3 - pgBackRest или Barman, минимум ежедневный full + WAL-архивирование. Не «когда-нибудь» - сразу.
- Тест восстановления - restore из бэкапа нужно проверять регулярно, не только перед аудитом.
Managed PostgreSQL как альтернатива: считаем честно
TCO: не только цена в месяц
Managed-сервис кажется дороже при поверхностном сравнении цифр. Но TCO (совокупная стоимость владения) включает время инженеров на поддержку, стоимость инцидентов, потенциальную потерю данных и ночные дежурства.
Авторы исследования на simplyblock.io показали, что self-hosted PostgreSQL на EKS vs RDS при учёте операционных затрат сопоставимы или обходятся дороже - зависит от нагрузки и размера команды.
⚠️ Предположительно (точных данных по российскому рынку нет): для команд до 10 человек managed-сервис в Яндекс Облаке или VK Cloud скорее всего дешевле по TCO, чем self-hosted PostgreSQL в k8s с учётом операционных расходов.
Что умеют российские managed-сервисы
Yandex Managed Service for PostgreSQL:
- Автоматический failover без ручного вмешательства
- Резервное копирование с настраиваемым RPO
- Мониторинг через Yandex Monitoring
- Расширение хранилища без даунтайма
- Подключение из Kubernetes-кластера по внутреннему FQDN
VK Cloud Managed PostgreSQL:
- Аналогичный набор managed-функций
- Бэкапы в S3-совместимое объектное хранилище
Точные характеристики и актуальные цены: Yandex Cloud, VK Cloud.
Итоговое дерево решений
Перед тем как добавить PostgreSQL в values.yaml Helm-чарта, задай себе эти вопросы:
Есть ли в команде DBA или SRE с опытом stateful K8s?
├─ Нет → Managed PostgreSQL (Yandex MPG / VK Cloud)
└─ Да
├─ Это dev/staging? → K8s + любой оператор, всё ок
└─ Это production?
├─ Команда < 5 человек? → Managed PostgreSQL
├─ Хранилище --- NFS? → Managed PostgreSQL
├─ RPO < 1 мин без DR-плана? → Managed PostgreSQL
└─ Всё ok → K8s + CloudNativePG/Patroni + чеклист выше
FAQ
Можно ли запускать PostgreSQL в Kubernetes в production?
Да, при условии: есть оператор с HA (CloudNativePG, Patroni), блочное хранилище с RWO, PodDisruptionBudget, настроены anti-affinity, бэкап в S3 и проверен DR-план. Без этих условий - managed-сервис надёжнее.
Какой оператор PostgreSQL для Kubernetes выбрать в 2026?
CloudNativePG - для новых проектов, активно развивается как CNCF Sandbox. Percona Operator и Zalando postgres-operator - для команд с опытом Patroni. Подробное сравнение - в обзоре Palark (декабрь 2025).
Чем StatefulSet отличается от Deployment для PostgreSQL?
StatefulSet гарантирует стабильное имя пода (pg-0) и отдельный PVC. Deployment не гарантирует ни то, ни другое - PostgreSQL в Deployment неприемлем для production.
Что такое PVC и почему важен ReadWriteOnce?
PVC - заявка на хранилище в Kubernetes. ReadWriteOnce (RWO) означает подключение к одному поду. Только RWO совместимо с PostgreSQL в production: несколько подов с доступом к одному тому разрушат данные.
Yandex Managed PostgreSQL или self-hosted в k8s?
Для команд до 10 человек без выделенного DBA - Yandex Managed PostgreSQL. Автоматический failover, бэкапы, мониторинг - из коробки. Self-hosted оправдан при крупной платформе с DBaaS-командой.
Что такое PodDisruptionBudget и зачем он PostgreSQL?
PDB ограничивает количество подов, которые K8s может остановить одновременно при дренаже ноды. Без PDB дренаж узла может убить и primary, и реплики одновременно - database unavailable.
Как делать бэкап PostgreSQL из Kubernetes?
Используй pgBackRest или Barman с WAL-архивированием в S3. Регулярно тестируй restore. pg_dump - только как дополнение, не замена WAL-архивирования.
Источники
Habr / Zalando - «PostgreSQL на K8s в Zalando: два года в бою»
DigitalOcean - «How to Deploy Postgres to a Kubernetes Cluster»
Yandex Cloud - «Хранилище данных в Managed Service for Kubernetes»
Habr / Авито - «Эксплуатация Stateful-приложений в Kubernetes»
VK Cloud Blog - «Организация бэкапа PostgreSQL из Kubernetes в S3»
Habr / Flant - «Обзор операторов PostgreSQL для Kubernetes. Часть 3»
Habr / Arenadata - «Общие подходы к классическому PostgreSQL в Kubernetes»



.svg.webp)





