
쓰던 Velero 백업 파이프라인이 restic 기반이면 슬슬 갈아탈 때가 됐다. v1.15에서 restic이 deprecated로 마킹된 게 작년 말이고, v1.16에서는 새로운 file system backup의 기본 업로더가 Kopia다. 거기다 PV 백업 흐름 자체도 CSI snapshot data movement 쪽으로 무게추가 옮겨가는 중이라, 운영 환경을 그대로 두면 1~2년 안에 업그레이드 경로에서 발이 묶일 수 있다.
이 글은 EKS 클러스터에서 돌아가는 restic 기반 Velero를 Kopia + CSI data mover 조합으로 옮기는 실전 절차다. 우리 팀이 노드 50대짜리 프로덕션 클러스터에서 한 달에 걸쳐 진행한 작업을 정리한 거라, 가능한 단계마다 함정도 같이 적었다.
왜 지금 옮겨야 하는가
restic 자체가 나쁜 도구는 아니다. 잘 동작하고, 우리도 2년 가까이 별 사고 없이 썼다. 그런데 Velero가 손을 떼고 있는 게 명확하다. 1.15부터 새 설치는 Kopia가 기본이고, 1.16에서는 restic uploader가 새 백업 생성에서 disabled로 바뀌고 있다. Velero 로드맵상 1.18쯤에서 restic path가 완전히 제거될 전망인데, 이건 곧 "복구는 가능한데 새 백업은 못 만든다"는 시점이 온다는 뜻이다.
그래서 우선순위는 두 가지다.
첫째, Kopia 기반 file system backup으로 옮긴다. 둘째, EBS CSI snapshot이 가능한 PV는 가능한 한 CSI snapshot data movement로 백업 경로를 바꾼다. 둘은 별개 작업처럼 보이지만 실제로는 같은 v1.16 설정 안에서 같이 진행하는 게 자연스럽다.
사전 준비
기존 환경늤 상태부터 정리한다.
# 현재 Velero 버전 확인
velero version
# restic 데몬셋이 떠 있는지 확인
kubectl -n velero get ds restic
# 진행 중인 백업/스케줄
velero backup get
velero schedule get
# Backup Storage Location의 prefix 구조 파악
velero backup-location get -o yaml
restic은 BSL 안에 restic/ prefix로 데이터를 쌓는다. Kopia로 옮긴 뒤에도 기존 restic 백업의 복구는 한동안 유지해야 하므로, BSL을 새로 만드는 게 아니라 같은 버킷 안에서 prefix 분리만 잘하면 된다. 새 백업은 kopia/ prefix로 들어간다.
S3 권한 점검은 잊지 말 것. IRSA로 묶어 둔 Velero ServiceAccount의 IAM policy에 s3:GetObject, s3:PutObject, s3:DeleteObject, s3:ListBucket은 당연히 있을 텐데, CSI snapshot data movement까지 쓰려면 ec2:CreateSnapshot, ec2:DescribeSnapshots, ec2:DeleteSnapshot 권한이 추가로 필요하다. EBS CSI Driver 쪽 권한이 충분한지 같이 확인한다.
단계 1: Velero를 1.16으로 업그레이드
업그레이드 자체는 Helm이면 그냥 차트 버전만 올리면 된다. 다만 values에 손볼 게 좀 있다.
# values.yaml
image:
tag: v1.16.0
deployNodeAgent: true # 과거 deployRestic 자리를 대체
nodeAgent:
podVolumePath: /var/lib/kubelet/pods
privileged: false
initContainers:
- name: velero-plugin-for-aws
image: velero/velero-plugin-for-aws:v1.12.0
volumeMounts:
- mountPath: /target
name: plugins
configuration:
uploaderType: kopia # 핵심: 기본 업로더를 명시
defaultVolumesToFsBackup: false # opt-in 방식 권장
features: EnableCSI # CSI snapshot 사용
defaultSnapshotMoveData: false # 일단 false로 시작
deployRestic는 옛 키워드이고, 1.16에서는 deployNodeAgent가 같은 데몬셋을 띄운다. 이름이 바뀌었을 뿐 컨테이너 안에서는 Kopia와 restic 둘 다 들어 있어서, prefix와 메타데이터에 따라 알맞은 쪽이 실행된다. 즉, 마이그레이션 기간에는 두 종류의 백업이 공존할 수 있다.
업그레이드 후 첫 확인:
kubectl -n velero get pods
# velero-... Running
# node-agent-... Running (각 노드마다)
# uploader 확인
kubectl -n velero exec deploy/velero -- velero version
# Server Version: v1.16.0
여기서 node-agent가 일부 노드에서 안 뜨면 십중팔구 hostPath 마운트 문제다. EKS의 경우 /var/lib/kubelet/pods가 디폴트인데, Bottlerocket 같은 AMI를 쓰면 경로가 다를 수 있다. kubectl describe node에서 kubeletRoot 비슷한 키를 확인하면 된다.
단계 2: 새 백업을 Kopia로 만들기
기존 스케줄을 갑자기 죽이면 안 된다. 병행 운영부터 한다.
# 새 스케줄을 별도로 생성 (Kopia 기반)
velero schedule create daily-kopia \
--schedule="0 17 * * *" \
--include-namespaces=production,staging \
--default-volumes-to-fs-backup=false \
--snapshot-volumes=true \
--ttl 720h
--default-volumes-to-fs-backup=false로 두면 PV는 기본적으로 CSI snapshot 경로로 간다. file system backup이 필요한 PV(EFS, NFS 등)만 pod annotation으로 opt-in한다.
# pod metadata
annotations:
backup.velero.io/backup-volumes: "logs,uploads"
이렇게 하면 EBS PV들은 CSI snapshot, 명시한 볼륨은 Kopia file system backup으로 갈라진다. 첫 백업은 일부러 작은 네임스페이스 하나만 잡아서 돌려본다.
velero backup create kopia-smoke-1 \
--include-namespaces=test-sandbox \
--default-volumes-to-fs-backup=true
velero backup describe kopia-smoke-1 --details
Backup Item Operations에 PodVolumeBackup이 Kopia로 처리됐다는 게 보이면 성공이다. 우리 팀에서는 첫 시도에서 backup이 PartiallyFailed로 떨어졌는데, 원인은 node-agent의 메모리 limit이었다. restic은 200~300Mi로도 잘 돌았는데 Kopia는 PV가 크면 1Gi 가까이 먹는다. limit을 2Gi로 올리고 다시 돌리니 깔끔하게 끝났다.
단계 3: CSI snapshot data movement 켜기
PV 백업을 진짼 EBS snapshot으로 뺽u�고, 그걔 S3로 올기는 흐름이다. snapshot이 같은 계정/리전에 갇혀 있으면 DR 관점에서 의미가 적기 때문에 data movement까지 쓰는 게 맞다.
VolumeSnapshotClass에 Velero 라벨이 붙어 있어야 한다.
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: ebs-csi-velero
labels:
velero.io/csi-volumesnapshot-class: "true"
driver: ebs.csi.aws.com
deletionPolicy: Retain
parameters:
tagSpecification_1: "Name=velero-{{ .VolumeSnapshotContentName }}"
deletionPolicy: Retain이 중요하다. 처음에 별생각 없이 Delete로 두고 운영하다가, backup TTL이 만료될 때 snapshot�� 같이 날아가서 백업 자체가 문횀화되는 사고를 한 번 겪안다. Velero가 data movement 로 S3에 옮긴 뒤에는 EBS snapshot은 정리해도 되째拌, 그건 Velero가 자기 라이프사이큼로 관리하게 두는 것 안전하다.
이된 백업에 data movement 를 활성화한다.
velero backup create csi-mover-1 \
--include-namespaces=production-api \
--snapshot-move-data=true
snapshot-move-data 옵션을 켜면 EBS snapshot을 뜬 뒤 Velero가 그 snapshot에서 데이터를 읽어 Kopia repository로 S3에 저장한다. 진행 상황은 DataUpload 리소스로 확인할 수 있다.
kubectl -n velero get datauploads.velero.io
# NAME STATUS STARTED ...
# csi-mover-1-abcde Completed ...
여기서 자주 막히는 곳이 두 군데다. 하나는 VolumeSnapshotClass 라벨 누락(위에서 처리). 다른 하나는 dataMover pod이 뜨는 노드에서 PVC 마운트가 안 되는 케이스다. Velero는 dataMover pod을 임시로 띄워서 snapshot을 마운트하는데, 이 pod이 가용 영역 매칭이 안 되면 멈춘다. EBS는 같은 AZ에서만 마운트되므로, EKS 클러스터의 AZ가 여러 개인 경우 dataMover pod의 nodeSelector나 affinity를 조정하지 않아도 Velero가 알아서 해주는 게 정상인데, 특이한 노드 taint를 걸어둔 환경에서는 nodeAgent.podConfig.tolerations를 손봐야 한다.
단계 4: 옛 restic 백업 정리
새 파이프라인이 한 주 정도 안정적으로 돌아가면 옛 스케줄을 제거한다.
velero schedule delete daily-restic
이미 만들어진 restic 백업은 손대지 말 것. Velero 1.16은 prefix를 보고 어느 uploader로 복구해야 할지 자동 판단한다. 그래서 적어도 TTL이 끝날 때까지는 그대로 두고, 마지막 restic 백업의 TTL이 지난 뒤에 BSL 안의 restic/ prefix를 정리하면 된다. 미리 지우면 만약의 복구가 막힌다.
복구 테스트를 한 번씩 돌려보는 것도 권장한다.
# Kopia 백업으로 복구
velero restore create --from-backup csi-mover-1 \
--namespace-mappings production-api:production-api-restore
# 옛 restic 백업도 한 번 더 (남아 있는 동안)
velero restore create --from-backup daily-restic-20260601-...
두 경로 모두 동작하는 게 확인되면 일단 마이그레이션은 끝났다고 봐도 된다.
운영 중 부딪힌 자잘한 것들
Kopia repository는 처음 한 번 init이 일어나는데, 이 단계가 느리거나 실패하면 첫 백업이 길게 멈춰 보인다. kubectl -n velero logs deploy/velero | grep repository로 확인하면 된다.
restic 시절에는 prune이 별도 명령이었는데, Kopia는 백그라운드에서 자체 maintenance가 돈다. 처음 몇 일은 S3 비용이 좀 출렁일 수 있다. 우리는 마이그레이션 첫 주에 일일 S3 PUT 요청靴 평소 대비 1.6배쯤 올라갔다가 안정화됐다.
진짜로 가끔 일어나는 일인데, node-agent가 OOMKilled로 주으면 PodVolumeBackup이 멈춘 상태로 남는다. backup describe 상에는 InProgress로 영원히 떠 있어서 헷갈린다. velero backup logs <name>을 봐서 timeout이나 OOM 흔적이 보이면 그 백업은 그냥 cancel하고 limit 올린 뒤 다시 돌리는 게 빠르다.
마지막으로, 우리 환경에서 한 가지 더 발견한 건 EKS 1.30 이상에서 volumeAttachment 정리가 늦어지는 경우다. data mover pod이 끝난 뒤에 PVC가 즉시 해제 안 되면서 다음 백업이 충돌하는 식이었는데, 이건 EBS CSI Driver 쪽 이슈로 보였고 컨트롤러 버전을 v1.36 이상으로 올려서 정리됐다.
정리
요약하면, 결국 두 줄이다. 새 백업 uploader는 Kopia, EBS PV 백업은 가능하면 CSI snapshot data movement. 둘 다 v1.16에 들어 있고, 옛 restic 백업을 죽이지 않은 상태에서 점진적으로 옮길 수 있다.
restic 완전 제거 시점이 언제일지는 Velero 릴리스 노트를 따로 챙겨보면 좋다. 우리는 분기에 한 번씩 릴리스 노트를 훑고, deprecated 표시된 기능에 한 분기 정도 유예를 두고 옮기는 식으로 운영 중이다.
'IT > Kubernets' 카테고리의 다른 글
| kubectl events, 아직도 get events 쓰세요? (0) | 2026.06.26 |
|---|---|
| ndots:5 한 줄이 클러스터를 무릎 꿇린 새벽 (0) | 2026.06.26 |
| kubectl .kuberc, 팀 kubeconfig 안 건드리고 내 alias 관리하기 (0) | 2026.06.25 |
| Cilium vs Calico, 2026년에 새 클러스터를 만든다면 (0) | 2026.06.24 |
| PreStop sleep, 아직도 sh -c 'sleep 10' 쓰시나요 (0) | 2026.06.23 |