Skip to main content

Storage — PV, PVC, StorageClass

컨테이너는 일시적이지만 데이터는 영구적이어야 한다


1. K8s 스토리지 모델

1.1 왜 별도 스토리지인가

컨테이너의 파일시스템은 임시적(ephemeral). 컨테이너가 재시작되면 데이터가 사라짐. DB, 로그, 설정 등 영속 데이터를 위해 별도 스토리지가 필요함.

1.2 추상화 계층

flowchart TB
App["애플리케이션<br/>(Pod)"]
App -->|"Volume Mount"| PVC["PVC<br/>(사용자 요청)"]
PVC -->|"바인딩"| PV["PV<br/>(실제 스토리지)"]
PV --> Backend["스토리지 백엔드<br/>(NFS, Ceph, EBS, local)"]

SC["StorageClass"] -->|"동적 생성"| PV
오브젝트역할비유
PV실제 스토리지 리소스물리 디스크
PVC사용자의 스토리지 요청"10GB 디스크 주세요"
StorageClass동적 프로비저닝 정책"요청하면 자동으로 만들어 줌"

2. Volume 유형

유형생명주기용도
emptyDirPod와 동일임시 캐시, Pod 내 컨테이너 간 공유
hostPath노드노드 로컬 파일 접근 (⚠️ 위험)
configMap / secret오브젝트와 동일설정/인증 주입
PV/PVC독립적✅ 영구 데이터

⚠️ hostPath는 프로덕션에서 지양. 특정 노드에 종속되어 Pod가 다른 노드로 이동하면 데이터에 접근할 수 없음.


3. PV & PVC

3.1 정적 프로비저닝

관리자가 PV를 미리 생성하고, 사용자가 PVC로 요청하면 매칭.

# PV (관리자)
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.10.10.50
path: /exports/data
---
# PVC (사용자)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi

3.2 Access Mode

모드약자설명
ReadWriteOnceRWO하나의 노드에서만 읽기/쓰기
ReadOnlyManyROX여러 노드에서 읽기만
ReadWriteManyRWX여러 노드에서 읽기/쓰기
ReadWriteOncePodRWOP하나의 Pod에서만 (K8s 1.22+)

3.3 Reclaim Policy

PVC가 삭제되었을 때 PV를 어떻게 처리할지:

정책동작
RetainPV 보존 (수동 정리). 데이터 안전
DeletePV + 백엔드 스토리지 자동 삭제
Recycle❌ 폐지됨

4. StorageClass & 동적 프로비저닝

4.1 왜 동적 프로비저닝인가

정적: 관리자가 PV를 미리 만들어야 함 → 비효율 동적: PVC 생성 시 StorageClass가 자동으로 PV를 만듦

# StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-rbd
provisioner: rbd.csi.ceph.com # CSI 드라이버
parameters:
clusterID: my-ceph-cluster
pool: kubernetes
reclaimPolicy: Delete
allowVolumeExpansion: true
---
# PVC (StorageClass 지정)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-data
spec:
storageClassName: ceph-rbd # ← StorageClass 참조
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
# → PV가 자동 생성되고 PVC에 바인딩됨

4.2 기본 StorageClass

# 기본 StorageClass 확인
kubectl get storageclass
# NAME PROVISIONER RECLAIMPOLICY DEFAULT
# ceph-rbd rbd.csi.ceph.com Delete ✅

# storageClassName을 생략하면 기본 StorageClass가 사용됨

5. CSI (Container Storage Interface)

스토리지 플러그인의 표준 인터페이스. 벤더가 CSI 드라이버를 만들면 K8s에서 해당 스토리지를 사용할 수 있음.

CSI 드라이버스토리지Proxmox 관련
Ceph CSICeph RBD, CephFS✅ Proxmox Ceph 연동
NFS CSINFS✅ Proxmox NFS
AWS EBS CSIAWS EBS
Longhorn분산 블록 (Rancher)
OpenEBS로컬 디스크 기반

6. StatefulSet + PVC

StatefulSet의 volumeClaimTemplatesPod마다 고유 PVC를 자동 생성.

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres
replicas: 3
template:
spec:
containers:
- name: postgres
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
storageClassName: ceph-rbd
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 20Gi
# → data-postgres-0, data-postgres-1, data-postgres-2 PVC가 자동 생성

Pod가 삭제되어도 PVC는 유지됨 → Pod가 재생성되면 같은 PVC에 다시 연결.


다음 글

→ #6 ConfigMap, Secret & Configuration


📝 참고 자료