Почему PostgreSQL падает в Docker Swarm с ошибкой checkpoint

    Развёртывание PostgreSQL в среде Docker Swarm - популярная практика, но иногда она приводит к неожиданным сбоям. Типичная ситуация: база данных объёмом 30 ГБ падает раз в 1-3 месяца с критической ошибкой could not locate a valid checkpoint record. После восстановления (ремонта) БД снова работает стабильно, но цикл повторяется. Рассмотрим, почему это происходит и как избежать проблемы.

    Основная причина: некорректное завершение работы контейнера

    В Docker Swarm оркестратор может перезапускать или перемещать контейнеры между узлами кластера. Если во время записи checkpoint-записи (контрольной точки) происходит внезапная остановка контейнера (из-за нехватки памяти, перезагрузки узла или ошибки сети), файл контрольной точки повреждается. При следующем запуске PostgreSQL не может найти валидный checkpoint и впадает в PANIC.

    Факторы, усугубляющие проблему в Docker Swarm

    • Нестабильное сетевое хранилище (NFS, Ceph): если данные БД размещены на сетевом томе, задержки и разрывы соединения приводят к частичной записи WAL или checkpoint.
    • Нехватка ресурсов контейнера: ограничение CPU или RAM (cgroups) может вызвать принудительное завершение процесса postgres в критический момент.
    • Перемещение сервиса (rescheduling): при сбое узла Swarm запускает контейнер на другом узле. Если том не отмонтирован корректно, данные могут быть повреждены.
    • Неверные настройки shared_buffers и wal_buffers: в контейнере с ограниченной памятью эти параметры должны быть рассчитаны с учётом лимитов.

    Почему на отдельной VM проблема исчезла

    Перенос PostgreSQL на выделенную виртуальную машину решает проблему по нескольким причинам:

    • Стабильный доступ к локальному диску (без сетевых задержек).
    • Гарантированные ресурсы CPU и RAM (без конкуренции с другими контейнерами).
    • Отсутствие перепланирования контейнеров - процесс работает непрерывно.
    • Операционная система сама управляет кэшированием и вводом-выводом, что снижает риск частичной записи.

    Как предотвратить падение PostgreSQL в Docker Swarm

    Если вы не можете отказаться от Docker Swarm, примените следующие меры:

    1. Используйте локальные тома или statefulset

    Размещайте данные БД на локальном диске узла (bind mount) или используйте драйверы томов с поддержкой консистентности (например, Rook/Ceph с fsync).

    2. Настройте ресурсы контейнера

    Выделите контейнеру достаточное количество памяти (не менее 2 ГБ на 30 ГБ данных) и CPU (минимум 1 ядро). Укажите limits и reservations в docker-compose.

    3. Оптимизируйте параметры PostgreSQL

    Увеличьте wal_keep_segments и checkpoint_completion_target, чтобы снизить нагрузку на запись checkpoint. Настройте shared_buffers на 25% от доступной памяти.

    4. Включите fsync и full_page_writes

    Убедитесь, что fsync = on и full_page_writes = on в postgresql.conf. Это гарантирует целостность страниц даже при сбое.

    Диагностика ошибок checkpoint

    Чтобы понять, что именно вызывает повреждение, проверьте:

    • Логи Docker: docker service logs - ищите сообщения OOMKilled или exit code 137.
    • Логи PostgreSQL: PANIC: could not locate a valid checkpoint record - указывает на битый файл в каталоге pg_wal.
    • Мониторинг I/O: используйте iostat или dstat для проверки задержек диска на узле Swarm.

    В вашем случае перенос на отдельную VM - правильное решение, но описанные настройки помогут и в кластерной среде.

    Часто задаваемые вопросы