-
PV 확장 원리, Kubernetes CSI DriverKubernetes 2025. 7. 9. 19:00
Kubernetes에서의 Volume, File System 확장
AWS를 예로 들자. EC2에서 EBS 등 스토리지를 사용하는 상황에서 볼륨 용량을 늘리려면,
콘솔 등에서 EBS Volume 크기를 조정하고, EC2 인스턴스에서 파티션 및 File System 확장을 했었다.
그렇다면 쿠버네티스에서는 어떤 방법으로 Pod에 연결된 PVC의 PV를 늘릴 수 있는지,
Volume확장과 File System확장은 어떤 과정을 통해 일어나는지 살펴본다.
Persistent Volume Expansion
기존에는 PVC를 확장하려면 PVC 및 PV 삭제/재생성 같은 귀찮은 작업들이 필요했다.
Kubernetes v1.11부터 정식 베타로 Persistent Volume Expansion가 도입되었다.
덕분에 allowVolumeExpansion필드를 True로 설정한 Strorageclass가 있을때,
그 Storageclass를 사용하는 PVC들은 손쉽게 볼륨을 확장할 수 있다.
아래처럼 PVC의 storage 필드(용량 부분)만 수정해주면 간단히 확장이 된다.
다시 말해, 내부적으로 Volume확장과 File System 확장이 일어났다는 것이다.
사진 출처: https://kubernetes.io/blog/2018/07/12/resizing-persistent-volumes-using-kubernetes/
Container Storage Interface (CSI)
PVC만 살짝 수정하면 자동으로 Volume확장과 File System 확장이 일어난다니?
어떻게 그럴 수 있을까를 찾아봤다. 결론부터 말하자면 CSI 드라이버와 kubelet 덕분이다.
CSI는 쿠버네티스같은 Container Orchestration Systems (COs)가 스토리지 시스템에 컨테이너를 노출시키는 표준 인터페이스다. 이 인터페이스는 Identity Service, Controller Service, Node Service로 구성되어 있다.
Controller plugin은 CSI의 Controller Service를 구현한 것이고, Node plugin은 CSI의 Node Service를 구현한 것이다. Identity Service는 두 Plugin에서 모두 구현해야 한다.
쿠버네티스에서 일반적으로 CSI드라이버는 이 plugin을 포함하는 `controller component`, `per-node component`로 배포된다.참고) CSI Spec: https://github.com/container-storage-interface/spec/blob/master/spec.md#rpc-interface
1. Controller Component
CSI의 Controller Service를 구현한 'Controller plugin' & 하나 이상의 'Controller Sidecar' 로 구성되는 컴포넌트이다.
여기서 Sidecar들의 목적은 쿠버네티스 오브젝트와 상호작용하면서 드라이버가 구현한 CSI Controller Service를 호출하는 것이다.
가령, PVC의 Storage 용량을 늘리면 resizer Sidecar가 이를 감지해서 CSI Controller Service에 구현된 ControllerExpandVolume을 호출하는 것이다.
Controller Sidecar 종류는 아래와 같다.
물론 이 외에도 더 있는데, 어떤 Sidecar Conatiner를 포함할지는 Controller개발자가 필요에 따라 선택했을 것이다.- provisioner: PVC 생성 요청 시 볼륨 생성
- attacher: 볼륨을 노드에 attach
- snapshotter: 볼륨 스냅샷 기능 지원
- resizer: PVC 용량 증가 감지 및 확장 요청
이렇게 Controller plugin과 Sidecar들로 구성된 Controller Component는 Deployment나 StaefulSet등 형태로 배포가 된다.
일반적으로 CSI Controller와 같은 이름을 가지는 Pod에 해당한다.
나는 Amazon EBS를 사용하면서 ebs-csi-controller를 사용하고 있는데, 컨테이너 이름을 조회해 보니,
앞서 학습한대로 controller plugin(ebs-plugin)과 Sidecar들을 포함하고 있었다.kubectl get pod ebs-csi-controller-657c7f6895-ffhj7 -n kube-system -o jsonpath="{.spec.containers[*].name}" # ebs-plugin csi-provisioner csi-attacher csi-snapshotter csi-resizer liveness-probe
자세한 구성은 아래 aws-ebs-csi-driver의 helm charts를 참고했다.
https://github.com/kubernetes-sigs/aws-ebs-csi-driver/tree/master/charts/aws-ebs-csi-driver
2. Per-Node Component
CSI의 Node Service를 구현한 'Node Plugin' & 'node-driver-registrar'(Sidecar)로 구성되는 컴포넌트이다.
node-driver-registrar는 Node Plugin을 Kubelet에 등록하기 위한 Sidecar container다. 이를 통해 CSI 드라이버와 gRPC 통신을 할 수 있게 된다. 가령, 볼륨이 확장됐을때 Kubelet이 Node Plugin에 구현된 NodeExpandVolume 요청을 함으로써 실제 파일 시스템 확장(resize2fs 등..)을 하는 등 작업이 가능해지는 것이다.
이 컴포넌트는 kubelet과 상호작용하는 만큼, 워커 노드마다 설치되어야 할 CSI 컴포넌트다. 따라서 DaemonSet을 통한 배포가 적절하다.참고) node-driver-registrar https://kubernetes-csi.github.io/docs/node-driver-registrar
PV Expansion 과정 확인
직접 확장을 해보며 plugin 호출 등 과정을 살펴보았다. 시나리오는 아래와 같다.
1. 사용자가 PVC의 storage 요청량을 증가시킴 (예: 30Gi → 40Gi) ↓ 2. external-resizer(csi-resizer)가 이를 감지 ↓ 3. CSI Controller에게 ControllerExpandVolume RPC 호출 ↓ 4. CSI Controller가 스토리지 백엔드 API 호출 (예: AWS EBS) ↓ 5. 디스크가 확장됨 → PV 객체의 capacity.storage 필드가 업데이트됨 ↓ 6. PVC에 FileSystemResizePending 조건이 추가됨 ↓ 7. Kubelet이 해당 PVC를 사용하는 Pod을 통해 이를 감지 ↓ 8. Kubelet이 CSI Node Plugin에게 NodeExpandVolume RPC 호출 ↓ 9. CSI Node Plugin이 마운트 경로의 파일 시스템을 확장 (resize2fs 등 작업) ↓ 10. PVC의 Status부분이 정상화됨 → 확장 완료
나는 EKS에서 EBS를 사용하는 statefulset Pod 3개를 배포해둔 상태이다.
gp3라는 Storageclass를 사용 중이며, 확장을 위해서는 Storageclass에 allowVolumeExpansion=true가 명시되어 있어야 한다.
기존 pvc는 30Gi를 Claim하고 있는데, 40Gi로 올려보았다.kubectl edit <pvc-name> # storage 부분 수정
Edit 직후에는 status에 allocatedResources부분이 40Gi로 추가되었다.# PVC Edit 후 status를 확인해보자 k get pvc <pvc-name> -oyaml
잠시 기다리면 conditions부분에 type이 FileSystemResizePending으로 바뀌었다.

즉, PV Resizing은 끝난 것이다. 실제로 매칭된 PV를 describe해보면 아래와 같이 확장이 되어있다.
conditions이 FileSystemResizePending이라는 것은
다시 말해, kubelet이 CSI Node Plugin에 NodeExpandVolume요청을 통해 FileSystemResizing을 진행할 차례라는 것이다.
여기서 조금 더 기다려보면 최종적으로 pvc의 capacity가 40Gi로 변경되었고, FileSystemResizePending도 사라졌다.
kubelet이 제 역할을 했음을 유추할 수 있다.
kubelet의 Node Plugin요청 여부를 명확히 확인하려면
해당 Pod를 describe해서 Events를 보면 된다.Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal FileSystemResizeSuccessful 13m kubelet MountVolume.NodeExpandVolume succeeded for volume "pvc-98d52b3c-ce38-49ee-baa4-a36bf4f60b72" i-0f2a5c9c120e30cbcFileSystemResizing이 성공했음을 알 수 있다. 또 그 주체는 From 부분의 Kubelet임을 확인했다.
MountVolume.NodeExpandVolume succeeded라는 메시지를 보니, NodeExpandVolume을 요청 했음도 알 수 있다.
마지막으로 Pod의 Volume Mount정보를 명확하게 확인해보자.
kubectl exec -it <your-pod-name> -- df -h
이 pod의 pv 마운트 위치는 /qdrant/storage이었다.
해당 Mounted의 Available 부분을 보면 40G로 잘 변경되어있다.
기존에는 해당 부분이 약 30G로 표시되어있었다.
참고자료
https://github.com/kubernetes-sigs/aws-ebs-csi-driver
https://kubernetes.io/docs/concepts/storage/persistent-volumes/
https://kubernetes.io/blog/2018/07/12/resizing-persistent-volumes-using-kubernetes/
https://kubernetes-csi.github.io/docs/volume-expansion.htmlk8s csi-resizer(external-resizer)
https://github.com/kubernetes-csi/external-resizer/blob/master/cmd/csi-resizer/main.go
aws-ebs-csi-driver의 헬름 차트
https://github.com/kubernetes-sigs/aws-ebs-csi-driver/tree/master/charts/aws-ebs-csi-driver
K8s에서의 CSI Driver 배포
https://kubernetes-csi.github.io/docs/deploying.html'Kubernetes' 카테고리의 다른 글
[(Kubeadm) K8s 클러스터 구축 3/3] Kubeadm init 및 Node join (0) 2025.10.16 [(Kubeadm) K8s 클러스터 구축 2/3] Kubeadm, Kubelet, Kubectl 설치 (0) 2025.10.15 [(Kubeadm) K8s 클러스터 구축 1/3] Container Runtime 설치 (1) 2025.10.14 CKA 쿠버네티스 자격증 취득과정 기록 (2025. 02 변경 이후) (3) 2025.07.25 Dockerfile(ENTRYPOINT, CMD) => YAML Definition file(command, args) 덮어쓰기 과정 (0) 2025.06.30