목차
- 안녕하세요, 13년차의 서버실입니다!
- 1. 쿠버네티스 영구 스토리지, 왜 필요하고 어떻게 작동하나요?
- PersistentVolume (PV, 영구 볼륨): 물리적인 스토리지 자원
- PersistentVolumeClaim (PVC, 영구 볼륨 요청): 애플리케이션의 스토리지 요구
- StorageClass (스토리지 클래스): 스토리지 프로비저닝 자동화
- CSI (Container Storage Interface) 드라이버: 쿠버네티스와 스토리지 연결 고리
- 2. CSI 드라이버를 활용한 영구 스토리지 설정하기 (NFS CSI 드라이버 예시)
- 2.1. NFS CSI 드라이버 배포
- 2.2. StorageClass 생성
- 2.3. PersistentVolumeClaim (PVC) 생성
- 2.4. Pod에서 PVC 사용
- 3. 삽질 경험담: CSI 드라이버 사용 시 주의사항과 트러블슈팅
- 3.1. ⚠️ Access Modes (접근 모드) 이해하기
- 3.2. ⚠️ Reclaim Policy (회수 정책) 신중하게 설정하기
- 3.3. 네트워크 연결 문제 (NFS 예시)
- 3.4. CSI 드라이버 설치 버전 호환성
- 4. CSI 드라이버를 통한 영구 스토리지 관리의 성과
- 5. 마무리하며: 쿠버네티스 스토리지, CSI 드라이버로 마스터하기
안녕하세요, 13년차의 서버실입니다!
저는 인프라 엔지니어로 일하면서 수많은 서버실을 드나들었고, 홈랩에서도 다양한 기술을 직접 실험해보고 있거든요. 특히 쿠버네티스(Kubernetes)를 운영하면서 가장 머리 아팠던 부분 중 하나가 바로 스토리지(Storage) 문제였습니다.
컨테이너는 Stateless(무상태)여야 한다지만, 실제 애플리케이션은 데이터가 필요하잖아요? DB나 파일 서버 같은 것들 말이죠. 컨테이너가 죽거나 재시작하면 데이터가 홀라당 날아가 버리는 경험... 혹시 해보셨나요? 제가 그랬거든요, 처음엔. 😭
그래서 오늘은 쿠버네티스 환경에서 데이터를 안전하게 보관하고 관리하는 핵심 기술인 CSI (Container Storage Interface) 드라이버를 활용한 영구 스토리지(Persistent Storage) 관리 및 최적화 방법에 대해 제 경험을 바탕으로 솔직하게 이야기해보려고 합니다. 💡
쿠버네티스에서 스토리지가 어떻게 연결되는지 전반적인 아키텍처를 보여주는 다이어그램입니다. CSI 드라이버가 핵심 역할을 하는 것을 볼 수 있습니다.
1. 쿠버네티스 영구 스토리지, 왜 필요하고 어떻게 작동하나요?
쿠버네티스에서 애플리케이션이 데이터를 영구적으로 저장하려면 몇 가지 핵심 개념을 알아야 합니다. 쉽게 말해, 컨테이너는 휘발성(Ephemeral)이라서 데이터를 저장해도 컨테이너가 사라지면 데이터도 같이 사라져요. 그래서 컨테이너 외부에 데이터를 안전하게 보관할 수 있는 공간이 필요한데, 이걸 영구 스토리지(Persistent Storage)라고 부릅니다.
PersistentVolume (PV, 영구 볼륨): 물리적인 스토리지 자원
PV는 실제 물리적인 스토리지 공간, 예를 들면 네트워크 파일 시스템(NFS)의 특정 디렉터리나 클라우드 제공자의 디스크(AWS EBS, Google Persistent Disk 등)를 추상화한 겁니다. 클러스터 관리자가 미리 정의해두죠. 마치 서버실의 빈 하드디스크 같은 개념이랄까요? PV는 특정 스토리지 솔루션과 연결되어 실제 데이터를 저장하는 역할을 합니다.
PersistentVolumeClaim (PVC, 영구 볼륨 요청): 애플리케이션의 스토리지 요구
PVC는 Pod(파드)가 사용할 스토리지의 "요구 사항"을 선언하는 겁니다. "나는 10GiB(기가바이트) 용량의 ReadWriteOnce(한 번에 한 Pod만 쓰기 가능) 모드의 스토리지가 필요해!" 하고 요청하는 거죠. 사용자가 빈 하드디스크를 "내 거"라고 찜하는 것과 비슷합니다. Pod는 PV에 직접 접근하는 대신 PVC를 통해 스토리지를 요청하고 사용합니다.
StorageClass (스토리지 클래스): 스토리지 프로비저닝 자동화
여기서부터 좀 더 편리해집니다. StorageClass는 스토리지의 "종류"를 정의하는 템플릿이라고 보시면 돼요. 예를 들어, "빠른 SSD 스토리지", "저렴한 HDD 스토리지", "백업용 스토리지" 같은 거죠. StorageClass를 사용하면 PVC가 요청할 때 PV를 자동으로 생성(Dynamic Provisioning)해줍니다. 제가 처음엔 PV를 일일이 만들었었는데, StorageClass 덕분에 삽질을 훨씬 줄일 수 있었어요. 이거 진짜 편하더라고요! ✅
StorageClass는 어떤 CSI 드라이버를 사용할지, 어떤 볼륨 타입(SSD/HDD), 회수 정책(reclaim policy) 등을 정의합니다.
CSI (Container Storage Interface) 드라이버: 쿠버네티스와 스토리지 연결 고리
자, 오늘의 주인공입니다! CSI 드라이버는 쿠버네티스가 다양한 외부 스토리지 시스템(NFS, Ceph, AWS EBS, OpenEBS 등)과 통신할 수 있도록 표준화된 인터페이스를 제공합니다. 스토리지 벤더들은 이 CSI 표준에 맞춰 드라이버를 개발하고, 쿠버네티스는 이 드라이버를 통해 어떤 스토리지든 일관된 방식으로 사용할 수 있게 되는 거죠. 마치 USB 포트에 어떤 장치를 꽂아도 표준 드라이버 덕분에 작동하는 것과 비슷하다고 보시면 됩니다. 덕분에 쿠버네티스가 특정 스토리지 솔루션에 종속되지 않고 유연하게 확장될 수 있더라고요. 💡
2. CSI 드라이버를 활용한 영구 스토리지 설정하기 (NFS CSI 드라이버 예시)
제가 홈랩에서 가장 많이 쓰는 방식 중 하나가 바로 NFS (Network File System)를 이용한 영구 스토리지입니다. 간편하고 설정하기도 쉬워서 처음 시작하는 분들께도 추천드려요. 여기서는 NFS CSI 드라이버를 예시로 들어볼게요.
(⚠️ 사전에 NFS 서버가 구성되어 있고, 쿠버네티스 클러스터에서 접근 가능해야 합니다.)
2.1. NFS CSI 드라이버 배포
먼저 NFS CSI 드라이버를 쿠버네티스 클러스터에 배포해야 합니다. 보통 Helm 차트나 manifests 파일을 통해 배포하죠. 저는 안정적인 버전의 Helm 차트를 선호하는 편입니다.
저는 보통 프로젝트 공식 저장소에서 제공하는 Helm 차트 가이드를 따라 설치합니다. Kubernetes-CSI 프로젝트의 NFS CSI 드라이버를 설치하는 방법을 보여드릴게요.
helm repo add csi-driver-nfs https://kubernetes-csi.github.io/csi-driver-nfs
helm repo update
helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system
배포가 완료되면, 다음과 같이 CSI 드라이버 관련 Pod들이 잘 올라왔는지 확인해볼 수 있습니다.
kubectl get pods -n kube-system -l app.kubernetes.io/name=csi-driver-nfs
2.2. StorageClass 생성
이제 이 CSI 드라이버를 사용할 StorageClass를 정의합니다. NFS 서버의 주소와 공유할 경로를 지정해줘야 해요.
# nfs-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-csi-storage
provisioner: nfs.csi.k8s.io # CSI 드라이버의 이름
parameters:
server: 192.168.1.100 # 여러분의 NFS 서버 IP 주소로 변경하세요!
share: /mnt/nfs_share # NFS 서버의 공유 경로로 변경하세요!
reclaimPolicy: Delete # Pod 삭제 시 PV도 함께 삭제 (Retain으로 하면 수동 삭제 필요)
volumeBindingMode: Immediate
mountOptions:
- hard
- nfsvers=4.1
이 파일을 적용하면 <code>nfs-csi-storage라는 이름의 StorageClass가 생성됩니다.
kubectl apply -f nfs-storageclass.yaml
StorageClass를 정의하는 YAML 파일의 예시입니다. NFS CSI 드라이버를 이용해 스토리지 클래스를 생성하는 과정을 보여줍니다.
2.3. PersistentVolumeClaim (PVC) 생성
이제 애플리케이션이 스토리지 1GiB를 요청할 PVC를 만들어봅시다.
# my-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-nfs-pvc
spec:
accessModes:
- ReadWriteOnce # 한 Pod만 읽기/쓰기 가능
storageClassName: nfs-csi-storage # 위에서 생성한 StorageClass 이름 지정
resources:
requests:
storage: 1Gi # 1 기가바이트 스토리지 요청
적용하면 자동으로 PV가 프로비저닝됩니다. 정말 편해졌죠?
kubectl apply -f my-pvc.yaml
kubectl get pvc my-nfs-pvc
kubectl get pv
PVC가 Bound 상태가 되고, 그에 맞는 PV가 생성된 것을 확인할 수 있을 겁니다. 🎉
2.4. Pod에서 PVC 사용
마지막으로, 이 PVC를 사용할 Pod를 생성합니다. 간단한 Nginx Pod를 예시로 들어볼게요.
# nginx-pod-with-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-with-nfs
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: nfs-storage
mountPath: /usr/share/nginx/html # Nginx의 웹 루트에 마운트
volumes:
- name: nfs-storage
persistentVolumeClaim:
claimName: my-nfs-pvc # 위에서 생성한 PVC 이름 지정
이제 이 Pod를 배포하고, /usr/share/nginx/html 경로에 파일을 생성해보세요. Pod가 재시작되어도 데이터가 유지되는 것을 확인할 수 있을 겁니다!
kubectl apply -f nginx-pod-with-pvc.yaml
kubectl exec -it nginx-with-nfs -- bash
echo "Hello from NFS CSI!" > /usr/share/nginx/html/index.html
exit
# Pod를 삭제했다가 다시 만들어도 데이터가 유지되는지 확인해보세요.
kubectl delete pod nginx-with-nfs
kubectl apply -f nginx-pod-with-pvc.yaml
kubectl exec -it nginx-with-nfs -- cat /usr/share/nginx/html/index.html
정상적으로 "Hello from NFS CSI!"라는 문구가 보인다면 성공입니다! 드디어 됐다! 🎉
3. 삽질 경험담: CSI 드라이버 사용 시 주의사항과 트러블슈팅
제가 이 과정을 거치면서 몇 번이고 머리를 쥐어뜯었던 경험이 있습니다. 여러분은 저 같은 삽질을 하지 마시라고 몇 가지 팁을 드릴게요.
3.1. ⚠️ Access Modes (접근 모드) 이해하기
PVC를 만들 때 accessModes를 지정하는데, 이게 꽤 중요합니다.
- ReadWriteOnce (RWO): 단일 Pod만 읽기/쓰기 가능. (가장 흔함)
- ReadOnlyMany (ROX): 여러 Pod가 읽기만 가능.
- ReadWriteMany (RWX): 여러 Pod가 읽기/쓰기 가능. (NFS 같은 공유 파일 시스템에서 주로 사용)
만약 RWX가 필요한데 RWO로 설정하면, 다른 Pod에서 접근이 안 돼서 문제가 생길 수 있습니다. 특히 클라우드 볼륨(EBS 같은)은 대부분 RWO만 지원하므로, RWX가 필요하면 NFS나 CephFS 같은 공유 파일 시스템 기반 CSI 드라이버를 고려해야 해요. 제가 이 부분에서 많이 헷갈렸었죠.
3.2. ⚠️ Reclaim Policy (회수 정책) 신중하게 설정하기
StorageClass에 reclaimPolicy를 Delete로 설정하면, PVC가 삭제될 때 연결된 PV와 실제 스토리지 볼륨도 함께 삭제됩니다. 개발 환경에서는 편하지만, 실제 운영 환경에서는 데이터가 날아갈 수 있으니 주의해야 합니다!
저는 처음에 이걸 모르고 테스트용 DB를 날려먹을 뻔했어요... 다행히 백업이 있었지만요. 😅
운영 환경에서는 Retain으로 설정해서 PVC 삭제 시 PV만 삭제하고, 실제 볼륨은 수동으로 관리하는 것을 고려해봐야 합니다. 아니면 백업 정책을 철저히 해야겠죠.
3.3. 네트워크 연결 문제 (NFS 예시)
NFS CSI 드라이버를 사용할 경우, 쿠버네티스 노드들이 NFS 서버에 접근할 수 있는지 확인해야 합니다. 방화벽 문제나 네트워크 경로 설정 문제로 연결이 안 되는 경우가 많거든요. showmount -e [NFS 서버 IP]나 mount 명령어로 직접 마운트 테스트를 해보는 것이 가장 확실합니다.
3.4. CSI 드라이버 설치 버전 호환성
가끔 CSI 드라이버 버전과 쿠버네티스 클러스터 버전 간의 호환성 문제로 말썽을 일으킬 때가 있습니다. CSI 드라이버의 공식 문서를 참조하여 호환되는 버전을 사용하는 것이 중요해요. 최신 버전이 무조건 좋은 건 아니더라고요.
4. CSI 드라이버를 통한 영구 스토리지 관리의 성과
이렇게 CSI 드라이버를 통해 영구 스토리지를 구성하고 나면, 다음과 같은 이점을 얻을 수 있습니다.
- 데이터 영속성 (Data Persistence) 확보: Pod가 죽거나 재시작되어도 데이터는 안전하게 유지됩니다. DB나 상태를 가지는 애플리케이션 운영에 필수적이죠.
- 스토리지 관리의 유연성 (Flexibility): 특정 스토리지 벤더에 종속되지 않고, 다양한 스토리지 솔루션을 쿠버네티스에서 일관된 방식으로 사용할 수 있습니다.
- 운영 효율성 (Operational Efficiency) 증대: StorageClass를 통한 동적 프로비저닝(Dynamic Provisioning) 덕분에 스토리지 할당 및 관리가 자동화되어 운영 부담이 크게 줄어듭니다. 제가 직접 PV를 일일이 만들던 시절을 생각하면 정말 격세지감이죠. 😮
- 확장성 (Scalability): 필요한 만큼 스토리지를 손쉽게 확장하거나 축소할 수 있게 됩니다.
실제로 제가 운영하는 서비스에서도 CSI 드라이버 덕분에 안정적으로 데이터를 관리하고, 필요에 따라 스토리지를 유연하게 변경하거나 확장할 수 있게 되었어요. K8s 스토리지 최적화의 첫걸음이라고 할 수 있습니다.
쿠버네티스 클러스터에서 PV, PVC, StorageClass 등의 스토리지 리소스 상태를 모니터링하는 대시보드의 예시입니다.
5. 마무리하며: 쿠버네티스 스토리지, CSI 드라이버로 마스터하기
오늘은 쿠버네티스 환경에서 영구 스토리지를 관리하고 최적화하는 데 필수적인 CSI 드라이버에 대해 제 경험을 바탕으로 이야기해보았습니다. PersistentVolume(PV), PersistentVolumeClaim(PVC), StorageClass, 그리고 CSI 드라이버라는 핵심 개념들이 처음에는 복잡하게 느껴질 수 있지만, 몇 번 직접 구성해보면 금방 익숙해지실 거예요.
특히 StorageClass와 CSI 드라이버를 활용한 동적 프로비저닝은 쿠버네티스 운영의 편의성을 극대화시켜주는 정말 강력한 기능이라고 생각합니다. 저의 삽질 경험담이 여러분의 K8s 스토리지 여정에 작은 도움이 되었으면 좋겠네요. 🤝
다음번에는 CephFS나 Rook-Ceph 같은 분산 스토리지 솔루션을 CSI 드라이버와 함께 사용하는 방법에 대해서도 다뤄볼 기회가 있었으면 좋겠습니다. 궁금한 점이나 공유하고 싶은 경험이 있다면 댓글로 남겨주세요! 저는 13년차의 서버실이었습니다. 감사합니다!
다양한 쿠버네티스 영구 스토리지 솔루션(NFS, Ceph, 클라우드 볼륨 등)의 특징과 장단점을 비교하는 인포그래픽입니다.
'IT > k8s' 카테고리의 다른 글
| [k8s] Kubernetes Operator 활용 사례: 데이터베이스 관리 자동화로 운영 효율 높이기 (0) | 2026.05.23 |
|---|---|
| [k8s] Helm 차트 관리의 진화: GitOps 시대의 베스트 프랙티스 분석 (0) | 2026.05.23 |
| [k8s] AWX로 쿠버네티스 워크플로우 자동화: 실전 가이드 (0) | 2026.05.21 |
| [k8s] ArgoCD로 멀티 클러스터 GitOps 배포 자동화 완벽 가이드 (0) | 2026.05.20 |
| [k8s] 쿠버네티스 Ingress Controller 비교: Nginx, Traefik, HAProxy 장단점 분석 (0) | 2026.05.18 |
| [k8s] ArgoCD GitOps CI/CD 구축: 쿠버네티스 자동 배포 완벽 가이드 (0) | 2026.05.18 |