백업·HA·DR 기술정보 공유

1. 개요 (Executive Summary)
- 본 문서는 Veeam Agent for Linux를 활용하여 리눅스 호스트 전체(Volume-level) 스냅샷 백업을 수행할 때, Docker 가상화 환경 및 내부 데이터베이스(MySQL / MariaDB)의 데이터 무결성과 정합성(Consistency)을 확보하기 위한 가이드이다.
- Docker 컨테이너는 호스트 OS의 커널을 공유하되 고유한 네임스페이스와 격리된 파일시스템을 사용하는 대표적인 ‘어플리케이션 가상화 영역’이다. 이러한 구조적 특성과 애플리케이션의 상태를 직접 제어하여 정합성을 확보할 수 있는 범용 온라인 백업 API를 제공하지 않기 때문에 기존 스냅샷 기반 및 데이터 백업 솔루션 모두 컨테이너 내부에서 동작하는 데이터베이스의 트랜잭션 정합성(Application Consistency)을 자동으로 보장할 수 없다.
- 이러한 Docker 백업의 기술적 한계를 극복하기 위해 본 가이드에서는 디스크 스냅샷의 물리적 효율성을 유지하되, 백업 직전 논리적 정합성을 추가 확보하는 ‘하이브리드 자동화 백업 모델’을 적용하는 방안을 제시한다.
2. 백업 아키텍처 및 흐름도 (Workflow)
[Veeam 백업 시작]
│
▼
1. Pre-freeze 스크립트 실행
└─ 실행 중인 DB 컨테이너에서 논리 Dump(.sql.gz) 생성 및 Veeam 백업 대상 볼륨에 저장
│
▼
2. 볼륨 Snapshot 생성
└─ Veeam Agent가 백업 대상 Linux 볼륨의 Snapshot 생성 (생성된 DB Dump 파일 포함)
│
▼
3. Post-thaw 스크립트 실행
└─ 필요 시 DB/Application의 Quiesce 상태 해제
※ 본 구성에서는 별도 작업이 없으므로 사용하지 않음
│
▼
4. 실제 백업 데이터 전송
└─ Snapshot → Veeam Backup Repository
│
▼
5. 백업 작업 완료
│
▼
6. Post-job 스크립트 실행
└─ 호스트 디스크 용량 관리를 위해 3일 이전 DB Dump 파일 자동 삭제
│
▼
[Veeam 백업 종료]
3. 단계별 세부 작업 절차 (Implementation Steps)
3.1. 사전 준비 (디렉토리 생성 및 권한 설정)
# 스크립트 저장 경로 생성
sudo mkdir -p /opt/veeam-scripts
# DB 덤프 파일 저장 경로 생성 (Veeam 백업 대상 볼륨 내 위치 필수)
sudo mkdir -p /var/lib/docker/db_dumps
3.2. Pre-freeze 스크립트 작성 (백업 직전 단계)
경로: /opt/veeam-scripts/pre-freeze.sh
역할: Veeam Volume Snapshot 생성 직전에 컨테이너 내부 DB의 논리적으로 일관된 백업본을 생성하여, 호스트 Volume Snapshot만으로 확보하기 어려운 데이터베이스의 Application Consistency를 추가로 확보한다.
#!/bin/bash
set -o pipefail
# ----------------------------------------------------
# 1. 환경 변수 설정
# ----------------------------------------------------
CONTAINER_NAME="mysql-container"
DB_USER="root"
DB_PASSWORD="your_secure_password"
BACKUP_DIR="/var/lib/docker/db_dumps"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/veeam_db_backup.log"
DUMP_FILE="$BACKUP_DIR/db_dump_$DATE.sql.gz"
# ※ MySQL 기준 예제입니다.
# MariaDB 환경에서는 mysqldump 대신 mariadb-dump를 사용합니다.
# ----------------------------------------------------
# 2. 실행 로그 기록
# ----------------------------------------------------
echo "[$(date)] --- Pre-freeze: DB Dump Start ---" >> "$LOG_FILE"
# ----------------------------------------------------
# 3. DB 전체 논리 백업 및 압축
# ----------------------------------------------------
docker exec "$CONTAINER_NAME" \
mysqldump \
-u"$DB_USER" \
-p"$DB_PASSWORD" \
--all-databases \
--single-transaction \
--routines \
--events \
--triggers \
| gzip > "$DUMP_FILE"
RESULT=$?
# ----------------------------------------------------
# 4. Dump 결과 확인
# ----------------------------------------------------
if [ $RESULT -eq 0 ] && [ -s "$DUMP_FILE" ]; then
echo "[$(date)] Pre-freeze: DB Dump Success. (File: $DUMP_FILE)" >> "$LOG_FILE"
exit 0
else
echo "[$(date)] Pre-freeze: DB Dump FAILED!" >> "$LOG_FILE"
rm -f "$DUMP_FILE"
exit 1
fi
3.3. Post-job 스크립트 작성 (백업 작업 완료 후 단계)
경로: /opt/veeam-scripts/post-job.sh
역할: Veeam 백업 작업이 완료된 이후 호스트 디스크의 DB Dump 보관 정책을 적용한다. 최근 Dump 파일은 유지하고 3일 이상 경과한 과거 Dump 파일을 삭제하여 호스트 디스크 사용량을 관리한다.
#!/bin/bash
# ----------------------------------------------------
# 1. 환경 변수 설정
# ----------------------------------------------------
# DB Dump 파일이 저장되는 경로
BACKUP_DIR="/var/lib/docker/db_dumps"
# Post-job 실행 결과를 기록할 로그 파일
LOG_FILE="/var/log/veeam_db_backup.log"
# ----------------------------------------------------
# 2. Post-job Retention 작업 시작 로그 기록
# ----------------------------------------------------
echo "[$(date)] --- Post-job: Retention Cleanup Start ---" >> "$LOG_FILE"
# ----------------------------------------------------
# 3. 3일(72시간) 이상 경과한 DB Dump 파일 삭제
# ----------------------------------------------------
# db_dump_*.sql.gz 형식의 파일 중
# 수정된 지 3일 이상 지난 파일을 삭제한다.
#
# -mtime +2 의미:
# 24시간 단위로 계산하며, 72시간 이상 경과한 파일을 대상으로 한다.
#
# 예:
# 오늘 생성된 Dump → 유지
# 1일 전 Dump → 유지
# 2일 전 Dump → 유지
# 3일 이상 경과 Dump → 삭제
find "$BACKUP_DIR" \
-name "db_dump_*.sql.gz" \
-type f \
-mtime +2 \
-delete
# ----------------------------------------------------
# 4. Retention 작업 결과 확인
# ----------------------------------------------------
# find 명령이 정상적으로 완료되었는지 확인한다.
if [ $? -eq 0 ]; then
# 정상적으로 오래된 Dump 파일 삭제가 완료된 경우
echo "[$(date)] Post-job: Retention Cleanup Completed." >> "$LOG_FILE"
exit 0
else
# Dump 파일 삭제 작업 중 오류가 발생한 경우
echo "[$(date)] Post-job: Retention Cleanup FAILED!" >> "$LOG_FILE"
# Veeam에 스크립트 실행 실패 상태 전달
exit 1
fi
3.4. 스크립트 권한 부여
작성된 스크립트 파일을 Veeam Agent 프로세스가 실행할 수 있도록 실행 권한을 명시적으로 부여한다.
sudo chmod 700 /opt/veeam-scripts/pre-freeze.sh
sudo chmod 700 /opt/veeam-scripts/post-job.sh
3.5. Veeam Agent 작업(Job) 연동
- 백업 마스터 서버의 Veeam 관리 콘솔에 접속하여 Linux Agent Backup Job을 편집한다.
- 백업 대상 유형을 Entire System 또는 해당 디렉토리가 포함된 Volume-level backup으로 선택한다.
- Guest Processing → Applications → 대상 서버 Edit → Scripts 탭으로 이동하여 Pre-freeze 및 Post-job 스크립트를 지정한다.
- 아래와 같이 절대 경로 지정:
– Pre-freeze script: /opt/veeam-scripts/pre-freeze.sh
– Post-job script: /opt/veeam-scripts/post-job.sh - 설정을 저장하고 백업 스케줄을 확정한다.
4. 핵심 주의사항 (Crucial Considerations)
본 백업 아키텍처의 안정적인 운영을 위해 담당자는 다음 사항을 반드시 인지하고 정기적으로 점검해야 한다.
- ① 호스트 디스크 여유 공간(Storage) 확보 필수
mysqldump 결과는 gzip을 통해 실시간으로 압축되어 /var/lib/docker/db_dumps 경로에 저장된다. 따라서 실제 Dump 파일 크기는 DB 원본 데이터 크기 및 압축률에 따라 달라진다. Dump 파일 저장 공간과 Veeam Snapshot 동작에 필요한 여유 공간을 함께 고려하여 충분한 호스트 디스크 여유 공간을 확보하고 주기적으로 모니터링해야 한다. - ② 패스워드 보안 노출 주의
스크립트 내부에 DB_PASSWORD=”비밀번호” 형태로 평문 저장된다. 리눅스 호스트 내 일반 사용자가 이 스크립트를 열람할 수 없도록 엄격한 파일 권한 관리가 필요하다. 대책으로 스크립트 파일의 권한을 루트 계정만 볼 수 있도록 제한한다. (sudo chmod 700 /opt/veeam-scripts/*.sh) - ③ Docker Compose 프로젝트 파일 경로 일치 확인
데이터 볼륨이 완벽히 복구되더라도, 컨테이너를 구동하는 아키텍처 명세서(docker-compose.yml)나 환경 설정 파일(.env)이 유실되면 신속한 서비스 재개가 불가능하다. 해당 파일들이 저장되는 경로가 Veeam의 전체 볼륨 백업 대상에 완벽히 포함되어 있는지 사전에 타겟팅을 검증해야 한다. - ④ 스크립트 에러 발생 시 백업 작업 정책 수립
DB 컨테이너가 일시적인 이슈로 멈춰있거나 이름이 바뀌어 Pre-freeze 덤프 명령이 실패(exit 1)할 경우, Veeam 백업 작업 전체가 실패하거나 경고(Warning) 상태로 종료된다. 깨진 상태의 백업이 완료되는 것보다 백업 실패 알람을 받아 담당자가 즉시 조치하는 것이 안전하므로, 에러 반환 설정을 유지하는 것을 권장한다. - ⑤ 데이터 디렉토리 위치 규정 및 외부 NFS 구성 시 예외 조건
로컬 디스크 원칙: 본 가이드에서 제시하는 하이브리드 백업 아키텍처가 유효하려면, Docker 컨테이너가 마운트하여 사용하는 실제 DATA 디렉토리(볼륨 및 마운트 경로)가 반드시 해당 리눅스 호스트 서버 내(로컬 스토리지)에 물리적으로 위치해야 한다.
NFS 외부 공유 폴더 구성 시 위험성: 만약 아키텍처 설계상 타 서버의 볼륨을 NFS(Network File System)나 SAMBA 등으로 마운트하여 도커 데이터 저장소로 사용할 경우, 본 호스트 서버를 Veeam으로 전체 볼륨 백업하더라도 네트워크 마운트 지점 내부의 실제 데이터는 백업 대상에서 누락될 수 있으므로 별도 백업 범위를 확인해야 한다.
NFS 환경에서의 조치 요건: 데이터 저장소가 분리된 분산 스토리지 아키텍처인 경우, 도커 호스트 서버와 NFS 데이터 스토리지 서버 양쪽 모두에 대한 백업 작업을 개별 수행하고, 백업 전/사후 스크립트 실행 타이밍을 양측 서버 간에 동기화하여 데이터 정합성 확보 방안을 추가 구성해야 한다. - ⑥ Pre-freeze / Post-job 스크립트 실행 시간 제한 주의
Veeam Agent for Linux의 Pre-freeze 및 Post-thaw 스크립트는 기본적으로 실행 제한 시간이 10분이다. DB 용량이 크거나 mysqldump 수행 시간이 10분을 초과할 가능성이 있는 경우 /etc/veeam/veeam.ini의 timeoutFreezeThaw 값을 실제 최대 Dump 수행 시간보다 충분히 크게 조정해야 한다. 또한 Pre-job / Post-job 스크립트에도 별도의 실행 제한 시간이 적용되며, 필요 시 timeoutPrePost 값을 조정한다.
5. 재해 복구 시나리오 (Disaster Recovery Blueprint)
- ① OS 및 볼륨 복구
Veeam Recovery Media를 사용하여 대상 리눅스 호스트의 OS와 볼륨 전체를 베어메탈 복구(Bare-Metal Recovery)한다. - ② 도커 상태 점검
복구 완료 후 서버가 켜지면 도커 엔진을 구동하고, 백업 경로에 .sql.gz 파일과 docker-compose.yml 파일이 정상 복원되었는지 확인한다. - ③ 컨테이너 유효성 검증
docker compose up -d로 서비스를 올렸을 때 만약 스냅샷 시점의 충격으로 라이브 DB 컨테이너가 정상 작동하지 않거나 데이터가 오염되었다면, 즉시 컨테이너를 정지(docker compose down)한다. - ④ DB 데이터 무결성 복구
– 기존 DB 데이터 디렉토리를 즉시 삭제하지 않고 별도 경로로 이동 또는 보존한다. 신규 빈 데이터 디렉토리를 준비하여 DB 컨테이너를 초기화한 후, 복원된 논리 Dump를 Import한다. 데이터 검증 완료 후 기존 데이터 디렉토리의 삭제 여부를 결정한다.
– 컨테이너를 초기 상태로 다시 가동한다.
– 함께 복원된 안전한 덤프 파일을 압축 해제하여 컨테이너 내부에 밀어 넣는다.
(명령어 예시: gunzip /var/lib/docker/db_dumps/db_dump_최신날짜.sql.gz 및 docker exec -i mysql-container mysql -u root -p’비밀번호’ < /var/lib/docker/db_dumps/db_dump_최신날짜.sql) - ⑤ 최종 완료: 데이터 유효성 검증 후 서비스를 정상 활성화한다.
상기 가이드는 Veeam Backup 뿐만 아니라, 다른 이미지 백업 솔루션에서도 Docker 컨테이너 내 Mysql 등에 대한 정합성을 보장할 수 있는 방법으로 다른 분들에게도 도움이 되었으면 한다.



