엔지니어링단일 노드 k3s의 PVC 보존 정책과 데이터 복구 한계
· 핀로그
- #kubernetes
- #storage
- #persistence
- #recovery
쿠버네티스에서 데이터를 다루다 보면 “PVC를 붙였으니 남는다”는 말로 설명을 끝내기 쉽습니다. 하지만 무엇이 사라진 뒤에도 남는다는 뜻일까요? 컨테이너가 다시 뜨는 상황과 PVC를 지우는 상황, 서버의 디스크를 잃는 상황은 서로 다릅니다. 핀로그의 저장 구성을 살펴보면서 중요하게 본 것도 이 구분이었습니다.
핀로그는 AWS의 단일 노드에서 k3s의 제어 영역과 워크로드를 함께 실행하고 있었습니다. k3s는 가볍게 만든 Kubernetes 배포판입니다.
문제
“PVC를 붙였으니 남는다”는 설명은 Pod 재시작, PVC 삭제, 노드 손실을 구분하지 않았다. 핀로그는 단일 노드에서 PostgreSQL의 data·backup PVC를 같은 로컬 저장소에 두고 있었다.
결정
저장 구성을 세 상황으로 나눠 읽었다. StorageClass 이름 대신 PV의 실제 reclaim policy를 보고, 삭제 정책과 복구 절차를 따로 확인했다.
결과
Retain은 PVC 삭제 뒤 자동 정리만 막을 뿐, 같은 노드의 backup PVC로는 노드 손실에 대비할 수 없다는 점을 확인했다. 호스트 밖 사본과 복구 절차는 별도로 설계하고 확인해야 할 다음 단계로 남았다.
남는 대상부터 구분
Pod는 실행 단위이고, PVC는 저장 공간을 요청하는 객체입니다. 그 요청에 연결된 실제 저장 자원을 쿠버네티스에서는 PV로 표현합니다. 애플리케이션이 PVC로 연결된 볼륨에 데이터를 쓰면, 데이터의 수명을 컨테이너의 수명과 분리할 수 있습니다. 컨테이너 안의 아무 경로에 쓴 파일이 전부 보존되는 것은 아니에요.
Pod가 재시작되거나 교체되더라도 PVC가 유지되고, 그 PVC가 가리키는 디스크가 살아 있으며 다시 접근할 수 있어야 기존 데이터를 사용할 수 있습니다. 로컬 저장소라면 데이터가 있는 노드라는 조건도 따라옵니다. 실행을 다시 시작하는 것과 저장 장치를 다시 확보하는 것은 다른 문제입니다.
StorageClass 비교
StorageClass는 볼륨을 어떤 방식으로 만들지 정해 둔 종류이고, reclaim policy는 PVC가 삭제된 뒤 볼륨을 어떻게 처리할지 정한 규칙입니다. 기본 StorageClass인 local-path의 reclaim policy는 Delete였고, local-path-retain은 Retain이었습니다. 둘 다 노드의 로컬 저장소를 사용하지만, PVC가 삭제된 뒤 볼륨을 어떻게 처리할지에 차이가 있습니다.
local-path · Delete
PVC 삭제로 볼륨이 해제되면 PV와 기반 저장소를 삭제하는 정책입니다. 실제 정리는 이를 처리하는 프로비저너의 동작을 따릅니다.
local-path-retain · Retain
PVC가 삭제되어도 PV와 기반 데이터를 자동 정리하지 않고 남깁니다. 이후 재사용이나 정리는 운영자가 처리해야 합니다.
정확히는 reclaim policy가 적용되는 대상은 PV입니다. 동적으로 만들어지는 PV가 StorageClass의 정책을 물려받는 구조죠. 따라서 중요한 볼륨을 확인할 때는 클래스 이름만 보지 말고 해당 PV의 실제 정책까지 봐야 합니다. StorageClass 설정을 바꾸는 것만으로 이미 만들어진 모든 PV의 정책이 함께 바뀌지는 않습니다.
여기서 Retain을 “PVC를 지워도 자동 복구된다”로 읽으면 안 됩니다. PVC 객체 자체를 보존하는 기능이 아니고, 남은 PV도 새로운 PVC에 저절로 다시 연결되는 것은 아닙니다. 삭제에 따른 자동 정리를 멈추는 정책이지, 데이터를 찾아 애플리케이션에 다시 붙여 주는 복구 절차는 아니에요.
바인딩 시점의 문제
두 클래스의 volume binding mode는 모두 WaitForFirstConsumer였습니다. PVC를 만들자마자 볼륨의 위치를 확정하기보다, 이를 사용할 Pod의 스케줄링 조건을 고려해 바인딩과 동적 프로비저닝을 진행하는 방식입니다. 로컬 볼륨의 위치와 Pod가 실행될 노드가 어긋나지 않도록 하는 데 의미가 있습니다.
PVC 요청
사용할 StorageClass를 지정소비자 Pod
스케줄링 조건을 함께 고려볼륨 연결
선택된 노드의 로컬 저장소 사용
이는 연결 시점과 배치에 관한 설정입니다. 기다렸다 연결한다고 해서 복제본이 생기거나, 다른 서버로 데이터가 이동하지는 않습니다. 단일 노드 구성에서는 스케줄링을 고려해도 저장 위치가 그 노드 바깥으로 나가는 것은 아닙니다.
같은 경계의 데이터와 백업
PostgreSQL의 data PVC와 backup PVC는 물론, 상태를 저장하는 다른 PVC도 모두 local-path-retain을 사용했습니다. PostgreSQL뿐 아니라 다른 상태도 Pod의 수명과 분리되어 있었습니다.
단일 노드의 저장 경계
PostgreSQL의 data와 backup이 별도 PVC라는 점은 용도를 구분해 줍니다. 하지만 PVC가 둘이라는 사실과 장애 영역이 둘이라는 사실은 같지 않습니다. 같은 노드의 로컬 저장소에 의존한다면, 노드나 그 저장 장치 전체를 잃는 문제를 Retain만으로 해결할 수 없습니다. 볼륨 이름에 backup이 들어가는지도 이 경계를 바꾸지 못합니다.
그래서 백업은 저장 공간의 존재 다음을 확인해야 합니다. 어떤 데이터가 언제 생성되는지, 원본 호스트 밖에도 사본이 있는지, 그 사본으로 서비스를 다시 구성할 수 있는지가 별개의 질문입니다. 같은 노드에 백업용 공간을 마련하는 것과 off-host 복구 경로를 갖추는 것은 다른 단계입니다.
삭제 정책과 복구 절차의 분리
Retain은 PVC 삭제가 곧바로 데이터 정리로 이어지는 것을 막는 데 의미가 있습니다. 대신 남은 볼륨을 누가 관리하고 언제 재사용하거나 정리할지 책임이 남습니다. 보존에 유리한 정책을 적용했다고 해서 운영 작업이 사라지는 것은 아닙니다.
이 구성을 설명할 때의 결론은 “영속 볼륨이 있으니 안전하다”가 아니었습니다. Pod 재시작에는 유지된 PVC와 살아 있는 디스크가, PVC 삭제에는 PV의 reclaim policy가, 호스트 전체 손실에는 호스트 밖의 데이터와 복구 절차가 필요합니다. 같은 ‘데이터 보존’이라는 말 아래 묶기에는 조건이 너무 다릅니다.
저장소를 볼 때 먼저 물어야 할 것은 “어디까지 없어져도 다시 시작할 수 있는가?”였습니다. PVC는 실행과 데이터의 수명을 분리해 주고, Retain은 삭제 뒤 정리 방식을 바꿉니다. 그다음 경계인 호스트 밖 복구는 별도로 설계하고 확인해야 합니다.