こんにちは!インフラの現場で毎日システムを見守っていると、ふとこんな悪夢が頭をよぎることはありませんか?
- 「ある日突然、データベースのディスクが吹き飛んだ……」
- 「大規模障害の復旧後、Zabbixのグラフが真っ白になり、過去のトレンドが見れなくなった……」
- 「バージョンアップに失敗し、設定が巻き戻って監視アラートが沈黙した……」
オブザーバビリティ(可観測性)を担うZabbix自身がブラックボックス化し、いざという時にリカバリできない――これは運用者にとって最大の悪夢です。
今回は、Zabbixのバックアップと災害復旧(DR)の神髄を、現場で即座に使える実践的な知見とともに徹底解説します。これをマスターすれば、深夜の障害対応でも冷や汗をかくことなく、圧倒的な安心感を持ってシステムを支えられるようになりますよ。
—
1. Zabbix運用におけるバックアップ対象の全整理
Zabbixのバックアップを語る上で絶対に外してはいけない大原則があります。それは、「設定データ」と「履歴データ」は性質が全く異なるため、別々に戦略を立てる必要があるということです。
Zabbixの心臓部は、以下の4つの要素で構成されています。これら全てを網羅して初めて「完全なバックアップ」と言えます。
+——————————————————-+
| Zabbix サーバー環境 |
| |
| [1. フロントエンド設定ファイル] (/etc/zabbix/web/) |
| [2. カスタムスクリプト] (/usr/lib/zabbix/alertscripts/)
| |
| +————————————————-+ |
| | 3. 設定データベース (MySQL / PostgreSQL) | |
| | – ホスト、アイテム、トリガー、テンプレート | |
| +————————————————-+ |
| +————————————————-+ |
| | 4. 履歴データベース (TimescaleDB / DB内テーブル)| |
| | – 監視メトリクス、トレンド、イベントログ | |
| +————————————————-+ |
+——————————————————-+
1. 設定データベース(Config DB)
- ホスト、アイテム、トリガー、テンプレート、ユーザー権限など、Zabbixの「頭脳」にあたる部分。
- データ量は比較的小さいですが、変更頻度が高く、ここが消えると監視の定義自体が失われます。
2. 履歴データベース(History / Trends DB)
- エージェントから収集したメトリクスやイベントの「足跡」。
- データ量が膨大になるため、MySQL/PostgreSQL単体か、時系列DBに最適化されたTimescaleDBが使われます。バックアップの容量とコストの大部分を占めます。
3. フロントエンド設定ファイル
- `/etc/zabbix/web/zabbix.conf.php` が代表例です。DBへの接続情報やパス塩のソルトが含まれており、これが欠けるとWebUIが動きません。
4. 外部スクリプト・プラグイン
- `/usr/lib/zabbix/alertscripts/`(アラート通知用)や `externalscripts/`(独自ポーリング用)に配置したシェルスクリプトやPythonスクリプト。本体のDBに含まれないため、ファイル単位でのバックアップが必須です。
—
2. 稼働中のデータベースを無停止・整合性を保ったままバックアップする実装
「夜間バッチで止めるから大丈夫」――そんな言い訳は現代の24時間稼働システムでは通用しません。ここでは、PostgreSQL(TimescaleDB環境を想定)を例に、完全無停止(Online)かつデータ不整合を起こさないプロフェッショナルなバックアップスクリプトを授けます。
ポイントは、単なる `pg_dump` ではなく、適切なロック制御と世代管理(ローテーション)を組み込むことです。
!/bin/bash
==============================================================================
Zabbix Database Online Backup Script (PostgreSQL / TimescaleDB)
==============================================================================
set -euo pipefail
— 設定変数 —
DB_NAME=”zabbix”
DB_USER=”zabbix”
BACKUP_DIR=”/backup/zabbix/db”
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7 # 保持日数
バックアップ先ディレクトリの作成
mkdir -p “${BACKUP_DIR}”
echo “[$(date)] Zabbix DB Backup Started: ${DB_NAME}”
1. 設定データのバックアップ(軽量なためスキーマとデータをテキストで取得)
–schema-only / –data-only を分ける手法もありますが、全体をカスタムフォーマット(-Fc)で取得するのが鉄則
pg_dump -U “${DB_USER}” -d “${DB_NAME}” -Fc –no-owner –no-privileges \
> “${BACKUP_DIR}/zabbix_full_${DATE}.dump”
echo “[$(date)] Database dump completed successfully.”
2. 古いバックアップの自動削除(世代管理)
find “${BACKUP_DIR}” -name “zabbix_full_.dump” -type f -mtime +${RETENTION_DAYS} -exec rm -f {} \;
echo “[$(date)] Old backups older than ${RETENTION_DAYS} days cleaned up.”
echo “[$(date)] Zabbix Backup Process Finished.”
> 先輩からのアドバイス:
> 履歴データ(`history`, `trends`系のテーブル)が数十GB〜数百GBを超えている場合、毎日のフルバックアップはストレージを圧迫します。その場合は、TimescaleDBのハイパーテーブルのチャンク単位でのバックアップや、ストレージ層のスナップショット(AWS EBS SnapshotやLVMスナップショット)を組み合わせるのが、プロの現場のスタンダードです。
—
3. 災害発生時を想定したスタンバイ環境へのフェイルオーバーとリカバリ演習
「バックアップがある」と安心しきっていて、いざ本番機が火を吹いた時にリストア手順でモタつく……これが現場の最大の悲劇です。
ここでは、DBサーバーが全損した最悪のシナリオを想定し、別系統のスタンバイ環境へ迅速に復旧する手順をシミュレーションします。
リストアの4ステップ手順
1. ベース環境の構築(インフラのプロビジョニング)
- AnsibleやTerraformを使い、Zabbixサーバーのミドルウェア(PostgreSQL/Apache/PHPなど)を同等バージョンで構築します。
2. 設定ファイルとカスタムスクリプトの配置
- 事前に退避させておいた `/etc/zabbix/` や `/usr/lib/zabbix/` を新しいサーバーへ同期します。
3. データベースのリストア(極意:整合性回復)
- 空のデータベースを作成し、バックアップファイルからリストアを流し込みます。
新規DBの作成
createdb -U postgres zabbix
カスタムフォーマット(-Fc)からのリストア
–clean オプションで既存オブジェクトを綺麗にクリアしながら復元
pg_restore -U postgres -d zabbix –clean –no-owner –no-privileges /backup/zabbix/db/zabbix_full_20231025_120000.dump
4. Zabbixサーバーの起動とスモークテスト
- サービスを起動し、ログにエラーが出ていないか確認します。
systemctl start zabbix-server
systemctl start zabbix-frontend
tail -f /var/log/zabbix/zabbix_server.log
—
4. リストア後のデータ不整合やヒストリキャッシュエラーを防ぐための事後確認チェックリスト
「よし、リストア完了!」とすぐエージェントを接続させてはいけません。DBをリストアした直後は、Zabbix特有の「時限爆弾」が隠れていることがあります。以下のチェックリストを必ずクリアしてください。
- [ ] ホストの「ホスト名(IP/DNS)」とエージェントの設定が一致しているか
- DR環境のIPアドレスやホスト名が変わっている場合、即座にZabbixフロントエンドからアクティブ/パッシブチェックの設定を調整するか、DNSを切り替えてください。
- [ ] データベースのシーケンス(Auto Incrementのカウンター)が同期しているか
- `pg_dump` のバージョンやリストア方法によっては、IDの最大値とシーケンスがズレてしまい、新規ホスト追加時に `Duplicate key error` が発生することがあります。以下のクエリでズレがないか確認し、必要に応じて修正します。
— PostgreSQLの場合のシーケンス確認・修復の一例(Zabbixの主要テーブル)
— 実際には各テーブルのIDカラムに対して調整が必要です
SELECT setval(‘hosts_hostid_seq’, (SELECT MAX(hostid) FROM hosts));
- [ ] ヒストリキャッシュおよびトレンドウォッチャーのログ枯渇がないか
- リストア直後は、未送信だったデータが一斉に流れ込もうとするため、`zabbix_server.log`に `historic data cache is full` や `preprocessing worker` の悲鳴が出やすくなります。一時的に `HistoryCacheSize` などのパラメータを拡張して受け皿を大きくすることをお勧めします。
- [ ] アラート通知機能(メディアタイプ)の無効化確認(最重要!)
- DR演習時の最大の罠がこれです。 リストアした瞬間に、古い障害トリガーが復活し、数千件の「死活監視アラートメール」が社内やクライアントに一斉送信される事故が後を絶ちません。
- 必ずリストア直後かつZabbix起動前に、DBを直接叩いて全てのメディアタイプ(ActionやMedia type)を無効化(あるいはアクションの実行を停止)してからサービスを立ち上げてください。
— 予防策:全アクションを強制的に無効化するSQL(リストア直後に実行)
UPDATE actions SET status = 1; — 1 = disabled
—
最後に:オブザーバビリティの守護者であれ
監視ツールであるZabbix自身が、誰からも監視されず、バックアップも適当に扱われている――そんな現場を私たちはいくつも見てきました。
今回紹介したバックアップ戦略とリカバリ手順を組織に組み込めば、あなたのシステムの信頼性は圧倒的な次元へと引き上げられます。「いざという時、俺が5分でシステムを蘇らせる」そう胸を張れるエンジニアに、今日からなっていきましょう。毎日の運用が劇的に楽になり、自信に満ちたシステムライフが待っていますよ!