Network & Server Factory

개인 공부 기록

DevOps/Kubernetes

[Kubernetes] Volume, PV, PVC, StorageClass 정리

1nfra 2026. 9. 28. 17:00
Pod 안에서 쓴 파일은 Pod가 다시 만들어지면 사라지므로, 남겨야 하는 데이터는 Pod 밖의 저장소에 둬야 합니다. 이 글에서는 Pod에 붙이는 Volume의 종류, 저장소를 요청하는 PVC와 실제 저장소인 PV, 저장소를 자동으로 만들어 주는 StorageClass의 관계를 정리하고, 9편의 Redis에 PVC를 붙여 데이터가 남는지 확인합니다.

컨테이너부터 Kubernetes까지 시리즈 10편입니다. 이전 글은 [Kubernetes] ConfigMap과 Secret 정리이고, 전체 순서는 시리즈 목차에 있습니다.

1. Pod의 Volume

2편에서 본 것처럼 컨테이너가 쓴 파일은 쓰기 계층에 남고 컨테이너와 함께 사라집니다. Kubernetes에서는 Pod가 수시로 다시 만들어지므로 이 문제가 더 자주 드러납니다. 그래서 Pod의 spec.volumes에 저장소를 정의하고, 컨테이너의 volumeMounts로 원하는 경로에 붙여 씁니다. 9편에서 ConfigMap을 /etc/redis에 붙인 것도 Volume의 한 종류입니다.

 

종류 데이터 수명 용도
emptyDir Pod가 지워지면 함께 삭제
컨테이너 재시작에는 유지
캐시, 같은 Pod 컨테이너끼리 파일 공유
configMap, secret 원본 리소스를 따름 설정 파일, 인증서(9편)
hostPath 노드 디스크에 남지만 Pod가 다른 노드로 가면 볼 수 없음 노드 관리용 에이전트, 일반 앱에는 쓰지 않음
persistentVolumeClaim Pod와 상관없이 PVC를 지울 때까지 유지 DB 등 남겨야 하는 데이터

2. PV, PVC, StorageClass

남겨야 하는 데이터는 PVC를 씁니다. 앱을 배포하는 사람은 "1Gi, 한 노드에서 읽고 쓰기"처럼 필요한 저장소를 PVC로 요청하기만 하고, 실제 디스크가 로컬 디스크인지 Azure Disk인지는 몰라도 됩니다. 도서관에 비유하면 PVC는 대출 신청서, PV는 실제로 빌려준 책, StorageClass는 신청이 들어오면 책을 새로 구해 오는 구매 담당입니다.

PVC가 만들어지면 StorageClass의 provisioner가 디스크와 PV를 만들어 PVC에 연결(Bound)합니다

 

리소스 역할 누가 만드나
PVC 필요한 크기, 접근 방식, StorageClass를 적은 요청서
네임스페이스에 속함
앱 배포 담당
PV 실제 저장소 하나를 나타내는 리소스
클러스터 전체에 속함
대부분 StorageClass가 자동 생성
StorageClass 저장소 종류와 만드는 방법(provisioner), 반납 정책을 정의 클러스터 관리자

3. 접근 방식과 반납 정책

PVC를 만들 때는 접근 방식(accessModes)을 고르고, StorageClass에는 PVC를 지웠을 때 PV를 어떻게 할지(reclaimPolicy)와 언제 PV를 만들지(volumeBindingMode)가 정해져 있습니다.

 

설정 값과 의미
accessModes ReadWriteOnce(RWO): 노드 하나에서 읽고 쓰기
ReadOnlyMany(ROX): 여러 노드에서 읽기만
ReadWriteMany(RWX): 여러 노드에서 읽고 쓰기
ReadWriteOncePod(RWOP): Pod 하나에서만 읽고 쓰기
reclaimPolicy Delete: PVC를 지우면 PV와 실제 디스크도 삭제
Retain: PV와 디스크를 남기고 관리자가 직접 정리
volumeBindingMode Immediate: PVC를 만들자마자 PV 생성
WaitForFirstConsumer: PVC를 쓰는 Pod의 노드가 정해진 뒤 그 노드에 맞춰 생성

 

어떤 accessModes를 쓸 수 있는지는 저장소 종류가 정합니다. 예를 들어 AKS에서 Azure Disk는 RWO만 되고, 여러 노드에서 함께 써야 하면 Azure Files를 씁니다.

4. 직접 해 보기

kind에는 standard라는 기본 StorageClass가 들어 있습니다.

kubectl get storageclass

PROVISIONER는 rancher.io/local-path, RECLAIMPOLICY는 Delete, VOLUMEBINDINGMODE는 WaitForFirstConsumer로 나옵니다. local-path는 노드 컨테이너 안의 /var/local-path-provisioner 폴더를 PV로 만들어 주는 학습용 provisioner입니다. 이제 1Gi짜리 PVC를 만듭니다. storageClassName을 적지 않으면 기본 StorageClass가 쓰입니다.

# redis-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-data
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 1Gi
kubectl apply -f redis-pvc.yaml
kubectl get pvc

STATUS가 Bound가 아니라 Pending입니다. WaitForFirstConsumer라서 이 PVC를 쓰는 Pod가 생길 때까지 PV를 만들지 않고 기다리는 것이고, kubectl describe pvc redis-data의 이벤트에도 waiting for first consumer로 나옵니다.

 

9편의 redis.yaml에 PVC를 붙입니다. 바뀌는 부분만 보면 아래와 같습니다. Redis 이미지는 /data에 데이터를 쓰므로 그 경로에 붙이고, RWO 디스크를 두 Pod가 동시에 잡지 않도록 업데이트 방식을 Recreate로 바꿉니다.

spec:
  strategy:
    type: Recreate
  template:
    spec:
      containers:
      - name: redis
        volumeMounts:
        - name: config
          mountPath: /etc/redis
        - name: data
          mountPath: /data
      volumes:
      - name: config
        configMap:
          name: redis-config
      - name: data
        persistentVolumeClaim:
          claimName: redis-data
kubectl apply -f redis.yaml
kubectl get pvc,pv
kubectl exec deploy/redis -- sh -c 'redis-cli -a "$REDIS_PASSWORD" --no-auth-warning set visits 10'

Pod가 뜨면서 PVC가 Bound로 바뀌고, pvc-로 시작하는 이름의 PV가 자동으로 만들어집니다. 이제 Pod를 지워서 새 Pod가 같은 데이터를 보는지 확인합니다.

kubectl delete pod -l app=redis
kubectl exec deploy/redis -- sh -c 'redis-cli -a "$REDIS_PASSWORD" --no-auth-warning get visits'

새 Pod에서도 "10"이 나옵니다. 4편에서 Docker 볼륨으로 한 실험을 Kubernetes에서 다시 한 것입니다. kubectl get pv -o yaml로 PV를 보면 nodeAffinity에 노드 이름이 적혀 있습니다. local-path는 특정 노드의 폴더라서 이 Redis Pod는 앞으로 그 노드에만 배치됩니다. 실제 운영의 네트워크 디스크는 노드가 바뀌면 디스크를 떼어 다른 노드에 붙여 줍니다.

5. 운영 시 주의점

항목 조치
reclaimPolicy Delete PVC를 지우면 디스크까지 삭제됨
중요한 데이터는 Retain StorageClass를 쓰거나 PV의 정책을 Retain으로 변경
RWO와 롤링 업데이트 새 Pod가 다른 노드에 뜨면 디스크를 붙이지 못해 멈출 수 있음
Recreate 전략을 쓰거나 StatefulSet 사용
DB 운영 Pod마다 자기 PVC가 필요한 복제 DB는 Deployment가 아닌 StatefulSet(volumeClaimTemplates)으로 구성
용량 늘리기 StorageClass에 allowVolumeExpansion: true가 있어야 PVC 크기를 늘릴 수 있음
줄이는 것은 불가
백업 PV도 결국 디스크 하나이므로 장애나 실수로 지울 수 있음
VolumeSnapshot이나 DB 자체 백업으로 따로 보관

6. 정리

  • emptyDir는 Pod와 함께 사라지고, 남겨야 하는 데이터는 PVC로 요청한 PV에 둡니다.
  • PVC를 만들면 StorageClass의 provisioner가 PV와 실제 디스크를 만들어 연결하고, WaitForFirstConsumer면 Pod의 노드가 정해진 뒤에 만듭니다.
  • 기본 reclaimPolicy는 대부분 Delete라서 PVC를 지우면 데이터도 지워지므로, 중요한 데이터는 Retain과 별도 백업으로 보호합니다.

다음 글 11편에서는 Pod가 쓸 CPU와 메모리를 정하는 requests와 limits, 그리고 부하에 따라 Pod 수를 자동으로 늘리고 줄이는 HPA를 다룹니다.

참고

728x90
서울
--:--:--
-전체 글
-카테고리
오늘 방문