Выберите продукт

PostgreSQL + S3 + WAL-G: WAL-архивирование и PITR шаг за шагом

Пошаговая настройка резервного копирования PostgreSQL с WAL-G и S3-совместимым хранилищем: непрерывная архивация WAL, регулярные base backup, политика удаления и восстановление до точки во времени (PITR). Разбираем конфиги, команды, проверку и типичные ошибки на VDS.
PostgreSQL + S3 + WAL-G: WAL-архивирование и PITR шаг за шагом

Надежное резервное копирование PostgreSQL с возможностью восстановиться до любой точки во времени (PITR) — базовая гигиена продакшена. Связка PostgreSQL + WAL-G + S3-совместимое object storage закрывает задачу полноценно: регулярные base backup, непрерывное wal archiving и проверяемые сценарии backup / restore. Ниже — практический разбор, ориентированный на эксплуатацию на облачном VDS.

Что и зачем: WAL, WAL-G, S3 и PITR

WAL — журналы предзаписи PostgreSQL. При включенном архивировании каждый завершенный сегмент WAL отправляется в безопасное хранилище. В связке с периодическими полными бэкапами это позволяет восстановить кластер на конкретный момент времени, воспроизведя изменения из WAL. Для краткого обзора терминов и сценариев см. материал про основы PITR и WAL в PostgreSQL.

WAL-G — современный инструмент для холодных/горячих бэкапов PostgreSQL с поддержкой потоковой отправки WAL и хранения в S3-совместимых объектных хранилищах. Он умеет:

  • делать base backup каталога данных;
  • архивировать WAL-сегменты по мере их завершения;
  • управлять политикой хранения (retention, delete before/retain);
  • восстанавливать базу и WAL до нужной точки времени (PITR).

S3-совместимое object storage — недорогое, масштабируемое, географически отказоустойчивое хранилище. В связке с версионированием и политиками жизненного цикла оно хорошо подходит для резервных копий. Альтернативный стек — pgBackRest; сравнить подходы можно в статье pgBackRest: бэкапы и восстановление PostgreSQL.

Итог: base backup + непрерывная отправка WAL в S3 через WAL-G = возможность восстановить PostgreSQL к любой секунде между бэкапами (PITR), минимизируя потерю данных.

Предпосылки и минимальная архитектура

Что нужно для старта:

  • Рабочий экземпляр PostgreSQL (желательно 12+), доступ root и пользователь postgres.
  • Доступ к S3-совместимому object storage: бакет, ключи с минимальными правами (только чтение/запись в нужный префикс; отдельно — право удаления для хоста, который отвечает за ретеншн).
  • Синхронизированное время (chrony/systemd-timesyncd), стабильная сеть на VDS.
  • Достаточно места на диске под workdir и буферы сжатия; CPU для компрессии (lz4/zstd).

Логическая схема:

  • PostgreSQL пишет WAL локально.
  • archive_command вызывает wal-g wal-push, отправляя сегменты в S3.
  • Планировщик (systemd timer/cron) периодически запускает wal-g backup-push для полного бэкапа каталога данных.
  • Политики хранения wal-g delete удаляют устаревшие бэкапы и WAL, оставляя нужное окно для PITR.

Схема WAL-архивирования PostgreSQL в S3 через WAL-G и окно PITR

Установка и базовая структура конфигурации WAL-G

WAL-G поставляется как единый бинарник. Устанавливайте сборку, соответствующую вашей ОС и архитектуре. Бинарник рекомендуется поместить в /usr/local/bin/wal-g и сделать исполняемым. Запускать его будет пользователь postgres.

Конфигурация читается из окружения и/или YAML. Удобно хранить настройки в /etc/wal-g.d/server.yaml с правами 600 и владельцем postgres:postgres.

# /etc/wal-g.d/server.yaml
WALG_S3_PREFIX: s3://your-bucket/pg/prod
AWS_ACCESS_KEY_ID: YOUR_ACCESS_KEY
AWS_SECRET_ACCESS_KEY: YOUR_SECRET_KEY
AWS_REGION: your-region-1
AWS_ENDPOINT: s3.endpoint.internal
S3_FORCE_PATH_STYLE: true
WALG_COMPRESSION_METHOD: zstd
WALG_UPLOAD_CONCURRENCY: 8
WALG_DOWNLOAD_CONCURRENCY: 8
WALG_S3_STORAGE_CLASS: STANDARD
# При необходимости: серверное шифрование на стороне S3
# WALG_S3_SSE: AES256
# Клиентское шифрование PGP (альтернатива SSE)
# WALG_PGP_KEY: ASCII-армированный публичный ключ

Переменные шифрования выбирайте по вашей политике безопасности: SSE в бакете или шифрование на клиенте PGP. Не храните секреты с правами чтения для других пользователей.

Подготовка PostgreSQL к wal archiving

Включим нужные параметры в postgresql.conf и перезапустим сервис:

# postgresql.conf (фрагмент)
wal_level = replica
archive_mode = on
archive_command = 'wal-g wal-push %p'
archive_timeout = 60s
max_wal_senders = 5
wal_compression = on

Пояснения:

  • wal_level=replica — минимальный уровень для архивации и репликации.
  • archive_mode=on включает механизм архивации.
  • archive_command вызывает WAL-G для отправки каждого завершенного сегмента.
  • archive_timeout форсирует завершение сегмента, если мало активности.
  • wal_compression=on уменьшает размер WAL.

Убедитесь, что пользователь postgres видит конфигурацию WAL-G (YAML или переменные окружения). Проще всего положить YAML в /etc/wal-g.d/server.yaml и запускать wal-g от postgres; также можно добавить EnvironmentFile или переменную WALG_CONFIG_FILE в drop-in юнит PostgreSQL.

Первый полный бэкап (base backup)

Сделаем первичный снимок данных. Во время создания бэкапа WAL-G корректно обрабатывает backup start/stop, обеспечивая согласованность.

sudo -u postgres wal-g backup-push /var/lib/postgresql/16/main

Путь к каталогу данных укажите свой. По завершении появится запись в списке бэкапов:

sudo -u postgres wal-g backup-list

Рекомендуется автоматизировать base backup через systemd timers (например, раз в сутки вне пикового окна) с уведомлениями об ошибках. Пример минимальных юнитов:

# /etc/systemd/system/walg-backup.service
[Unit]
Description=WAL-G base backup

[Service]
User=postgres
Environment=WALG_CONFIG_FILE=/etc/wal-g.d/server.yaml
ExecStart=/usr/local/bin/wal-g backup-push /var/lib/postgresql/16/main

# /etc/systemd/system/walg-backup.timer
[Unit]
Description=Daily WAL-G base backup

[Timer]  02:30:00
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now walg-backup.timer
FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Непрерывная архивация WAL

После включения archive_mode и настройки archive_command PostgreSQL будет вызывать wal-g wal-push на каждый завершенный сегмент WAL. Проверить статус можно в журналах Postgres и командами WAL-G (например, сверив наличие новых архивов). Для форсирования ротации WAL выполните:

sudo -u postgres psql -c "SELECT pg_switch_wal();"

Типичные признаки проблемы:

  • в логах Postgres появляются повторяющиеся попытки архивации с ошибкой;
  • локальный каталог pg_wal быстро разрастается — архивирование не работает;
  • в бакете не появляются новые объекты под префиксом WAL.

В таких случаях проверьте права на запуск wal-g, видимость переменных окружения, корректность префикса WALG_S3_PREFIX и доступы к бакету.

Политика хранения: сколько держать бэкапов и WAL

Обычно задают окно восстановления (например, 7–14 дней) и частоту base backup (например, каждый день). Тогда держим 7–14 полных бэкапов и соответствующие WAL между ними. Примеры команд:

# Оставить 7 последних полных бэкапов (и связанные WAL)
sudo -u postgres wal-g delete retain FULL 7 --confirm

# Удалить все, что старше указанной точки, выбрав ближайший полный бэкап до нее
sudo -u postgres wal-g delete before FIND_FULL 2025-11-01T00:00:00Z --confirm

# Ограничить количество хранимых WAL за последние 168 часов (пример)
sudo -u postgres wal-g delete wal --retain 168 --confirm

Команды удаления следует запускать только на «хосте-хозяйственнике» бэкапов, чтобы не пересекались роли. Перед внедрением — протестируйте в непроизводственной среде.

PITR: восстановление до точки во времени

Сценарий проверки (рекомендую репетировать раз в квартал): поднимаем тестовую копию из бэкапа и воспроизводим WAL до нужного момента времени (до или прямо перед инцидентом).

1) Подготовка каталога данных

sudo systemctl stop postgresql
mv /var/lib/postgresql/16/main /var/lib/postgresql/16/main.broken-2025-11-07
sudo -u postgres wal-g backup-fetch /var/lib/postgresql/16/main LATEST
sudo -u postgres touch /var/lib/postgresql/16/main/recovery.signal

2) Настройка параметров восстановления

Добавьте в postgresql.conf параметры restore и цель восстановления:

# postgresql.conf (фрагмент для PITR)
restore_command = 'wal-g wal-fetch "%f" "%p"'
recovery_target_time = '2025-11-07 13:54:00+03'
recovery_target_action = promote
recovery_target_timeline = latest

Вместо времени можно указать recovery_target_lsn или recovery_target_name, если вы ставили именованные точки восстановления.

Терминал с примером recovery: wal-g backup-fetch и восстановление до целевой точки

3) Запуск и контроль

sudo systemctl start postgresql

PostgreSQL подтянет недостающие WAL из S3 и остановится на целевой точке. В логах будет видно момент «promote». Проверьте консистентность бизнес-данных тестовыми запросами.

Для восстановления «до последнего доступного момента» достаточно не указывать recovery_target_time (или поставить latest), а затем выполнить промоут при достижении конца имеющихся WAL.

Проверка бэкапов и регулярные drill-тесты

Бэкап, который никогда не восстанавливали, — это предположение, а не гарантия. Обязательные практики:

  • Раз в N недель выполнять тестовое восстановление в отдельный каталог на отдельном экземпляре VDS.
  • Отдельно проверять способность качать WAL за длительный период (сеть, пропускная способность S3, время восстановления).
  • Следить за логами WAL-G и Postgres: отдельные алерты на ошибки архивации.
  • Автоматизировать backup-list и метрики (возраст последнего base backup, отставание по WAL).

Если в вашей версии WAL-G есть команда верификации (например, backup-verify), используйте ее дополнительно, но финальным критерием все равно остается успешный restore с запуском Postgres.

Оптимизация производительности на VDS

Чтобы бэкапы не мешали продакшен-нагрузке:

  • Компрессия: для CPU-ограниченных VDS используйте lz4; для диско- или сеть-ограниченных — zstd с умеренным уровнем.
  • Параллелизм: WALG_UPLOAD_CONCURRENCY и WALG_DOWNLOAD_CONCURRENCY подбирайте экспериментально (обычно 4–8 потоков хорошо использует S3-мультипарт и канал).
  • Ограничение IO: запускайте бэкапы в непиковые часы, при необходимости используйте cgroups/ionice.
  • Сеть: контролируйте исходящий трафик и лимиты провайдера object storage; при больших базах убедитесь, что окно бэкапа укладывается в ночное.

Безопасность и соответствие

Основные моменты:

  • Минимальные права для ключей S3: доступ только к нужному префиксу, разделите роли «загрузка» и «удаление».
  • Шифрование: включите SSE на бакете или используйте PGP-шифрование на клиенте. Храните приватные ключи отдельно от VDS.
  • Защита секретов: файл /etc/wal-g.d/server.yaml — права 600, владелец postgres. Не пишите секреты в логи и shell history.
  • Версионирование в бакете + политики жизненного цикла для защиты от случайных удалений и оптимизации затрат.

Распространенные ошибки и их диагностика

  • archive_command возвращает код ошибки. Проверьте путь к wal-g в PATH пользователя postgres, права на конфиг и корректность переменных.
  • WAL не уезжают, локальный pg_wal растет. Ошибка в доступах к S3, неверный WALG_S3_PREFIX, сеть или проблемы с DNS. Временно увеличьте max_wal_size, чтобы выиграть время.
  • restore не находит WAL. Проверьте restore_command, указанный префикс, временной диапазон и наличие нужных сегментов между base backup и целевой точкой.
  • Слишком долгое восстановление. Увеличьте параллелизм скачивания, используйте более быстрый алгоритм компрессии, чаще делайте base backup, чтобы сократить длину последовательности WAL.
  • Несогласованные конфиги. Следите, чтобы server.yaml был одинаковым на узлах, участвующих в бэкапе/восстановлении, и версионируйте изменения.

Практические рекомендации эксплуатации

  • Разделяйте префиксы S3 по средам: s3://your-bucket/pg/prod, .../stg, .../dev.
  • Ставьте метки на объекты (tags) для отчетности и ретенции.
  • Для крупных баз используйте инкрементальную стратегию с более частыми base backup и отладьте окна.
  • Фиксируйте версию WAL-G и PostgreSQL в документации, чтобы воспроизводить окружение при DR.
  • Периодически тестируйте восстановления на «холодном» каталоге в отдельном VDS.

Чек-лист внедрения

  • Создан бакет и префикс в S3-совместимом хранилище, ключи с минимальными правами.
  • Установлен wal-g, настроен /etc/wal-g.d/server.yaml, права 600.
  • Включены wal_level=replica, archive_mode=on, задан archive_command.
  • Сделан первичный backup-push, проверен backup-list.
  • Работает отправка WAL, наблюдаются новые объекты в S3.
  • Настроены таймеры base backup и ретеншн (delete retain/delete before).
  • Выполнен тестовый PITR в непроизводственной среде, задокументированы шаги.

Итого

Связка PostgreSQL + WAL-G + S3 дает предсказуемый и масштабируемый пайплайн резервного копирования: быстрые base backup, непрерывное wal archiving и проверяемый PITR. Для эксплуатации на VDS важно уделить внимание компрессии, параллелизму и сетевым лимитам, а также дисциплине тестовых восстановлений. Один раз аккуратно настроив процесс и автоматизировав ретеншн, вы получите устойчивую защиту от потери данных и человеческих ошибок.

Поделиться статьей

Вам будет интересно

systemd-networkd на VDS: пропал интернет после reboot — DHCP, cloud-init и метрики маршрутов OpenAI Статья написана AI (GPT 5)

systemd-networkd на VDS: пропал интернет после reboot — DHCP, cloud-init и метрики маршрутов

Если после reboot на VDS «отвалилась» сеть, чаще всего виноваты cloud-init/netplan, конкурирующие DHCP-клиенты или неверная метрик ...
CPU throttling на VDS в Linux: TDP/thermal лимиты, частоты и квоты cgroups v2 (cpu.max) OpenAI Статья написана AI (GPT 5)

CPU throttling на VDS в Linux: TDP/thermal лимиты, частоты и квоты cgroups v2 (cpu.max)

Если на VDS растёт load average и задержки, а CPU «не на 100%», причина часто в throttling: тепловые/мощностные лимиты, steal time ...
Let’s Encrypt через DNS-01: wildcard, автоматизация продления и безопасные deploy-хуки OpenAI Статья написана AI (GPT 5)

Let’s Encrypt через DNS-01: wildcard, автоматизация продления и безопасные deploy-хуки

DNS-01 удобен для wildcard и закрытых сетей: владение доменом подтверждается TXT-записью в DNS. Разбираем выбор certbot/lego/acme. ...