
파드(Pod)는 기본적으로 일시적인(ephemeral) 존재이기 때문에 파드가 재시작되면 내부의 데이터는 사라진다. 이를 방지하고 데이터를 영구적으로 저장하기 위해 볼륨을 사용한다. 특히, 영구 볼륨(Persistent Volume, PV)과 영구 볼륨 클레임(Persistent Volume Claim, PVC)은 동적으로 스토리지를 할당하고 관리하는 핵심적인 방법이다.
영구 볼륨 클레임(PVC)은 사용자가 필요한 스토리지(영구 볼륨)를 요청하는 리소스이다.
관리자가 미리 생성해 둔 여러 영구 볼륨(PV) 중에서, PVC가 요청하는 조건(용량, 접근 모드, 레이블 등)에 가장 적합한 PV를 쿠버네티스 스케줄러가 찾아 할당(바인딩)해준다.
PVC를 정의할 때 설정 가능한 주요 항목은 다음과 같다. 이 값들은 매칭될 영구 볼륨(PV)에 먼저 정의되어 있어야 한다.
레이블 셀렉터 (Label Selector): 특정 레이블을 가진 PV에만 바인딩되도록 지정한다.
용량 (Capacity): 요청할 스토리지의 크기를 지정한다. 요청하는 용량은 대상 PV의 용량보다 작거나 같아야 한다.
접근 모드 (Access Modes): 볼륨에 대한 접근 방식을 정의한다.
ReadWriteOnce (RWO): 단일 노드에서만 읽기/쓰기 가능
ReadOnlyMany (ROX): 여러 노드에서 읽기 전용으로 마운트 가능
ReadWriteMany (RWX): 여러 노드에서 읽기/쓰기 가능
스토리지 클래스 (Storage Class): 프로비저닝할 스토리지의 유형(예: ssd, hdd)을 정의한다.
YAML 예시: sample-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: sample-pvc
spec:
# 레이블 셀렉터를 사용하여 특정 PV를 타겟팅
selector:
matchLabels:
type: gce-pv
matchExpressions:
- key: environment
operator: In
values:
- stg
# 접근 모드 지정
accessModes:
- ReadWriteOnce
# 리소스 요청
resources:
requests:
storage: 3Gi
# 특정 스토리지 클래스 지정 (정적 프로비저닝 시)
storageClassName: manual
리소스 생성: kubectl apply -f sample-pvc.yaml
리소스 확인: kubectl get persistentvolumeclaim 또는 kubectl get pvc
Bound 상태는 적절한 PV를 찾아 성공적으로 할당되었음을 의미한다. Pending 상태는 조건에 맞는 PV가 없어 할당 대기 중임을 의미한다.Retain 정책과 재할당: PV의 persistentVolumeReclaimPolicy가 Retain으로 설정된 경우, 해당 PV에 연결된 PVC를 삭제하면 PV의 상태는 Bound에서 Released로 변경된다. 이 상태의 PV는 다른 PVC에서 재사용할 수 없다. (수동으로 정리 후 재사용 가능)
파드 스펙의 spec.volumes 섹션에 persistentVolumeClaim을 정의하고, 사용할 컨테이너의 volumeMounts에 연결하여 사용한다.
YAML 예시: sample-pvc-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-pvc-pod
spec:
containers:
- name: nginx-container
image: nginx:1.16
volumeMounts:
- mountPath: "/usr/share/nginx/html" # 컨테이너 내부의 마운트 경로
name: nginx-pvc # 사용할 볼륨의 이름
volumes:
- name: nginx-pvc # 볼륨의 이름
persistentVolumeClaim:
claimName: sample-pvc # 사용할 PVC의 이름
정적 프로비저닝(Static Provisioning) 방식에서는 관리자가 사전에 여러 크기의 PV를 미리 만들어 두어야 한다. 이는 PVC 요청 용량과 정확히 일치하지 않아 스토리지 자원 낭비를 유발할 수 있다.
동적 프로비저닝은 이러한 문제를 해결하기 위해, PVC가 생성되는 시점에 요청에 맞는 PV를 자동으로 생성하는 기능이다. 이를 통해 필요한 만큼의 용량만 정확히 할당하여 자원 낭비를 최소화한다.
동적 프로비저닝을 사용하려면, 어떤 종류의 스토리지를 동적으로 생성할지 정의하는 스토리지 클래스(StorageClass) 리소스가 반드시 필요하다.
YAML 예시: sample-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: sample-storageclass
provisioner: kubernetes.io/gce-pd # 어떤 스토리지 플러그인을 사용할지 지정 (예: GCE 영구 디스크)
parameters:
type: pd-ssd # 스토리지 유형 (예: SSD)
reclaimPolicy: Delete # PVC가 삭제될 때 PV와 실제 스토리지도 함께 삭제
PVC를 생성할 때 storageClassName을 지정하면, 해당 스토리지 클래스가 정의한 방식에 따라 PV가 자동으로 생성된다. 이때 생성되는 PV의 이름은 보통 pvc-<랜덤-UID> 형식을 따른다.
YAML 예시: sample-pvc-dynamic.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: sample-pvc-dynamic
spec:
# 동적 프로비저닝을 위해 StorageClass 이름 지정
storageClassName: sample-storageclass
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
StatefulSet은 데이터베이스와 같이 상태 유지가 중요한 워크로드를 위한 리소스이다. 각 파드가 고유한 상태와 식별자를 가지므로, 영구 데이터 영역을 사용하는 경우가 많다.
StatefulSet은 spec.volumeClaimTemplates 항목을 제공하여, 각 파드(Replica)에 대한 PVC를 자동으로 생성하고 바인딩해준다.
volumeClaimTemplates에 정의된 내용을 기반으로 (템플릿이름)-(파드이름) 형식의 PVC가 파드 수만큼 생성된다.
컨테이너 내부의 volumeMounts에 volumeClaimTemplates의 metadata.name을 지정하기만 하면 자동으로 연결된다.
YAML 예시: sample-statefulset-with-pvc.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sample-statefulset-with-pvc
spec:
serviceName: stateful-with-pvc
replicas: 2
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: sample-pvc
image: nginx:1.16
volumeMounts:
- name: pvc-template-volume # volumeClaimTemplates의 이름과 일치해야 함
mountPath: /tmp
# 이 템플릿을 기반으로 각 파드에 대한 PVC가 자동으로 생성됨
volumeClaimTemplates:
- metadata:
name: pvc-template-volume
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: sample-storageclass
kubectl apply -f sample-statefulset-with-pvc.yaml 명령을 실행하면 replicas: 2에 따라 2개의 파드와 2개의 PVC가 자동으로 생성된다.