Kubernetes Kubernetes Velero Backup Storage

Velero FSB 백업이 4시간 걸린다고?

defaultVolumesToFsBackup: true의 함정과 opt-in 방식으로 백업 시간 99% 단축하기

들어가며

“백업이 4시간이나 걸려요. 그런데 PartiallyFailed예요.”

홈클러스터에서 Velero File-System Backup(FSB)을 운영하다가 발견한 문제다. 매일 새벽 3시에 시작된 백업이 오전 7시가 되어도 끝나지 않았고, 완료되더라도 상태는 PartiallyFailed였다.

이전 글에서 FSB를 적용하고 130개 PodVolumeBackup이 성공한 걸 확인했다. 그때는 “전부 백업됐다”고 넘어갔지만, 실제 PVC는 44개뿐이었다. 나머지는 뭘 백업하고 있었을까?


문제 상황

환경

  • Kubernetes: 홈클러스터 (kubespray)
  • 스토리지: Longhorn
  • 백업: Velero + kopia (File-System Backup)
  • 백업 대상: GitLab, Langfuse, ClearML, Grafana 등 10개 서비스

증상

Terminal window
$ velero backup describe daily-backup-20260204
Phase: PartiallyFailed
Errors:
Velero: <none>
Cluster: <none>
Namespaces:
langfuse: error running kopia backup... context canceled
Started: 2026-02-05 03:00:33 +0900 KST
Completed: 2026-02-05 07:07:54 +0900 KST
Duration: 4h7m21s

4시간이 걸렸는데 실패한 볼륨도 있다. 백업이 이렇게 오래 걸리면 안 된다.

FSB 목록 확인

Terminal window
$ velero backup describe daily-backup-20260204 --details | grep "^ " | wc -l
132

132개의 볼륨을 FSB로 백업하고 있었다. 목록을 보니 문제가 바로 보였다.

gitlab/gitlab-gitaly-0[repo-data]
gitlab/gitlab-gitaly-0[etc-ssl-certs] # ?
gitlab/gitlab-gitaly-0[gitaly-config] # ?
gitlab/gitlab-gitaly-0[init-gitaly-0] # ?
langfuse/langfuse-xxx[tmp] # ?
observability/prometheus-xxx[web-config] # ?
...

repo-data, data 같은 실제 데이터 볼륨 외에 etc-ssl-certs, tmp, gitaly-config 같은 볼륨들이 전부 백업되고 있었다.


원인 분석

defaultVolumesToFsBackup: true

Velero Helm Chart의 기본 설정을 확인해보니:

# velero values.yaml
configuration:
defaultVolumesToFsBackup: true

이 설정이 true모든 Pod의 모든 볼륨이 FSB 대상이 된다. ConfigMap 마운트, Secret 마운트, emptyDir까지 전부.

132개 볼륨의 정체

분류개수설명
실제 데이터 (PVC)~40postgresql, redis, gitaly 등
ConfigMap/Secret~30ssl-certs, config 등
emptyDir~30tmp, shm, cache 등
기타~30init containers, sidecar 등

PVC 44개를 백업하려다 132개를 백업하고 있었다.

PartiallyFailed 원인

ClickHouse 백업이 context canceled로 실패했다.


해결 방안: opt-in vs opt-out

Velero FSB는 두 가지 방식을 지원한다.

opt-out (기본값)

# 전역 설정
defaultVolumesToFsBackup: true
# 제외할 볼륨 지정
podAnnotations:
backup.velero.io/backup-volumes-excludes: "tmp,ssl-certs,config"

모든 볼륨을 백업하고, 불필요한 것만 제외한다.

opt-in

# 전역 설정
defaultVolumesToFsBackup: false
# 백업할 볼륨 지정
podAnnotations:
backup.velero.io/backup-volumes: "data"

아무것도 백업하지 않고, 필요한 것만 지정한다.

어떤 방식이 좋을까?

기준opt-outopt-in
새 볼륨 추가 시자동 백업됨 (안전)수동 추가 필요
불필요한 백업발생 가능없음
설정 관리제외 목록 관리포함 목록 관리
명확성뭐가 백업되는지 불명확백업 대상이 명확

132개 중 90개를 exclude하는 것보다 40개를 include하는 게 훨씬 명확하다. opt-in 방식을 선택했다.


적용

Velero 설정 변경

velero.yaml
configuration:
defaultVolumesToFsBackup: false # opt-in으로 변경
# schedule.yaml
spec:
schedule: "0 18 * * *"
template:
snapshotVolumes: false
defaultVolumesToFsBackup: false
ttl: 72h # 3일 보관

서비스별 annotation 추가

각 서비스의 Helm values에 백업 대상 볼륨을 명시적으로 지정했다.

gitlab.yaml
gitlab:
gitaly:
podAnnotations:
backup.velero.io/backup-volumes: "repo-data"
postgresql:
primary:
podAnnotations:
backup.velero.io/backup-volumes: "data"
langfuse.yaml
postgresql:
primary:
podAnnotations:
backup.velero.io/backup-volumes: "data"

백업 대상 목록

최종적으로 12개 볼륨만 백업하도록 설정했다.

서비스백업 볼륨이유
GitLab Gitalyrepo-dataGit 저장소
GitLab PostgreSQLdata메타데이터
Langfuse PostgreSQLdata트레이스 데이터
ClearML Elasticsearchclearml-elastic-master실험 데이터
DefectDojo PostgreSQLdata취약점 데이터
SonarQube PostgreSQLdata코드 분석 결과
Trivydata취약점 DB
Airflow Schedulerlogs실행 로그
Airflow MinIOexport내부 스토리지
Garagemeta, data오브젝트 스토리지
Grafanastorage대시보드

Prometheus와 Redis는 제외했다. Prometheus는 30일 retention으로 17.5GB나 차지하는데 메트릭은 재생성된다. Redis(Valkey 포함)는 세션/캐시 용도라 손실되어도 자동 재빌드된다.


결과

Before vs After

항목BeforeAfter개선
FSB 볼륨 수13212-91%
백업 시간4시간3분-99%
백업 크기~11GB4.4GB-60%
상태PartiallyFailedCompleted정상화
Terminal window
$ velero backup describe daily-backup-20260205
Phase: Completed
Started: 2026-02-06 03:00:28 +0900 KST
Completed: 2026-02-06 03:03:41 +0900 KST
Duration: 3m13s

4시간에서 3분으로. 백업이 정상화되었다.

스토리지 절약

Before: 11GB/일 × 7일 = 77GB
After: 4.4GB/일 × 3일 = 13.2GB

기존 기본 TTL 7일에서 3일로 줄여서 스토리지 사용량이 83% 감소했다.


정리

defaultVolumesToFsBackup: true는 “일단 다 백업하자”는 안전한 선택처럼 보이지만, 실제로는 emptyDir, ConfigMap 마운트, init 볼륨까지 전부 포함시킨다. 132개 중 실제 PVC 기반은 40개뿐이었고, 나머지 90개가 시간과 스토리지를 낭비하고 있었다.

opt-in으로 전환하고 나니 백업 대상이 명확해졌다. 각 서비스의 Helm values에 annotation이 선언되어 있으니, 어떤 볼륨이 백업되는지 코드만 보면 알 수 있다. 새 서비스를 추가할 때도 annotation을 넣을지 말지 의식적으로 판단하게 된다.


참고 자료

관련 콘텐츠

댓글