> For the complete documentation index, see [llms.txt](https://kopens.gitbook.io/plantpulse-platform/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kopens.gitbook.io/plantpulse-platform/admin/backup-recovery.md).

# 백업 및 복구

데이터 보호는 **운영의 가장 중요한 책임**입니다. PlantPulse 는 `plantpulse-backup` 모듈을 통해 PostgreSQL / Cassandra / 파일 / 컨테이너 볼륨을 통합 백업합니다.

## 보호 대상 한눈에 보기

```mermaid
flowchart LR
  subgraph SRC["보호 대상"]
    PG[(PostgreSQL<br/>메타데이터)]
    CASS[(Cassandra<br/>시계열)]
    FILE[/data1/pp-data<br/>파일/]
    MINIO[(MinIO<br/>오브젝트)]
    VOL[Docker 볼륨<br/>pp-*]
  end

  subgraph TOOL["백업 도구"]
    PGBR[pgBackRest]
    MED[Medusa]
    REST[Restic]
    MC[mc mirror]
    BVOL[backup-volume.sh]
  end

  subgraph DEST["저장 위치"]
    LOCAL[/data1/pp-backup/]
    OFFSITE[외부 스토리지<br/>S3 · NFS · 테이프]
  end

  PG --> PGBR
  CASS --> MED
  FILE --> REST
  MINIO --> MC
  VOL --> BVOL

  PGBR --> LOCAL
  MED --> LOCAL
  REST --> LOCAL
  MC --> OFFSITE
  BVOL --> LOCAL

  LOCAL -.->|rsync · S3 sync| OFFSITE
```

## 백업 도구 매트릭스

| 도구                   | 대상         | 방식                                | 압축          | 중복 제거 |
| -------------------- | ---------- | --------------------------------- | ----------- | ----- |
| **pgBackRest**       | PostgreSQL | Full / Differential / Incremental | gzip / zstd | ✓     |
| **Medusa**           | Cassandra  | Full / Differential (스냅샷)         | gzip        | -     |
| **Restic**           | 파일 / 디렉토리  | 증분                                | zstd        | ✓     |
| **mc mirror**        | MinIO      | 증분 동기화                            | -           | -     |
| **backup-volume.sh** | Docker 볼륨  | tar.gz 스냅샷                        | gzip        | -     |

## RPO / RTO 권장 목표

| 데이터               | RPO (복구 시점) | RTO (복구 시간) | 권장 백업 빈도              |
| ----------------- | ----------- | ----------- | --------------------- |
| **PostgreSQL 메타** | **1시간**     | **30분**     | 일 1회 Full + 시간별 WAL   |
| **Cassandra 시계열** | **24시간**    | **2시간**     | 일 1회 Diff + 주 1회 Full |
| **MinIO 오브젝트**    | **24시간**    | **4시간**     | 외부 S3 미러 + 일 1회       |
| **설정 / 인증서**      | **변경 시**    | **15분**     | 변경 시 즉시 + 월 1회        |

> **운영 등급 데이터센터**: 위 목표는 단일 사이트 단순 운영 기준입니다. Multi-AZ / Geo-redundant 가 필요하면 외부 사이트 복제 (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` 모듈이 모든 백업 도구를 wrapping 합니다.

### 초기 설치 (최초 1회)

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-backup/bin
./backup.sh --install
```

자동 수행:

* pgBackRest 설정 (`/etc/pgbackrest/pgbackrest.conf`)
* Medusa 설정 (`/etc/medusa/medusa.ini`)
* 디렉토리 / 권한 생성
* pgBackRest stanza 생성

### PostgreSQL 백업

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-backup/bin

./backup.sh --postgres            # Differential (기본, 빠름)
./backup.sh --postgres full       # Full (전체)
./backup.sh --postgres incr       # Incremental (가장 빠름)
```

### Cassandra 백업

```bash
./backup.sh --cassandra           # Differential
./backup.sh --cassandra full      # Full
```

### 파일 백업 (Restic)

```bash
/opt/kopens/plantpulse-platform/plantpulse-backup/etc/run_restic.sh
```

* `/data1/pp-data` 증분 백업
* 보존 정책: 최근 7일 + 월별 1개
* 자동 무결성 검사

### 백업 정리

```bash
./backup.sh --purge
```

* pgBackRest: `repo1-retention-full` (기본 2 세트)
* Medusa: `CASS_PURGE_KEEP_DAYS` (기본 10 일)
* Restic: 정책에 따라 자동

## 2. 자동 백업 (cron)

### 설치

```bash
./backup.sh --cron-install
```

### 기본 스케줄

```mermaid
gantt
    title 주간 백업 스케줄
    dateFormat HH:mm
    axisFormat %H:%M
    section Cassandra
    Diff (매일)            :01:20, 30m
    Full (일요일)          :crit, 00:10, 60m
    section PostgreSQL
    Diff (매일)            :01:30, 30m
    Full (일요일)          :crit, 01:00, 30m
    section 정리
    Purge (일요일)         :03:00, 30m
```

| 작업              | cron 표현      | 시간           |
| --------------- | ------------ | ------------ |
| PostgreSQL Diff | `30 1 * * *` | 매일 01:30     |
| PostgreSQL Full | `0 1 * * 0`  | 매주 일요일 01:00 |
| Cassandra Diff  | `20 1 * * *` | 매일 01:20     |
| Cassandra Full  | `10 0 * * 0` | 매주 일요일 00:10 |
| Purge           | `0 3 * * 0`  | 매주 일요일 03:00 |

### 해제

```bash
./backup.sh --cron-remove
```

## 3. Docker 볼륨 백업 (컨테이너 환경)

원라인 설치 / Docker 설치에서는 볼륨 단위 백업이 추가로 가능합니다.

```bash
cd /home/kopens/plantpulse-platform-docker/bin/util

./backup-volume.sh pp-data 7 /data1/pp-backup/docker-volume
./backup-volume.sh pp-security 30 /data1/pp-backup/docker-volume
./backup-volume.sh pp-template 7 /data1/pp-backup/docker-volume
```

| 인자 | 설명    | 기본                               |
| -- | ----- | -------------------------------- |
| 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 Full 보존      |
| `CASS_PURGE_KEEP_DAYS` | `10`                                                              | Medusa 보존 일수    |

## 5. 외부 사이트 복제 (Off-site)

로컬 백업만으로는 데이터센터 장애에 취약합니다. 권장 패턴:

```bash
# 매일 새벽 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 복구

```bash
# 1. plantpulse 중지 (PG 의존 모듈 + PG)
cd /opt/kopens/plantpulse-platform/plantpulse-startup
./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 복구

```bash
# 백업 목록
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)

```bash
# 스냅샷 목록
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)

특정 에셋의 특정 기간 데이터만 재처리하려면:

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-recovery/bin
./recovery.sh ASSET_01032 20260501 20260530
```

### 6.5 부분 시계열 추출 (plantpulse-exporter)

CSV 로 추출하거나 dsbulk 로 벌크 처리:

```bash
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: 서버 하드웨어 장애 (Cold DR)

```mermaid
flowchart TD
  A[1. 신규 서버 준비<br/>requirements.md 충족] --> B[2. PlantPulse 설치<br/>java-tomcat.md]
  B --> C[3. 백업 파일 신규 서버로 이전<br/>scp / 외부 스토리지]
  C --> D[4. PostgreSQL 복구<br/>pgbackrest restore]
  D --> E[5. Cassandra 복구<br/>medusa restore-cluster]
  E --> F[6. 파일 복구<br/>restic restore]
  F --> G[7. 플랫폼 시작<br/>./start-daemon.sh]
  G --> H[8. 복구 검증<br/>웹 로그인 · 데이터 수집]
```

**예상 RTO**: 4\~8시간 (데이터 용량에 따라 다름)

### 시나리오 B: 데이터 손상 (PITR)

```bash
# 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 비동기 복제
* **Cassandra**: multi-DC 클러스터 + 자동 hinted handoff
* **Kafka**: MirrorMaker 2 양방향 복제
* **MinIO**: site replication 또는 `mc mirror --watch`

## 8. 복구 후 검증 체크리스트

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-startup

# 1. 전체 모듈 상태
./status.sh

# 2. 헬스 체크
./ops-check.sh

# 3. Cassandra 클러스터 정상
./node-status.sh

# 4. PostgreSQL 연결
./node-psql.sh -c "SELECT count(*) FROM site;"

# 5. Kafka 토픽 / Consumer Group
./node-topic.sh
```

브라우저:

* [ ] 웹 콘솔 접속 (`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 에 기록

## 관련 문서

* [모듈: storage](/plantpulse-platform/admin/modules/storage.md)
* [모듈: utilities (backup / recovery / exporter)](/plantpulse-platform/admin/modules/utilities.md)
* [운영 관리](/plantpulse-platform/installation/database.md)
* [문제 해결](/plantpulse-platform/admin/troubleshooting.md)

## 기술 지원

백업 / 복구 관련 문의: **<webmaster@kopens.com>**
