Комментарии 17
Можно сэкономить: 2-х нодовый patroni, consul, fast DNS, walg, minio. С мониторингом конечно придется больше заморочиться
Ужас. Даже не знаю с чего начать коментировать.
При синхронной репликации Latency сети напрямую влияет на скорость транзакций: каждый Commit ждет подтверждения от реплики. Нужно заранее понимать, какая задержка допустима, и выбирать между синхронной и асинхронной репликацией осознанно
Ну и чего делать будете если нужна именно синхронная реплика для отказоустойчивости, а отлик не устраивает? А при более-менее серьезной нагрузке и нахождении её в другом ЦОДе он скорей всего не устроит, уж поверьте.
Этап 3. Отказоустойчивость
Что делаем на этом этапе:
настраиваем Streaming Replication между мастером и репликой;
разворачиваем систему автоматического Failover: Patroni, repmgr или аналог;
Ничего не понял... какой вы там Streaming Replication руками настраиваете, если вы следом ставите patroni/repmgr? Это вообще-то их прямая обязанность. Вообще, на моём опыте, патрони и уже настроеные руками кластера "подцеплял" успешно при запуске службы (без дт бекендов пг), но тут описан сценарий первоначального запуска. Тут возникают сомнения что автор вообще понимает что пишет.
Split-brain — ситуация, когда два узла одновременно считают себя мастером и принимают записи. Как это происходит: сеть между ЦОДами прерывается, каждая сторона считает, что другая недоступна. Patroni на каждой стороне решает: «Мастер умер, я беру на себя». Теперь у вас два мастера, и приложения пишут в оба.
ЧЕГО-ЧЕГО? Это каким образом патрони может так решить? Дайте хоть один пример: статью, пост, issue мож на гитхабе есть где такое у кого-то возникло? Патрони никогда не запромоутит реплику при обрыве связи с кластером и DCS, ни автоматически ни руками ты этого не сделаешь. Даже при опции failsafe_mode: true, патрони максимум оставит ТЕКУЩИЙ мастер работать. На этом моменте уже точно понятно что у автора околонулевой опыт реальной эксплуатации и траблшутинга кластеров с patroni.
настраиваем регулярные полные бэкапы через pg_basebackup;
автоматизируем все через pgBackRest или Barman;
Опять же, если вы использует barman/pgbackrest и прочее, что вы там с pg_basebackup "настраиваете" ручками? barman под капотом сам вызывает его когда надо.
настраиваем механизм переключения клиентов: VIP (виртуальный IP), DNS-based Failover или интеграция с Load Balancer;
Это всё хорошо, но простой способ не упомянут: прописывание через запятую бекендов в connection string jbdc драйвера (он давно такое умеет). Сервисы обеспечивающие VIP это, к сожалению, ещё одна точка отказа.
Бэкап базы в 500 ГБ восстанавливается несколько часов.
Как категорично, скорость сетевых интерфейсов, дисков и прочие факторы в расчет не берем, ага. Если я скажу что я базу 10ТБ восстанавливал за 4 часа, не поверите?
pgAudit позволяет логировать все операции с данными: SELECT, INSERT, UPDATE, DELETE
Это позволяет родной для pg параметр log_statement = 'mod'. pgAudit для куда более сложных вещей.
Полезность статьи со знаком минус.
Почему сразу "ужас"? Но в любом случае, спасибо за комментарий. Я постараюсь на все ваши вопросы дать ответ.
Замечания по делу. Цель статьи — показать декомпозицию трудозатрат, а не пошаговую инструкцию, но понимаю, что некоторые моменты требуют уточнений. Про split-brain — подправлю текст. Остальное возьму на доработку. Буду рад, если проревьюите!
1 По синхронной репликации и latency
Хороший комментарий. В статье действительно не раскрыты конкретные решения. На практике есть несколько вариантов:
Quorum-режим (
synchronous_mode: quorumв Patroni) — при 3 репликах достаточно подтверждения от любых 2, а не от конкретной. Снижает worst-case latency.remote_writeвместоon— мастер ждёт только записи WAL в OS-буфер реплики, без fsync. Я эту реализацию не поднимал, тк мне не нужно это, но пишут Crunchy Data : "The master waits only until the standby has received the WAL record and written it to the operating system" — даёт 30-40% снижения latency.Гибридный режим на уровне приложения — критичные транзакции с
SET LOCAL synchronous_commit = on, остальные async.
Если бизнес требует RPO=0, но latency критична — это конфликт требований, который решается на уровне продукта, а не инфраструктуры. Но техническую часть в статье стоило раскрыть подробнее, согласен.
2 По настройке Streaming Replication «руками» перед Patroni
Тут не правильно сформулировал мысль я. Вы правы Patroni действительно сам настраивает репликацию через bootstrap-конфигурацию:
Он управляет слотами, инициализирует реплики. Ручная настройка репликации до Patroni нужна только при миграции с существующего кластера — но это edge case, а не базовый сценарий. Переформулирую позже в статье.
3 По split-brain
Тут увлекся и прописал про свой частный случай. Это не являтеся правильной работой
Чтобы точнее быть в доках есть:
"The node is allowed to run Postgres as the primary only if it can update the leader lock in DCS. In case the update of the leader lock fails, Postgres is immediately demoted and started as read-only."
И дальше:
"In the case of DCS 'outage' the existing primary connects to all members presented in the /failsafe key via the POST /failsafe REST API and may continue to run as the primary if all replicas acknowledge it. If one of the members doesn't respond, the primary is demoted."
То есть мастер демотируется до того, как реплика успеет промоутиться. Split-brain в описанном сценарии невозможен при правильной конфигурации. Вы правы, сценарий в статье некорректен. Patroni по дизайну защищён от такого split-brain — мастер демотируется до того, как реплика успеет промоутиться. Описанная ситуация возможна только при багах в Patroni или ручном обходе системы., чем на реальное поведение Patroni 3.x/4.x.
4 По pg_basebackup и pgBackRest/Barman
Да, смешал два подхода. pgBackRest — это самостоятельная реализация на C, не обёртка над pg_basebackup. Barman использует pg_basebackup под капотом, а pgBackRest — нет. Исправлю.
5 По JDBC failover
Да, это сильно проще реализация. Это хорошо, что напомнили, про простый и действенные инструменты
Из документации PostgreSQL JDBC:
"Connection Fail-over: To support simple connection fail-over it is possible to define multiple endpoints (host and port pairs) in the connection url separated by commas."
jdbc:postgresql://node1,node2,node3/db?targetServerType=primary Никаких VIP, никаких дополнительных точек отказа. Для Java-приложений — отличный вариант
6 По времени восстановления 500 ГБ
Формулировка «несколько часов» слишком условная без учета окружения. Pure Storage в тестах может показать с pgBackRest 38 ТБ/час на параллельном восстановлении — это ~1-2 минуты для 500 ГБ. В статье эта информация избыточна, но понимаю, что важна
«Несколько часов» — это worst case на HDD + single-threaded + 1 Gbps. На NVMe + pgBackRest parallel — совсем другие цифры. 10 ТБ за 4 часа — вполне реальный сценарий при правильной настройке. Но понимаю, что нужно иметь опыт по восстановлению, чтобы в проде все починить за 4 часа. Вы молодец!
7 По pgAudit vs log_statement
В тексте эта часть упрощена. Доках pgAudit:
Basic statement logging can be provided by the standard logging facility with log_statement = all. This is acceptable for monitoring and other usages but does not provide the level of detail generally required for an audit."
log_statement='mod' — для операционного мониторинга. pgAudit — для compliance: object-level auditing, структурированный формат с AUDIT: prefix, автоматическая редакция паролей в CREATE USER. Разные инструменты для разных задач. Дополню раздел.
Отдельно отвечу вам, замечания ваши по делу, но в большей степени относятся, если бы статья была как полноценная инструкция к действию "как поднять СУБД руками". По формату статьи - приведены инструменты, которые могут быть задействованы по разному или вообще не использоваться. Это мой опыт.
Про split-brain - подправлю текст.
По прочим комментариям, я возьму на доработку в рамках отдельной статьи. Буду рад если её также проревъюите!
Можно добиться split brain с patroni. Чтобы было более правдоподобно, представим:
Сервис postgres в автозапуске и на хосте поменяли ip. После старта сервера patroni сразу падает, а postgres успешно стартует и приложения успешно подключаются по dns к СУБД
настраиваем ключевые параметры в postgresql.conf: shared_buffers, effective_cache_size, work_mem, max_connections, параметры WAL для репликации;
На мой взгляд, всё, что можно конфигурировать через ALTER SYSTEM SET, следует так и конфигурировать. Причем из git через CI/CD.
Ну и настройка - это еще и установка расширений, некоторые из которых изначально доступны только в исходниках. Поэтому опять предпочитаю в git разместить сборку DEB/RPM, если нет таких готовых, а через CI/CD обеспечить сборку скрипта для установки расширений и их зависимостей.
Даже на одном кластере из трех хостов такой подход заметно снижает трудоёмкость.
Причем из git через CI/CD.
И через подпись коммита с помощью PGP кворумом из доверенного количества аудиторов )
Когда у Вас будет даже не сотни, а всего десятки серверов с PostgreSQL, каждый из которых конфигурировался вручную, и не сможете найти концы, кто, когда и зачем что-то изменял, тогда поймёте, о чем я пишу.
Alter system это чтобы вместе с бэкапом конфигурации восстанавливалась?
В нем 85% берет на себя провайдер
У меня есть каверзные вопросы в этом плане - что входит в 85%? Где это зафиксировано?
Давайте придумаем какой-то искусственный кейс.
Например я развернул HA кластер в облаке. А потом начал в нем очень интенсивно апдейтить строки. С точки зрения неискушенного пользователя - количество данных не увеличивается. С точки зрения postgres - появляется огромное количество WAL. Что может привести, например:
к окончанию места на диске под WAL
к тому, что WAL не успевает архивироваться или выгружаться в S3 (если такое есть)
к тому, что реплики отстают
к тому, что невозможно сделать консистентный фулл-бэкап, потому что пока вы копируете WAL - появляются новые WAL
С точки зрения пользователя он делает легитимные операции с БД - апдейтит строку в таблице из одной строки. Да, часто, но почему бы и нет?
С точки зрения инфраструктуры и репликации постргеса - такие действия приводят к реальным проблемам.
Так вот, кто получает алерты, что, например, WAL не успевают реплицироваться? И как решаются такие ситуации в целом? Кластер ломается потому что место кончилось? Ваши инженеры бегут добавляют место под WAL? Уведомляете клиента что у него уже сломалось? Или что у него вот-вот сломается потому что он активно пишет? А может вы запрещаете делать асинхронные кластера, чтобы всегда была синхронная репликация, и WAL точно доезжали? Начинаете тротлить запросы? А должен ли пользователь Managed Postgres вообще знать что-то про WAL?
Я уже молчу про классику вроде "я купил тут самый жирный вариант инсталляции, но у меня запрос все равно работает медленно, наверное у вас что-то не так с ..." и далее на выбор: инстансом, с дисками, с iops, с сетью, плохая версия посгреса, вы оверселите ... Погружаетесь в запрос, или просто даете ссылку на свой мониторинг, пусть он ему верит?
Про «85%» — да, это упрощение для статьи. В реальности граница размыта. Есть вещи, которые однозначно на стороне платформы: установка, патчи, failover, инфраструктурный мониторинг. А есть зона «зависит» — ваш случай с WAL как раз оттуда.
По вашему кейсу с UPDATE и WAL.
Managed тут не значит магия. Платформа должна увидеть рост WAL и отставание реплик раньше падения, поднять алерт, дать рекомендации (увеличить диск, поменять retention, посмотреть на паттерн).
Но решить за клиента «это нормальная бизнес-логика или баг в коде» — не может. Троттлить запись автоматически опасно, можем сломать процесс. Молча доводить до падения — тоже плохо.
Получается совместная работа: мы видим метрики и говорим «проблема здесь», клиент решает «это норма, давайте масштабируем» или «да, баг у нас, фиксим».
По «жирный инстанс, но медленно».
Согласен, просто «смотрите метрики» недостаточно. Минимум — разобрать, где узкое место: в запросе/индексах или в железе. Если в запросе — показать план, explain, дать рекомендации. Если в инфраструктуре — объяснить конкретно что (IOPS, CPU wait, сеть).
DBaaS не убирает необходимость понимать Postgres. Он убирает рутину (патчи, бэкапы, failover) и берёт первую линию диагностики. Сложные кейсы всё равно требуют диалога, иначе это просто аренда железа с Postgres сверху.
Ну рутину допустим убирает установка cnpg operator, одной строкой
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.28/releases/cnpg-1.28.0.yamlИ немного подкручпнный мониторинг (он там есть, довольно расширяемый, только по умолчанию все довольно убого настроено)
И получаем бОльшую часть того, что вы описали, где-то чуть больше, где-то чуть меньше.
Правда там начинаются другие проблемы. Если с kubernetes на "вы", то все может быть сложно, непонятно. И самое страшное - непонятно что делать, если сломалось. Но так можно про что угодно сказать.
Согласен, что хорошо бы иметь для подстраховки людей, которым точно понятно что делать, когда вам уже ничего непонятно. И наверное как раз за это стоит платить.
Собственно самое интересное начинается с момента, когда ломается то, что вроде бы должно было не ломаться.
Информация
- Сайт
- tech.vk.com
- Дата регистрации
- Численность
- 1 001–5 000 человек
- Местоположение
- Россия
- Представитель
- Евгений Левашов
Мультизональный PostgreSQL своими руками: декомпозиция трудозатрат