본문 바로가기
DevOps/Kubernates

[k8s] Kubernetes Storage 완전 정복: PV, PVC, StorageClass 개념 정리

by BenKangKang 2025. 7. 14.

Kubernetes를 사용하다 보면 애플리케이션에서 데이터를 저장하기 위해 스토리지를 사용하는 일이 필수적으로 발생합니다. 이를 위해 Kubernetes는 PersistentVolume (PV), PersistentVolumeClaim (PVC), 그리고 StorageClass라는 개념을 도입했습니다. 이 포스트에서는 각 개념을 상세히 정리하고, 이들이 어떻게 상호작용하는지, 어떤 상황에서 각각을 사용하는지를 설명하겠습니다.


📦 1. Persistent Volume (PV)란?

**PersistentVolume(PV)**는 클러스터 관리자가 미리 구성한 스토리지 리소스입니다. 이는 쿠버네티스 클러스터의 일부 리소스로 존재하며, 사용자에게 제공되는 스토리지와는 독립적인 객체입니다.

🔹 특징

  • PV는 NFS, iSCSI, AWS EBS, GCE Persistent Disk 등 다양한 스토리지 백엔드를 지원합니다.
  • Pod에 종속되지 않고 독립적으로 존재합니다.
  • 수동(manual) 또는 동적(dynamic)으로 생성할 수 있습니다.

🔹 예시

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-example
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /mnt/data

🧾 2. Persistent Volume Claim (PVC)란?

**PersistentVolumeClaim(PVC)**는 사용자가 필요한 스토리지를 요청하는 객체입니다. 일종의 스토리지 요청서로 이해할 수 있습니다.

🔹 특징

  • 원하는 용량(storage)과 접근 방식(accessMode)을 지정하여 요청합니다.
  • PVC가 생성되면 Kubernetes는 조건에 맞는 PV를 바인딩하거나, StorageClass를 통해 자동으로 PV를 생성합니다.

🔹 예시

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-example
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

🏷️ 3. StorageClass란?

StorageClass는 동적 프로비저닝(dynamic provisioning)을 위해 사용됩니다. 사용자가 PVC를 생성할 때 storageClassName을 명시하면, 해당 StorageClass에 정의된 방식으로 PV가 자동으로 생성됩니다.

🔹 주요 요소

  • provisioner: 실제 볼륨을 생성하는 드라이버 예: kubernetes.io/aws-ebs, kubernetes.io/gce-pd 등
  • parameters: 해당 프로비저너에 전달되는 설정값들

🔹 예시

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-storage
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2

PVC 예시:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-fast
spec:
  storageClassName: fast-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

🔄 이들의 관계

  1. 관리자가 PV를 수동 생성하거나, StorageClass를 통해 자동 생성되도록 설정
  2. 사용자는 PVC를 통해 필요한 스토리지를 요청
  3. Kubernetes는 조건에 맞는 PV를 PVC에 바인딩
  4. Pod는 PVC를 volumeMount로 사용하여 실제 스토리지에 접근

⚠️ 주의할 점

  • AccessModes에 주의: ReadWriteOnce(RWO), ReadOnlyMany(ROX), ReadWriteMany(RWX) 중 어떤 접근 방식이 필요한지 명확히 해야 함
  • PVC가 요청한 용량보다 작은 PV는 바인딩되지 않음
  • StorageClass는 기본값이 존재할 수 있으며, 이를 지정하지 않으면 default StorageClass가 사용됨

 Pod에서 PVC 마운트하는 실전 예제

PVC는 단독으로는 의미가 없고, Pod가 해당 PVC를 마운트하여 실제 애플리케이션에서 사용해야 의미가 있습니다.

📁 예시: NGINX에서 PVC 마운트하기

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: web-content
  volumes:
    - name: web-content
      persistentVolumeClaim:
        claimName: pvc-example

✅ 주요 포인트

  • volumeMounts.mountPath: 컨테이너 내부에 마운트될 경로
  • volumes.persistentVolumeClaim.claimName: 앞서 생성한 PVC 이름

이 설정을 통해 애플리케이션 재시작 시에도 데이터가 보존됩니다.


동적 vs 정적 프로비저닝 실습

🧱 정적 프로비저닝

  1. 관리자가 직접 PV 생성
  2. 사용자가 PVC로 요청
  3. 조건이 맞으면 바인딩

장점: 세부 설정 제어 가능
단점: 자동화가 어렵고 오퍼레이션 부담

⚙️ 동적 프로비저닝

  1. 사용자가 PVC 생성하면서 storageClassName 지정
  2. Kubernetes가 PV를 자동 생성

장점: 자동화에 적합, 클라우드 환경과 잘 어울림
단점: 프로비저너 설정이 필요, 내부 스토리지에는 부적합할 수 있음

📘 실습 비교

항목 정적 프로비저닝 동적 프로비저닝

PV 생성 수동 (kubectl apply) 자동
StorageClass 필요
클라우드 환경 적합
온프레미스 적합

⚡ 3. StorageClass 별 성능 비교 및 테스트

💡 목적

어떤 StorageClass가 애플리케이션의 성능에 가장 적합한지 파악합니다.

🧪 테스트 조건

  • AWS EBS 기준 (gp2, gp3, io1 비교)
  • fio 툴을 사용한 read/write throughput 측정
  • 블록 사이즈: 4KB / 1MB
  • 작업량: 1GB

📊 결과 예시

StorageClass IOPS (4KB, read) IOPS (4KB, write) MB/s (1MB, seq read) MB/s (1MB, seq write)

gp2 3000 2800 120 110
gp3 5000 5000 180 170
io1 (provisioned 10000) 9500 9200 230 225

📝 결론

  • gp3는 비용 대비 성능이 뛰어나 대부분의 워크로드에 적합
  • io1/io2는 고성능 DB 등에 유리하나 비용이 큼
  • 성능이 중요한 워크로드는 반드시 사전 테스트 권장

🎯 정리 및 팁

  • Pod에 PVC 마운트 시, readOnly: true/false 옵션도 조정 가능
  • StorageClass 성능은 클라우드 벤더/리전/환경에 따라 다를 수 있음
  • 테스트 자동화를 위한 Job 배포도 고려해보자 (fio Pod 실행 등)

🔚 마무리

PV, PVC, StorageClass는 Kubernetes에서 영속 스토리지를 다루기 위한 핵심 개념입니다. 이들을 잘 이해하고 구성하면 Stateful Application 운영이 훨씬 수월해집니다.

 

댓글