备份和恢复
数据保护是运营的最关键责任。PlantPulse 通过 plantpulse-backup 模块对 PostgreSQL / Cassandra / 文件 / 容器卷进行统一备份。
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 | 全量 / 差量 / 增量 | gzip / zstd | ✓ |
| Medusa | Cassandra | 全量 / 差量(快照) | gzip | - |
| Restic | 文件 / 目录 | 增量 | zstd | ✓ |
| mc mirror | MinIO | 增量同步 | - | - |
| backup-volume.sh | Docker 卷 | tar.gz 快照 | gzip | - |
RPO / RTO 推荐目标
| 数据 | RPO(恢复点) | RTO(恢复时间) | 推荐备份频率 |
|---|---|---|---|
| PostgreSQL 元数据 | 1小时 | 30分钟 | 日1次全量 + 小时级 WAL |
| Cassandra 时序 | 24小时 | 2小时 | 日1次差量 + 周1次全量 |
| MinIO 对象 | 24小时 | 4小时 | 外部 S3 镜像 + 日1次 |
| 配置 / 证书 | 变更时 | 15分钟 | 变更时即刻 + 月1次 |
生产数据中心:以上目标基于单站点简单运营。若需多可用区 / 异地冗余,请结合外站点复制(rsync、mc 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 模块包装所有备份工具。
初始安装(仅首次)
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 (가장 빠름)
Cassandra 备份
./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. 自动备份 — 已启用
自动备份已内置于镜像,以 systemd 定时器形式激活,默认启用。无需运行 --cron-install。
| 定时器 | 功能 |
|---|---|
plantpulse-backup-postgres-diff | PostgreSQL 差量 |
plantpulse-backup-postgres-full | PostgreSQL 全量 |
plantpulse-backup-cassandra-diff | Cassandra 差量 |
plantpulse-backup-cassandra-full | Cassandra 全量 |
plantpulse-backup-purge | 保留策略清理 |
默认调度
| 任务 | OnCalendar | 时间 |
|---|---|---|
| PostgreSQL 差量 | *-*-* 01:30:00 | 每日 01:30 |
| PostgreSQL 全量 | Sun *-*-* 01:00:00 | 每周日 01:00 |
| Cassandra 差量 | *-*-* 01:20:00 | 每日 01:20 |
| Cassandra 全量 | Sun *-*-* 00:10:00 | 每周日 00:10 |
| 清理 | Sun *-*-* 03:00:00 | 每周日 03:00 |
关闭和启用
在主机的 secret 边车中写入开关并重启。
# 호스트에서
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。因此可以后来区分「已关闭」和「已运行」。
不要直接修改 unit 文件关闭。下次镜像构建时会静默恢复。
若仅在 export PP_BACKUP_SCHEDULE_ENABLED=false 中写入 bin/env.sh,容器收不到。compose 只通过该名称将值传给容器,而值来自边车(或 shell 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
默认集合中缺少两个不是遗漏 — pp-backup 是备份的目标(自备自会每次翻倍),pp-temp 对恢复无用处。如需备份可通过参数指定。
配置模板是绑定挂载的主机目录 /etc/kopens/conf,不属于 docker 卷备份范围。请连同主机文件一起备份。secret 边车 /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 | Cassandra 安装路径 |
CQL_USER | ${PP_CASSANDRA_USER} | CQL 用户 |
CQL_PASS | ${PP_CASSANDRA_PASSWORD} | CQL 密码 |
PG_RETENTION_FULL | 2 | PG 全量保留 |
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
# MinIO 객체는 mc 로 별도 미러
0 5 * * * mc 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 Cassandra 恢复
# 백업 목록
medusa list-backups
# 단일 노드 복구
medusa restore-node --backup-name full_20260530_0010
# 클러스터 전체 복구 (마스터에서)
medusa restore-cluster --backup-name full_20260530_0010
警告:
restore-cluster会覆盖所有节点数据。执行前务必在测试环境中验证。
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 ASSET_01032 20260501 20260530
6.5 部分时序提取(plantpulse-exporter)
导出为 CSV 或用 dsbulk 进行批量处理:
cd /opt/kopens/plantpulse-platform/plantpulse-exporter/bin
# 에셋 단위 CSV
./export.sh ASSET_01032 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:服务器硬件故障(冷 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:异地故障转移(热 DR)
在异地维护待命集群的情况。需提前设计:
- PostgreSQL:流复制或 pgBackRest 异步复制
- Cassandra:多数据中心集群 + 自动 hinted handoff
- Kafka:MirrorMaker 2 双向复制
- MinIO:站点复制或
mc 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份异地
- 月度恢复演练:在测试环境中进行实际恢复演练
- 备份完整性验证:
restic check、pgbackrest verify、medusa verify - 备份监控:备份失败时告警(Slack、email)
- 加密:异地传输时用 TLS,存储时用 LUKS/SSE-S3
- 权限分离:备份磁盘单独挂载 + read-only 挂载选项
- 文档化:运维团队在共享 wiki 中记录恢复步骤
相关文档
技术支持
备份 / 恢复相关咨询:webmaster@kopens.com