バックアップおよび復旧
データ保護は運用の最も重要な責任です。PlantPulse は plantpulse-backup モジュールを通じて PostgreSQL / Aster TSDB / ファイル / コンテナボリュームを統合的にバックアップします。
plantpulse-backup は plantpulse-datalake イメージの中に含まれています。データベースがすべてそのコンテナ内で動作しているためです。
cd /opt/kopens/plantpulse-platform-docker/bin
./shell.sh # 데이터레이크 진입
cd /opt/kopens/plantpulse-platform/plantpulse-backup/bin
Docker ボリュームのバックアップのみホストで行います(後述の §3)。
保護対象一覧
バックアップツールマトリクス
| ツール | 対象 | 方式 | 圧縮 | 重複排除 |
|---|---|---|---|---|
| pgBackRest | PostgreSQL | Full / Differential / Incremental | gzip / zstd | ✓ |
| Medusa | Aster TSDB | Full / Differential (スナップショット) | gzip | - |
| Restic | ファイル / ディレクトリ | 増分 | zstd | ✓ |
| rc mirror | RustFS | 増分同期 | - | - |
| backup-volume.sh | Docker ボリューム | tar.gz スナップショット | gzip | - |
RPO / RTO 推奨目標
| データ | RPO (復旧時点) | RTO (復旧時間) | 推奨バックアップ頻度 |
|---|---|---|---|
| PostgreSQL メタ | 1時間 | 30分 | 1日1回 Full + 時間別 WAL |
| Aster TSDB 時系列 | 24時間 | 2時間 | 1日1回 Diff + 週1回 Full |
| RustFS オブジェクト | 24時間 | 4時間 | 外部 S3 ミラー + 1日1回 |
| 設定 / 証明書 | 変更時 | 15分 | 変更時直ちに + 月1回 |
運用グレードデータセンター: 上記目標はシングルサイトの単純運用の基準です。Multi-AZ / Geo-redundant が必要な場合は、外部サイト複製 (rsync, rc mirror, Kafka MirrorMaker) を合わせて設計してください。
バックアップ保存構造
/data1/pp-backup/
├── pgbackrest/postgres/ # PostgreSQL 백업 (pgBackRest)
│ ├── archive/ # WAL archive
│ └── backup/ # Full / Diff / Incr
├── medusa/ # Cassandra 백업 (Medusa)
│ └── <hostname>/<backup-name>/
├── restic/ # 파일 백업 (Restic)
│ ├── data/
│ ├── index/
│ └── snapshots/
└── docker-volume/ # Docker 볼륨 (tar.gz)
├── pp-data-YYYYMMDD.tar.gz
├── pp-security-YYYYMMDD.tar.gz
└── ...
1. plantpulse-backup 統合コマンド
plantpulse-backup モジュールがすべてのバックアップツールをラッピングします。
初期インストール (初回1回のみ)
cd /opt/kopens/plantpulse-platform/plantpulse-backup/bin
./backup.sh --install
自動実行内容:
- pgBackRest 設定 (
/etc/pgbackrest/pgbackrest.conf) - Medusa 設定 (
/etc/medusa/medusa.ini) - ディレクトリ / 権限作成
- pgBackRest stanza 作成
PostgreSQL バックアップ
cd /opt/kopens/plantpulse-platform/plantpulse-backup/bin
./backup.sh --postgres # Differential (기본, 빠름)
./backup.sh --postgres full # Full (전체)
./backup.sh --postgres incr # Incremental (가장 빠름)
Aster TSDB バックアップ
./backup.sh --cassandra # Differential
./backup.sh --cassandra full # Full
ファイルバックアップ (Restic)
/opt/kopens/plantpulse-platform/plantpulse-backup/etc/run_restic.sh
/data1/pp-data増分バックアップ- 保存ポリシー: 最新7日 + 月別1件
- 自動整合性チェック
バックアップ整理
./backup.sh --purge
- pgBackRest:
repo1-retention-full(基本2セット) - Medusa:
CASS_PURGE_KEEP_DAYS(基本10日) - Restic: ポリシーに従い自動的に整理
2. 自動バックアップ — すでに有効です
自動バックアップはデフォルトで有効になっています。スケジュールを設定するコマンドを別途実行する必要はありません。
| ジョブ | 内容 |
|---|---|
postgres-diff | PostgreSQL Differential |
postgres-full | PostgreSQL Full |
cassandra-diff | Aster TSDB Differential |
cassandra-full | Aster TSDB Full |
purge | 保存ポリシー整理 |
データレイクイメージには systemd も crontab もありません(PID 1 がエントリポイント自身です)。
スケジュールはデータレイク DB の backup_schedule テーブルにジョブごとに1行で保持されており、
plantpulse-datalake-admin-api 内の Quartz スケジューラが(PP_MODE=MASTER でのみ)読み取って発火します。
pd backup schedule # 읽기
pd backup schedule set --job <잡> --cron "<초 분 시 일 월 요일>"
pd backup schedule reset [--job <잡>]
systemctl list-timers で探さないでください — 表示されません。
:::
基本スケジュール
| 作業 | OnCalendar | 時間 |
|---|---|---|
| PostgreSQL Diff | *-*-* 01:30:00 | 毎日 01:30 |
| PostgreSQL Full | Sun *-*-* 01:00:00 | 毎週日曜日 01:00 |
| Aster TSDB Diff | *-*-* 01:20:00 | 毎日 01:20 |
| Aster TSDB Full | Sun *-*-* 00:10:00 | 毎週日曜日 00:10 |
| Purge | Sun *-*-* 03:00:00 | 毎週日曜日 03:00 |
有効/無効の切り替え
ホストのシークレットサイドカーにスイッチを記述して再起動します。
# 호스트에서
sudo vi /etc/kopens/plantpulse-platform.env
# export PP_BACKUP_SCHEDULE_ENABLED=false
cd /opt/kopens/plantpulse-platform-docker/bin
./restart.sh
タイマー自体は常に発火し、ラッパースクリプトがスイッチを読み取って判断します。オフに設定されている場合、バックアップをスキップしつつ ジャーナルと history.jsonl に result="skipped" として記録します — ok も fail もありません。これにより、後で «オフにした» ことと «実行された» ことを区別できます。
ユニットファイルを直接書き換えて停止させないでください。次回のイメージビルドでオリジナルが再展開されると、静かに復活します。
export PP_BACKUP_SCHEDULE_ENABLED=false を bin/env.sh にのみ記述すると コンテナに到達しません。 compose がこの名前をコンテナに渡す行がスイッチのすべてであり、その値はサイドカー(またはシェル export)から供給されます。誤った記述をすると «オフに見えるが回り続けている» 状態になります。
3. Docker ボリュームバックアップ (コンテナ環境)
ワンラインインストール / Docker インストールでは、ボリューム単位のバックアップが追加で可能です。
ホストで実行します。
cd /opt/kopens/plantpulse-platform-docker/bin
# 기본 세트를 한 번에 (pp-data · pp-security)
./backup.sh
# 볼륨 하나만
./tools/backup-volume.sh pp-data 7 /data1/pp-backup/docker-volume
./tools/backup-volume.sh pp-security 30 /data1/pp-backup/docker-volume
基本セットから2つが除外されているのは、失念したからではありません — pp-backup はバックアップの 保存先であるため(自身の内部に自分を入れると毎回倍増します)、pp-temp は復旧に有用ではないためです。必要な場合は、引数で指定してバックアップできます。
設定テンプレートはホストディレクトリ /etc/kopens/conf をバインドマウントしたものであるため、Docker ボリュームバックアップの対象ではありません。ホストファイルとしてまとめてバックアップしてください。シークレットサイドカー /etc/kopens/plantpulse-platform.env も同様です。
| 引数 | 説明 | デフォルト |
|---|---|---|
| 1 | ボリューム名 | (必須) |
| 2 | 保存日数 | 7 |
| 3 | 保存パス | /data1/pp-backup/docker-volume |
4. 環境変数 (backup.sh)
| 変数 | デフォルト | 説明 |
|---|---|---|
BACKUP_ROOT | /data1/pp-backup | バックアップルート |
PG_VER | 18 | PostgreSQL バージョン |
PG_DATA | /data1/pp-data/postgres/data | PG データディレクトリ |
CASS_BASE | /opt/kopens/plantpulse-platform/plantpulse-storage/db/cassandra | Aster TSDB インストールパス |
CQL_USER | ${PP_CASSANDRA_USER} | CQL ユーザー |
CQL_PASS | ${PP_CASSANDRA_PASSWORD} | CQL パスワード |
PG_RETENTION_FULL | 2 | PG Full 保存 |
CASS_PURGE_KEEP_DAYS | 10 | Medusa 保存日数 |
5. 外部サイト複製 (Off-site)
ローカルバックアップのみではデータセンター障害に脆弱です。推奨パターンは以下の通りです。
# 매일 새벽 4시 — 외부 S3 로 복제
0 4 * * * rclone sync /data1/pp-backup/ s3:kopens-pp-backup/$(hostname)/ \
--bwlimit 50M --log-file /var/log/pp-backup-sync.log
# RustFS 객체는 S3 클라이언트로 별도 미러
0 5 * * * rc mirror --overwrite local/ s3-offsite/
6. 復旧
6.1 PostgreSQL 復旧
# 1. plantpulse 중지 (PG 의존 모듈 + PG)
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
./stop.sh
# 2. 백업 정보 확인
sudo -u postgres pgbackrest --stanza=pg18 info
# 3. 최신 복구
sudo -u postgres pgbackrest --stanza=pg18 restore
# 3-2. 시점 복구 (PITR)
sudo -u postgres pgbackrest --stanza=pg18 --type=time \
--target="2026-05-30 12:00:00" restore
# 4. 재시작
./start-daemon.sh
./status.sh
6.2 Aster TSDB 復旧
# 백업 목록
medusa list-backups
# 단일 노드 복구
medusa restore-node --backup-name full_20260530_0010
# 클러스터 전체 복구 (마스터에서)
medusa restore-cluster --backup-name full_20260530_0010
注意:
restore-clusterはすべてのノードのデータを上書きします。実行前に必ず stage 環境で検証してください。
6.3 ファイル復旧 (Restic)
# 스냅샷 목록
restic -r /data1/pp-backup/restic snapshots
# 최신 스냅샷 → 임시 위치 복구
restic -r /data1/pp-backup/restic restore latest --target /data1/pp-data-restored
# 특정 파일만 복구
restic -r /data1/pp-backup/restic restore latest --target / --include /data1/pp-data/cassandra/data/pp/tm_tag_point
6.4 部分時系列復旧 (plantpulse-recovery)
特定アセットの特定期間データのみを再処理する場合:
cd /opt/kopens/plantpulse-platform/plantpulse-recovery/bin
./recovery.sh EQUIPMENT_000001 20260501 20260530
6.5 部分時系列抽出 (plantpulse-exporter)
CSV として抽出、または dsbulk でバルク処理を行う場合:
cd /opt/kopens/plantpulse-platform/plantpulse-exporter/bin
# 에셋 단위 CSV
./export.sh EQUIPMENT_000001 20260101 20260530 /tmp
# 테이블 벌크 언로드 → gz
./bulk-unload.sh pp tm_tag_point
# /data1/pp-backup/cassandra/bulk/tm_tag_point.gz
# 다시 로드
./bulk-load.sh pp tm_tag_point
7. 災害復旧 (DR) シナリオ
シナリオ A: サーバーハードウェア障害 (Cold DR)
予想 RTO: 4~8時間 (データ容量により変動)
シナリオ B: データ破損 (PITR)
# 1. 손상 시점 직전으로 시점 복구
./stop.sh
sudo -u postgres pgbackrest --stanza=pg18 --type=time \
--target="2026-05-30 14:30:00" restore
# 2. Cassandra 도 동일 시점 가까운 백업으로
medusa restore-cluster --backup-name diff_20260530_0120
# 3. 재시작
./start-daemon.sh
./status.sh
シナリオ C: 外部サイトフェイルオーバー (Hot DR)
外部サイトに standby クラスターを維持する場合。事前設計が必要です:
- PostgreSQL: streaming replication または pgBackRest 非同期複製
- Aster TSDB: multi-DC クラスター + 自動 hinted handoff
- Kafka: MirrorMaker 2 双方向複製
- RustFS: site replication または
rc mirror --watch
8. 復旧後検証チェックリスト
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
# 1. 전체 모듈 상태
./status.sh
# 2. 헬스 체크
./ops-check.sh
# 3. Cassandra 클러스터 정상
./pd node status
# 4. PostgreSQL 연결
./pd node psql -c "SELECT count(*) FROM site;"
# 5. Kafka 토픽 / Consumer Group
./pd node topic
ブラウザ:
- ウェブコンソール接続 (
http://[HOST]/) - 管理者ログイン (
admin / admin123!) - ダッシュボードロード
- アラーム一覧表示
- OPC 接続状態 CONNECTED
- 時系列トレンドで最新データを表示
- CEP ルール実行確認
9. バックアップ運用のベストプラクティス
- 3-2-1 ルール: データ 3 コピー、2 媒体、1 オフサイト
- 月 1 回の復旧訓練: stage 環境で実際の復旧を試行
- バックアップ整合性検証:
restic check,pgbackrest verify,medusa verify - バックアップモニタリング: バックアップ失敗時の通知 (Slack, email)
- 暗号化: 外部サイト転送時の TLS、保存時の LUKS/SSE-S3
- 権限分離: バックアップディスクは別途マウント + read-only マウントオプション
- 文書化: 復旧手順を運用チームの共有 wiki に記録
関連文書
技術支援
バックアップ / 復旧に関するお問い合わせ: webmaster@kopens.com