Ketika proses archive_command pada PostgreSQL gagal, proses archiver internal tidak akan menghapus atau mendaur ulang berkas WAL di direktori pg_wal. Segmen WAL akan terus menumpuk hingga kapasitas penyimpanan habis. Saat disk 100% penuh, PostgreSQL langsung melakukan panic shutdown untuk mencegah korupsi data, memicu downtime tak terencana.
Penyebab Utama dan Anatomi Disk Bloat pada pg_wal
PostgreSQL mempertahankan berkas WAL sampai segmen tersebut sukses diarsipkan oleh proses eksternal. Apabila perintah keluar dengan status non-zero (gagal), PostgreSQL akan terus mencoba ulang segmen yang sama. Penyebab umum mencakup:
- Kegagalan autentikasi atau token expired pada object storage (S3, GCS).
- Limitasi bandwidth jaringan atau latensi tinggi ke storage target.
- Kesalahan konfigurasi CLI tool seperti salah path biner atau variabel environment tidak terbaca.
- Kapasitas bucket object storage penuh atau terkena rate limit API.
Konfigurasi WAL-G untuk Archiving Cepat
WAL-G adalah tool archiving modern berbasis Golang yang mendukung kompresi paralel (lz4, zstd) dan upload langsung ke object storage. Contoh konfigurasi pada postgresql.conf:
wal_level = replica
archive_mode = on
archive_timeout = 60
archive_command = '/usr/local/bin/wal-g wal-push %p'WAL-G memerlukan variabel environment storage (misalnya WALG_S3_PREFIX, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) yang harus diekspos ke environment proses PostgreSQL via systemd drop-in file atau wrapper script.
Observability: Monitoring Lag Segmen WAL via Prometheus
Metrik utama kegagalan archiving dapat dipantau langsung dari system catalog PostgreSQL pg_stat_archiver. Gunakan prometheus-community/postgres-exporter untuk mengekspos metrik ini.
Kueri Custom pg_stat_archiver untuk postgres_exporter
Tambahkan file kueri kustom queries.yaml pada postgres_exporter:
pg_stat_archiver:
query: "SELECT archived_count, failed_count, (SELECT count(*) FROM pg_ls_waldir()) AS current_wal_segments, CAST(EXTRACT(EPOCH FROM (now() - last_failed_time)) AS INT) AS seconds_since_last_fail FROM pg_stat_archiver;"
metrics:
- archived_count:
usage: "COUNTER"
description: "Total WAL segments successfully archived"
- failed_count:
usage: "COUNTER"
description: "Total WAL segments failed to archive"
- current_wal_segments:
usage: "GAUGE"
description: "Total WAL segments currently in pg_wal"
- seconds_since_last_fail:
usage: "GAUGE"
description: "Time elapsed since last archive failure"Alerting Rules di Prometheus Alertmanager
Buat ambang batas kritis agar tim dapat mengambil tindakan sebelum disk terisi penuh:
groups:
- name: postgres_wal_archive_alerts
rules:
- alert: PostgresWALArchivingFailing
expr: increase(pg_stat_archiver_failed_count[5m]) > 3
for: 2m
labels:
severity: critical
annotations:
summary: "PostgreSQL WAL Archiving is failing"
description: "Database instance {{ $labels.instance }} failed to archive WAL segments multiple times in the last 5 minutes."
- alert: PostgresWALDiskExhaustionRisk
expr: pg_stat_archiver_current_wal_segments > 200
for: 5m
labels:
severity: critical
annotations:
summary: "High number of pending WAL segments in pg_wal"
description: "Instance {{ $labels.instance }} has {{ $value }} segments pending in pg_wal, approaching disk limit."Graceful Auto-Rollback dan Circuit Breaker Pattern
Ketika sistem monitoring mendeteksi penumpukan WAL yang berisiko mematikan klaster database, langkah operasional darurat harus dieksekusi secara otomatis atau semi-otomatis melalui script monitoring lokal.
Peringatan Keamanan Data: Mengabaikan kegagalan archiving mengorbankan titik Point-in-Time Recovery (PITR). Pendekatan ini adalah trade-off demi mencegah downtime total database produksi.
Implementasi Wrapper Script Circuit-Breaker
Gunakan script wrapper sebagai perantara archive_command. Script ini akan fallback ke mode discard (exit code 0) hanya jika disk lokal berada di ambang batas ekstrim (>90%):
#!/usr/bin/env bash
set -euo pipefail
WAL_FILE="$1"
THRESHOLD=90
# Eksekusi WAL-G push
if /usr/local/bin/wal-g wal-push "$WAL_FILE"; then
exit 0
fi
# Jika WAL-G gagal, cek penggunaan partisi disk pg_wal
USAGE=$(df --output=pcent /var/lib/postgresql/data/pg_wal | tr -dc '0-9')
if [ "$USAGE" -ge "$THRESHOLD" ]; then
logger -t postgres-archiver -p user.emerg "CRITICAL: Disk full ($USAGE%). Skipping WAL $WAL_FILE to prevent DB crash. PITR gap introduced!"
# Keluar dengan 0 agar PostgreSQL menganggap file terarsip dan mendaur ulangnya
exit 0
else
logger -t postgres-archiver -p user.err "ERROR: wal-g failed for $WAL_FILE. Disk at $USAGE%. Retrying later."
exit 1
fiUbah konfigurasi postgresql.conf untuk memanggil wrapper tersebut:
archive_command = '/opt/scripts/wal_circuit_breaker.sh %p'Jalankan SELECT pg_reload_conf(); untuk menerapkan perubahan konfigurasi tanpa restart database.
Verifikasi Backup Terjadwal untuk Mencegah Replikasi Macet
Archiving yang gagal sering menyebabkan WAL-G tidak dapat membuat basebackup yang konsisten atau menyebabkan standby database lag karena perbedaan LSN (Log Sequence Number). Lakukan verifikasi integritas backup secara berkala:
- Otomatisasi Pengecekan Backup: Jalankan cron job untuk memeriksa manifest backup WAL-G:
/usr/local/bin/wal-g backup-list --detail --json - Dry-Run Restore: Buat worker ephemeral (container atau VM terpisah) setiap minggu untuk menguji proses restore menggunakan
wal-g backup-fetchdan menjalankan WAL replay hingga titik akhir. - Validasi WAL Hole: Periksa apakah ada segment yang terlewat dalam bucket menggunakan fitur verifikasi WAL bawaan WAL-G:
Perintah ini mendeteksi apakah segmen kontinuitas terputus yang berpotensi menggagalkan crash recovery pada replica./usr/local/bin/wal-g wal-verify integrity
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!