K8s를 사용하다보면 PersistentVolumeClaim(PVC)과 PersistentVolume(PV)가 분리되어 있는 것을 보면서 그 이유가 늘 궁금했는데, K8s를 좀 사용하다보니 분리되어 있는 이유나 구조 설계의 철학을 조금 알게 된 것 같다.
K8s에서 볼륨을 사용하려면 번거롭지만 PVC와 PV라는 두 개의 설정을 같이 해줘야 한다.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: public-html-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Gi
volumeName: public-html-pv
storageClassName: ""
apiVersion: v1
kind: PersistentVolume
metadata:
name: public-html-pv
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /home/user/public_html
주의사항
PV부터 먼저 적용(apply)해야 한다.
서비스 하나가 볼륨 하나를 필요로 한다면 PVC와 PV 설정이 한 벌씩 필요한 셈이다. 이렇게 대응되는 관계라면 굳이 PVC는 왜 필요한가?
우선 PVC와 PV는 위치가 다르다.
PVC는 개별 namespace 안에 속하고, PV는 namespace 외부에 존재한다. K8s 클러스터 전체의 공유 자원이라고 할 수 있다.
PVC는 개별 namespace 안에서 특정 서비스를 위한 "볼륨을 사용하겠다는 권리"라는 개념적인 객체로 존재한다. 반면, 서비스 입장에서 PV는 데이터가 실제로 저장되는 볼륨 객체로 인식된다.
PVC와 PV는 N:1의 관계로서 여러 PVC가 하나의 PV를 공유해서 사용할 수 있다.
어떤 서비스를 배포할 때 helm chart를 이용하는 경우가 많다. helm chart는 볼륨 사용이 필요한 경우 PVC를 포함하고 있는데, 설치 대상이 되는 K8s 클러스터마다 어떤 PV를 어떻게 물리적인 볼륨에 연결해서 제공할지가 달라지게 된다.
helm chart를 개발하는 애플리케이션 개발자는 PVC까지만 선언하고, PV는 K8s 클러스터를 관리하는 인프라 운영자가 제공하는 식으로 역할을 나눌 수 있다.
PV는 K8s 클러스터 바깥의 실제(물리적) 스토리지에 직접 대응되는 개념이라서 함부로 삭제되면 안 된다. 연결된 PVC가 유효한 상황에서 PV를 삭제하려고 하면 실패하게 된다. 반드시 PVC가 먼저 제거되어 PV와의 연결이 끊긴 이후에 PV를 삭제할 수 있다.
PV가 Bound 상태에서 Released나 Available 상태로 바뀐 후에 삭제가 가능하다.
실수로 사용 중인 PV를 삭제하는 건 어렵다. 늘 PVC를 먼저 삭제해야 PV를 삭제할 수 있다. 다시 말해, "볼륨을 사용하겠다는 권리"를 먼저 포기하고 철회해야 "볼륨에 대한 사용"을 삭제할 수 있는 것이다.