Theme:

컨테이너를 재시작하면 내부 데이터가 사라지는데, 데이터베이스처럼 데이터를 영구 보존해야 하는 경우에는 어떻게 해야 할까요?

컨테이너의 파일 시스템은 기본적으로 임시(ephemeral)입니다. Pod이 재시작되거나 다른 노드로 이동하면 데이터가 사라집니다. Kubernetes는 PersistentVolume(PV)과 PersistentVolumeClaim(PVC)으로 Pod의 라이프사이클과 독립적인 영속 스토리지를 제공합니다.

PV와 PVC의 개념

  • PV (PersistentVolume): 클러스터 수준의 스토리지 리소스. 관리자가 미리 준비하거나 동적으로 생성됩니다.
  • PVC (PersistentVolumeClaim): Pod이 스토리지를 요청하는 수단. 네임스페이스에 속합니다.

이 분리 설계의 핵심은 관심사 분리입니다. 인프라 관리자는 스토리지를 프로비저닝하고(PV), 개발자는 필요한 스토리지를 요청(PVC)하기만 하면 됩니다.

PLAINTEXT
관리자: PV 생성 (스토리지 종류, 용량, 접근 모드)
개발자: PVC 생성 (필요한 용량, 접근 모드)
Kubernetes: PV-PVC 바인딩 → Pod에서 사용

Static Provisioning — PV를 미리 생성

YAML
# 1단계: 관리자가 PV 생성
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:                    # 로컬 테스트용
    path: /mnt/data
---
# 2단계: 개발자가 PVC 생성
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual     # PV의 storageClassName과 일치
---
# 3단계: Pod에서 PVC 사용
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
    - name: app
      image: my-app:1.0
      volumeMounts:
        - name: data
          mountPath: /app/data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: my-pvc

바인딩 과정

PVC가 생성되면 Kubernetes는 조건에 맞는 PV를 찾아 바인딩합니다.

바인딩 조건:

  • 용량: PVC가 요청한 크기 이상의 PV
  • accessModes: PVC가 요청한 모드를 PV가 지원
  • storageClassName: PVC와 PV의 storageClassName이 일치
  • 레이블 셀렉터: PVC에 selector가 있으면 해당 조건
SHELL
# PV 상태 확인
kubectl get pv
# NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM
# my-pv   10Gi       RWO            Retain           Bound    default/my-pvc

# PVC 상태 확인
kubectl get pvc
# NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES
# my-pvc   Bound    my-pv    10Gi       RWO

PV의 상태 전이는 다음과 같습니다.

PLAINTEXT
Available → Bound → Released → (Available 또는 삭제)

accessModes

모드약어설명사용 사례
ReadWriteOnceRWO단일 노드에서 읽기/쓰기대부분의 블록 스토리지
ReadOnlyManyROX여러 노드에서 읽기 전용설정 파일, 정적 자산
ReadWriteManyRWX여러 노드에서 읽기/쓰기NFS, CephFS, EFS
ReadWriteOncePodRWOP단일 Pod에서만 읽기/쓰기데이터베이스 (1.22+)

주의: accessModes는 동시 접근을 제어하지, 단일 Pod 내 권한을 제어하는 것이 아닙니다.

reclaimPolicy

PVC가 삭제되었을 때 PV를 어떻게 처리할지 결정합니다.

정책동작사용 사례
RetainPV와 데이터 보존, 수동 정리 필요프로덕션 데이터
DeletePV와 실제 스토리지 자동 삭제개발/테스트 환경
Recycle데이터만 삭제(rm -rf) 후 재사용 (deprecated)-
YAML
spec:
  persistentVolumeReclaimPolicy: Retain  # 프로덕션 권장

프로덕션 환경에서는 반드시 Retain을 사용하세요. Delete를 사용하면 PVC 삭제 시 데이터가 복구 불가능하게 삭제됩니다.

Dynamic Provisioning

StorageClass를 사용하면 PVC 생성 시 자동으로 PV가 생성됩니다. 관리자가 미리 PV를 만들 필요가 없어 운영이 편해집니다.

YAML
# StorageClass 정의
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  iops: "3000"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
---
# PVC만 생성하면 PV가 자동 생성됨
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: fast-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 20Gi
SHELL
# PV가 자동으로 생성되어 바인딩됨
kubectl get pvc fast-pvc
# NAME       STATUS   VOLUME                                     CAPACITY
# fast-pvc   Bound    pvc-a1b2c3d4-e5f6-7890-abcd-ef1234567890   20Gi

볼륨 확장

StorageClass에서 allowVolumeExpansion: true를 설정하면 PVC의 용량을 늘릴 수 있습니다.

YAML
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: expandable
provisioner: ebs.csi.aws.com
allowVolumeExpansion: true  # 확장 허용
SHELL
# PVC 용량 확장
kubectl patch pvc my-pvc -p '{"spec":{"resources":{"requests":{"storage":"30Gi"}}}}'

축소는 지원하지 않으며, 파일 시스템 확장을 위해 Pod 재시작이 필요할 수 있습니다.

PV/PVC 디버깅

SHELL
# PVC가 Pending인 경우 — 적합한 PV가 없음
kubectl describe pvc my-pvc
# Events:
#   waiting for a volume to be created, either by external provisioner...

# PV 상태 확인
kubectl get pv --sort-by=.spec.capacity.storage

# 사용 중인 볼륨 확인
kubectl get pvc --all-namespaces

# PV가 Released 상태에서 재사용하려면
# 1. PV의 claimRef를 제거
kubectl patch pv my-pv -p '{"spec":{"claimRef": null}}'

실무에서 주의할 점

  • PVC 삭제 전에 reclaimPolicy를 확인하세요: Delete 정책이면 실제 데이터가 삭제됩니다
  • RWO는 노드 제한이 있습니다: Pod이 다른 노드로 이동하면 볼륨이 따라가지 못할 수 있습니다
  • WaitForFirstConsumer: Pod이 스케줄된 노드에서 볼륨을 생성하여 AZ 불일치를 방지합니다
  • StatefulSet의 PVC: StatefulSet 삭제 시 PVC는 자동으로 삭제되지 않습니다

정리

PV는 실제 스토리지를, PVC는 스토리지 요청을 나타내며, Kubernetes가 조건에 맞는 PV-PVC를 바인딩합니다. 동적 프로비저닝을 사용하면 PVC만 생성하면 되어 운영이 편해지고, reclaimPolicy와 accessModes를 올바르게 설정하는 것이 데이터 안전성의 핵심입니다.

댓글 로딩 중...