본문 바로가기
Cloud Computing & MSA

쿠버네티스 PVC를 파드 중단 없이 온라인으로 확장하기 (EBS CSI, allowVolumeExpansion)

냉장고를사다줘·2026년 8월 28일·조회 1

운영하다 보면 스테이트풀셋의 PVC가 어느 날 갑자기 꽉 차 있다. PostgreSQL 데이터 디렉터리든 Prometheus TSDB든, 예전 같으면 새 볼륨 붙이고 데이터 옮기고 파드 재배포하는 순서를 밟았다. 지금은 그럴 필요가 거의 없다. EBS는 Elastic Volumes로 붙어 있는 상태 그대로 커지고, 쿠버네티스가 파일시스템까지 자동으로 늘려준다. 이 글에서는 그 과정을 명령어 중심으로 짚는다.

결론부터 말하자면, StorageClass에 allowVolumeExpansion: true만 켜져 있으면 PVC의 spec.resources.requests.storage 값을 키우는 것으로 끝난다. EBS CSI 드라이버가 EC2 ModifyVolume을 호출해 디스크를 키우고, 파드가 떠 있는 노드에서 ext4/xfs 파일시스템을 자동으로 리사이즈한다. 파드 재시작은 필요 없다. 단, 용량은 늘릴 수만 있고 줄일 수 없으며, 같은 볼륨은 24시간 안에 네 번까지만 수정된다.

1. 개요 - 온라인 확장이 무엇이고 왜 2단계인가

PVC(PersistentVolumeClaim)는 파드가 요청하는 스토리지 명세다. 이 요청이 실제 EBS 볼륨(PV)에 바인딩된다. 볼륨 확장(volume expansion)은 이 PVC의 요청 용량을 키우면 아래 실물 EBS까지 따라 커지는 기능이다.

여기서 알아둘 점은 확장이 두 단계로 나뉜다는 것이다.

  • 컨트롤러 확장: external-resizer 사이드카가 PVC 변경을 감지하고 AWS ModifyVolume API를 호출한다. 블록 디바이스 자체가 커지는 단계다.
  • 노드 확장: 커진 블록 디바이스 위의 파일시스템을 실제로 넓히는 단계다. 파드가 떠 있는 노드에서 resize2fs(ext4)나 xfs_growfs(xfs)에 해당하는 작업을 CSI 드라이버가 대신 수행한다.

이 2단계 구조 때문에 확인 시점에 따라 PVC가 잠깐 FileSystemResizePending 상태로 보일 수 있다. 이건 에러가 아니라 "디스크는 커졌고 파일시스템 리사이즈를 기다리는 중"이라는 뜻이다. 아래에서 실제 출력으로 확인한다.

2. 사전 확인 - StorageClass와 CSI 드라이버

확장이 되려면 두 가지가 전제된다. StorageClass의 allowVolumeExpansiontrue여야 하고, EBS CSI 드라이버가 리사이즈를 지원하는 버전이어야 한다.

먼저 StorageClass를 본다.

$ kubectl get sc
NAME            PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp3 (default)   ebs.csi.aws.com   Delete          WaitForFirstConsumer   true                   30d

ALLOWVOLUMEEXPANSION 열이 true면 통과다. 만약 여기가 false이거나 비어 있으면 PVC를 키워도 API 서버가 요청을 거절한다. 기존 StorageClass는 이 필드를 나중에 켤 수 있다.

$ kubectl patch sc gp3 -p '{"allowVolumeExpansion": true}'
storageclass.storage.k8s.io/gp3 patched

드라이버 파드도 떠 있는지 본다. 확장 기능은 컨트롤러의 external-resizer 사이드카가 담당한다.

$ kubectl get pods -n kube-system -l app=ebs-csi-controller
NAME                                  READY   STATUS    RESTARTS   AGE
ebs-csi-controller-7d9c8b5f4c-abcde   6/6     Running   0          12d
ebs-csi-controller-7d9c8b5f4c-fghij   6/6     Running   0          12d

$ kubectl -n kube-system get deploy ebs-csi-controller -o jsonpath='{.spec.template.spec.containers[*].name}'
ebs-plugin csi-provisioner csi-attacher csi-snapshotter csi-resizer liveness-probe

컨테이너 목록에 csi-resizer가 보이면 확장 준비가 된 것이다. EBS CSI 드라이버는 v1.19.0 이상이면 최신 리사이즈 기능을 무리 없이 쓴다.

3. 확장 실행 - PVC 요청 용량 키우기

대상 PVC의 현재 용량을 확인한다. 여기서는 data-pvc가 10Gi라고 하자.

$ kubectl get pvc data-pvc
NAME       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-pvc   Bound    pvc-3f2a1c9e-7b44-4c0a-9a1e-2b6d1f0e8c7a   10Gi       RWO            gp3            18d

파드가 이 PVC를 마운트해서 쓰고 있는 상태 그대로 요청 용량만 20Gi로 올린다. 파드를 내릴 필요 없다.

$ kubectl patch pvc data-pvc \
    -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
persistentvolumeclaim/data-pvc patched

patch가 먹히면 external-resizer가 바로 EBS ModifyVolume을 호출한다. EBS 쪽에서는 크기 증가가 optimizing 상태에 도달하면 곧 반영되고, 이 전환 자체는 대개 몇 초 안에 일어난다. 다만 볼륨이 완전히 최적화되기까지 백그라운드 작업은 볼륨 크기에 따라 몇 분에서 몇 시간까지 걸릴 수 있다. 파드 입장에서 쓸 수 있는 용량이 늘어나는 시점은 파일시스템 리사이즈가 끝난 뒤다.

4. 확인 - PVC 상태와 파드 안 용량

patch 직후 describe를 보면 진행 조건이 찍힌다. 시점에 따라 Resizing 또는 FileSystemResizePending이 보인다.

$ kubectl describe pvc data-pvc
...
Conditions:
  Type                      Status   ...   Reason   Message
  ----                      ------         ------   -------
  FileSystemResizePending   True           ...      Waiting for user to (re-)start a pod to
                                                     finish file system resize of volume on node.
Events:
  Type     Reason                  Age   From                      Message
  ----     ------                  ----  ----                      -------
  Normal   Resizing                30s   external-resizer ...      External resizer is resizing volume ...
  Normal   FileSystemResizeRequired 20s  external-resizer ...      Require file system resize of volume on node
  Normal   FileSystemResizeSuccessful 5s kubelet                  MountVolume.NodeExpandVolume succeeded for volume ...

온라인 확장이 지원되는 최신 쿠버네티스에서는 마지막 FileSystemResizeSuccessful 이벤트가 파드를 재시작하지 않아도 찍힌다. 이 이벤트가 나오면 get pvc의 CAPACITY가 20Gi로 바뀐다.

$ kubectl get pvc data-pvc
NAME       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-pvc   Bound    pvc-3f2a1c9e-7b44-4c0a-9a1e-2b6d1f0e8c7a   20Gi       RWO            gp3            18d

확실히 하려면 파드 안에서 마운트 지점을 직접 본다.

$ kubectl exec -it my-pod -- df -h /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme1n1     20G  8.1G   12G  41% /data

Size가 20G로 늘고 파드는 그대로 떠 있다. 여기까지가 정상 방식이다. 처음 해보면 FileSystemResizePending이 안 사라져서 당황하는데, 대개는 노드 확장이 아직 안 끝난 것뿐이다. CSI 드라이버 노드 파드 로그(kubectl logs -n kube-system ds/ebs-csi-node -c ebs-plugin)를 보면 리사이즈 진행이 찍힌다.

5. 함정 - 축소 불가, 24시간 제한, 멈춘 확장 복구

줄일 수는 없다

EBS는 크기를 늘릴 수만 있다. PVC 요청을 현재보다 작은 값으로 patch하면 거절된다.

$ kubectl patch pvc data-pvc \
    -p '{"spec":{"resources":{"requests":{"storage":"5Gi"}}}}'
The PersistentVolumeClaim "data-pvc" is invalid: spec.resources.requests.storage:
Forbidden: field can not be less than previous value

정말 용량을 줄여야 하면 더 작은 새 볼륨을 만들고 애플리케이션 레벨 도구(rsync 등)로 데이터를 옮기는 수밖에 없다. 그러니 확장은 넉넉하되 과하지 않게, 한 번에 필요한 만큼만 올리는 편이 좋다.

24시간에 네 번, 이게 pending의 진짜 원인일 때가 있다

AWS 문서 기준으로 하나의 EBS 볼륨은 롤링 24시간 동안 최대 네 번까지 수정할 수 있다. 그리고 이전 수정이 completed 상태에 도달하기 전에는 다음 수정을 시작할 수 없다. 이 한도를 넘기면 다음 수정 가능 시각을 알려주는 에러가 난다.

테스트한다고 10Gi에서 12, 14, 16으로 찔끔찔끔 키우면 슬롯 네 개를 금방 다 쓴다. 그 뒤에 patch하면 쿠버네티스 PVC는 요청을 받아들여 Resizing으로 넘어가지만 EBS 쪽에서 진행이 안 되고 멈춰 있다. external-resizer 로그를 보면 이렇게 나온다.

$ kubectl logs -n kube-system deploy/ebs-csi-controller -c csi-resizer | tail -n 3
... Error expanding volume ... : rpc error: code = Internal desc = Could not modify volume
"vol-0abc123...": VolumeModificationRateExceeded: You've reached the maximum
modification rate per volume limit. Wait at least the required interval ...

이럴 때는 방법이 없다. 24시간 창이 지나 슬롯이 빌 때까지 기다려야 한다. 그래서 확장은 필요한 목표치로 한 번에 올리는 게 맞다. 용량과 IOPS를 같이 바꿔야 한다면 따로따로 두 번 하지 말고 한 번에 반영해 슬롯을 아끼는 게 좋다.

너무 크게 요청해서 멈췄을 때 되돌리기

실수로 500Gi 같은 값을 넣었는데 EBS 쿼터나 파일시스템 한계에 걸려 확장이 멈추는 경우가 있다. 예전에는 한 번 키운 요청을 되돌릴 수 없어 곤란했는데, RecoverVolumeExpansionFailure 기능 게이트가 켜진 클러스터라면 spec.resources.requests.storage를 실제 할당된 용량 이상, 원래 목표 미만의 값으로 다시 낮춰 멈춘 확장을 정리할 수 있다. 이 기능의 활성화 여부는 쿠버네티스 버전에 따라 다르니 클러스터 상태를 먼저 확인해야 한다. 확실한 값이 아니면 처음부터 무리한 크기를 넣지 않는 게 안전하다.

6. 마무리

정리하면 온라인 PVC 확장의 핵심은 세 가지다. StorageClass에 allowVolumeExpansion: true를 켜두고, PVC의 요청 용량만 키우면 컨트롤러 확장과 노드 파일시스템 리사이즈가 파드 중단 없이 이어진다. 대신 축소는 불가능하고, 같은 볼륨은 24시간에 네 번이라는 EBS 한도를 넘기면 확장이 멈춘 것처럼 보인다. 이 두 제약만 기억하면 급할 때 새벽에 파드 내리는 일은 피할 수 있다.

자주 묻는 질문

PVC를 확장할 때 파드를 재시작해야 하나?

온라인 확장을 지원하는 최신 쿠버네티스와 EBS CSI 드라이버 조합에서는 재시작이 필요 없다. 컨트롤러 확장으로 EBS가 커지고, 파드가 떠 있는 노드에서 파일시스템 리사이즈가 자동으로 수행된다. 다만 오래된 클러스터나 특정 파일시스템에서는 노드 확장을 끝내려고 파드 재시작이 필요할 수 있는데, 이때 describe pvc에 FileSystemResizePending 조건이 남는다.

PVC 용량을 줄일 수 있나?

줄일 수 없다. EBS는 크기 증가만 지원하고, 쿠버네티스도 spec.resources.requests.storage를 이전 값보다 작게 patch하면 거절한다. 정말 줄여야 하면 더 작은 새 볼륨을 만들고 rsync 같은 애플리케이션 레벨 도구로 데이터를 옮겨야 한다.

확장했는데 CAPACITY가 안 바뀌고 멈춰 있다. 왜인가?

두 가지를 의심한다. 첫째, 노드 파일시스템 리사이즈가 아직 안 끝났을 수 있다. describe pvc의 조건과 ebs-csi-node 로그를 확인한다. 둘째, EBS 수정 한도에 걸렸을 수 있다. 같은 볼륨은 롤링 24시간에 네 번까지만 수정되며, 초과하면 csi-resizer 로그에 VolumeModificationRateExceeded가 찍히고 창이 지날 때까지 진행되지 않는다.

StorageClass에 allowVolumeExpansion을 나중에 켤 수 있나?

가능하다. kubectl patch sc <이름> -p '{"allowVolumeExpansion": true}'로 기존 StorageClass에도 켤 수 있다. 이 필드가 false이거나 없으면 PVC 확장 요청 자체를 API 서버가 거절한다.

용량과 IOPS를 같이 늘리고 싶으면 어떻게 하나?

한 번의 수정으로 함께 반영하는 게 좋다. 볼륨당 24시간 네 번 한도를 용량 따로, IOPS 따로 나눠 쓰면 슬롯이 금방 소진된다. 크기는 PVC 요청 용량으로, 타입/IOPS/throughput은 VolumeAttributesClass(드라이버 v1.19.0+)로 조정할 수 있다.

관련 글

댓글 0

로그인 후 댓글을 남길 수 있습니다.

아직 댓글이 없습니다.