백업·복구
매일 밤 Postgres 덤프와 RustFS 미러를 만드는 systemd 타이머와 복구 방법
MLOps Central Platform 의 모든 상태는 두 곳에 저장: Postgres(앱과 MLflow 가 함께 사용하는 DB)와 RustFS(데이터셋·이미지 레이어·모델 아티팩트·빌드 로그·엣지 업로드). 둘 다 Docker 볼륨에만 있어서, MLflow 실험 영구 삭제나 테넌트 삭제처럼 실수로 삭제한 데이터는 백업 없이는 되돌릴 수 없음. Compose 는 백업을 수행하지 않으므로, 소스에 포함된 백업 스크립트와 systemd 타이머를 설치.
백업 대상과 방식
| 대상 | 방식 | 보존 |
|---|---|---|
| Postgres | 컨테이너 내부의 pg_dump -Fc 로 BACKUP_DIR/postgres/mlflow-<UTC시각>.dump 에 저장. 생성 즉시 pg_restore --list 로 검사하고, 손상된 파일은 남기지 않음. | BACKUP_KEEP_DAYS(기본 14일)보다 오래된 덤프는 삭제 |
| RustFS | 버킷마다 aws s3 sync 로 BACKUP_DIR/objects/<버킷>/ 에 복사 | 추가만 수행(--delete 없음). 삭제한 객체도 미러에 남음. 공간이 부족하면 수동으로 정리. |
- 매일 03:30(최대 15분 무작위 지연)에 실행. 서버가 꺼져 있어 놓친 백업은 다음 부팅 때 실행.
- 낮은 우선순위(
Nice=10, I/O idle)로 실행되어 학습·요청과 디스크 I/O 를 경합하지 않음. pg_dump는 Postgres 컨테이너 내부의 것을, S3 복사는 AWS CLI 컨테이너를 사용. 서버에 별도 설치 불필요.
설치 (서버에서 한 번)
-
스크립트와 유닛 파일 설치.
D=/opt/geo-mlops/deploy/backup sudo install -m 0755 $D/backup.sh /usr/local/sbin/geo-mlops-backup sudo install -m 0644 $D/geo-mlops-backup.service /etc/systemd/system/ sudo install -m 0644 $D/geo-mlops-backup.timer /etc/systemd/system/ -
기본값과 다르게 지정할 값이 있으면
/etc/geo-mlops/backup.env에 작성(없으면 생략 가능).sudo tee /etc/geo-mlops/backup.env >/dev/null <<'ENV' BACKUP_DIR=/mnt/backup/geo-mlops BACKUP_KEEP_DAYS=14 ENV -
타이머를 활성화하고, 첫 백업을 지금 한 번 실행해 확인.
sudo systemctl daemon-reload sudo systemctl enable --now geo-mlops-backup.timer sudo systemctl start geo-mlops-backup.service journalctl -u geo-mlops-backup.service -n 20 # 마지막 줄 "backup finished" systemctl list-timers geo-mlops-backup.timer # 다음 실행 시각
backup.env 로 바꿀 수 있는 값
| 변수 | 기본값 | 뜻 |
|---|---|---|
BACKUP_DIR | /var/backups/geo-mlops | 백업이 저장될 경로 |
BACKUP_KEEP_DAYS | 14 | DB 덤프 보존 일수 |
BACKUP_BUCKETS | (비움 = 모든 버킷) | 공백으로 구분한 버킷 이름 |
BACKUP_SKIP_OBJECTS | 0 | 1 이면 DB 만 백업 |
PG_CONTAINER / PG_USER / PG_DB | geo-mlops-mlflow-postgres / mlflow / mlflow | Postgres 컨테이너와 계정 |
S3_ENDPOINT / S3_ACCESS_KEY / S3_SECRET_KEY | http://localhost:9000 / rustfsadmin / rustfsadmin | RustFS 접속 정보. Compose 의 계정을 변경했다면 여기도 변경. |
AWS_CLI_IMAGE | amazon/aws-cli:2.34.63 | S3 복사에 사용할 이미지 |
복구
데이터베이스
앱을 중지해 DB 에 접속하는 프로세스가 없게 한 뒤 덤프 복원.
docker stop geo-mlops-app
docker exec -i geo-mlops-mlflow-postgres \
pg_restore -U mlflow -d mlflow --clean --if-exists --no-owner \
< /var/backups/geo-mlops/postgres/mlflow-<UTC시각>.dump
docker start geo-mlops-app
객체
버킷 하나(또는 그 내부의 접두사)를 미러에서 복원. 미러는 추가만 하므로 백업 시점 이후에 삭제한 객체도 복원됨. 필요한 접두사만 선택해 업로드.
docker run --rm --network host -v /var/backups/geo-mlops/objects:/backup \
-e AWS_ACCESS_KEY_ID=rustfsadmin -e AWS_SECRET_ACCESS_KEY=rustfsadmin \
-e AWS_DEFAULT_REGION=us-east-1 -e AWS_REQUEST_CHECKSUM_CALCULATION=when_required \
amazon/aws-cli:2.34.63 --endpoint-url http://localhost:9000 \
s3 sync /backup/datasets/<tenant_id>/<dataset_id>/ s3://datasets/<tenant_id>/<dataset_id>/
복구 연습 (분기마다)
분기에 한 번, 운영 서버가 아닌 곳(같은 Compose 스택이 실행 중인 개발 서버)에서 덤프가 읽히는지 확인. 그 서버에는 타이머를 설치하지 않았을 수 있으므로 소스의 스크립트를 직접 실행.
BACKUP_DIR=/tmp/geo-backup-drill BACKUP_BUCKETS=build-logs /opt/geo-mlops/deploy/backup/backup.sh
docker exec -i geo-mlops-mlflow-postgres pg_restore --list \
< /tmp/geo-backup-drill/postgres/mlflow-*.dump | head
다음: 앞단 프록시 주의