다음은 Amazon EBS 볼륨 유형 gp2와 gp3의 비교 지표이다.
2020년 12월에 출시된 gp3를 사용하면 스토리지 크기를 느리지 않고도 IOPS와 처리량을 독립적으로 프로비저닝할 수 있어 GB당 최대 20% 비용을 절감할 수 있다고 한다. 즉 저렴한 비용으로 고성능을 유지하면서 더 적은 볼륨을 프로비저닝 할 수 있다. gp3의 최고 성능은 gp2의 볼륨의 최대 처리량보다 4배 빠르며 gp2 볼륨이 적용될만한 모든 케이스에서 gp3 볼륨을 사용할 수 있다고 하니 gp3를 사용하지 않을 이유가 없는 거 같다고 생각한다.
gp3로 마이그레이션할 때 IOPS와 처리량에 대해서는 위 포스팅을 참고하도록 하자.
Amazon EBS 볼륨을 gp2에서 gp3으로 마이그레이션하고 최대 20% 비용 절감하기 | Amazon Web Services
업데이트 (4/27/2022): EBS gp2-gp3 마이그레이션 비용 절감 계산기를 다운로드하면 EBS gp2 볼륨을 gp3로 마이그레이션할 때 비용을 얼마나 절감할 수 있는지 알 수 있습니다. 범용 SSD (gp2) Amazon EBS 볼륨
aws.amazon.com
AWS 관리 콘솔에서도 변경 가능하며 AWS CLI로도 애플리케이션 중단없이 변경이 가능하다.
aws ec2 modify-volume --volume-type gp3 --iops 4000 --throughput 250 --volume-id vol-11111111111111111
하지만 그렇게 변경하게 되면 EKS 클러스터에서는 PV 사용 시 여전히 gp2로 보이게 될 것이다. PersistentVolume(PV)의 스토리지 클래스 정보가 그대로 gp2로 남아 있기 때문이다. Kubernetes에서 PV 생성 시 스토리지 클래스와 볼륨 타입이 결정되기에 새 PV/PVC를 생성하거나 Helm 차트 등의 배포 과정에서 storageClassName을 gp3로 지정해 재프로비저닝하는 절차가 필요하다.
EKS의 Default StorageClass가 gp2로 프로비저닝 하기에 default 스토리지 클래스를 gp3로 변경하는게 좋지만 기존에 프로비저닝 된 볼륨의 유형을 바꾸는 과정을 기록해보려고 한다. 옳은 방법, 더 쉬운 방법은 있을 것 같고 계속 고민해 볼 필요는 있을 것 같다.
eks csi-driver 설치 참조
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/ebs-csi.html#managing-ebs-csi
본격적인 마이그레이션 전에 VolumeSnapshot 관련 CRD 및 Controller 등을 설치 해야한다.
CRD 설치
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f snapshot.storage.k8s.io_volumesnapshots.yaml,snapshot.storage.k8s.io_volumesnapshotclasses.yaml,snapshot.storage.k8s.io_volumesnapshotcontents.yaml
Snapshot Controller 설치
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
kubectl apply -f rbac-snapshot-controller.yaml,setup-snapshot-controller.yaml
kubectl get deploy -n kube-system snapshot-controller
kubectl get pod -n kube-system -l app=snapshot-controller
마지막으로 VolumSnapshotClass를 설치하자. 스토리지 제공자별로 스냅샷 생성 방식을 정의하며, 어느 드라이버를 사용할지, 스냅샷 생성 시 어떤 옵션을 적용할지를 지정한다.
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: ebs-csi-aws
driver: ebs.csi.aws.com
deletionPolicy: Delete
kubectl apply -f volumesnapshot.yaml
마이그레이션 시나리오를 간략히 설명하자면 다음과 같다.
현재 gp3로 마이그레이션 하고자 하는 PV가 속해있는 EBS 볼륨 ID를 조회하여 스냅샷을 생성한다. 이 스냅샷을 기반으로 gp3로 프로비저닝 할 수 있다. (사실 이 부분에서 스냅샷 한 시점부터 동기화되지 않기 때문에 찝찝한 마음이 들긴 하다.)
스냅샷이 생성되면 이를 기반으로 VolumeSnapshotContent 오브젝트를 만든다. 이 오브젝트는 생성된 스냅샷의 정보를 담고 있고 실제 스냅샷과의 바인딩 역할을 한다고 볼 수 있다.
그 다음 VolumeSnapshot 오브젝트를 생성한다. 사용자가 스냅샷 생성을 요하는 오브젝트라고 생각하면 될 것 같다. 이 오브젝트를 생성하면 Kubernetes 컨트롤러가 VolumeSnapshotClass에 정의된 정책을 참고하여 실제 스냅샷(VolumeSnapshotContent)를 생성하고, 둘을 연결(binding)한다.
결과적으로 사용자는 VolumeSnapshot을 통해 생성된 스냅샷을 참조하고 활용할 수 있게 된다. 이 때 VolumeSnapshot과 VolumeSnapshotContent는 이상하게 보일 수 있지만 양방향 매핑이 필요하다.
This seems odd but is necessary for the bidirectional binding of VolumeSnapshotContent and VolumeSnapshot for preexisting snapshots!
VolumeSnapshotContent 생성
$ cat vsc-csi.yaml
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
name: imported-aws-snapshot-content
spec:
volumeSnapshotRef:
kind: VolumeSnapshot
name: imported-aws-snapshot
namespace: default
source:
snapshotHandle: snap-06fb1faafc1409cc5 # <-- snapshot to import
driver: ebs.csi.aws.com
deletionPolicy: Delete
volumeSnapshotClassName: ebs-csi-aws
$ kubectl apply -f vsc-csi.yaml
volumesnapshotcontent.snapshot.storage.k8s.io/imported-aws-snapshot-content created
$ kubectl get volumesnapshotcontent imported-aws-snapshot-content
NAME READYTOUSE RESTORESIZE DELETIONPOLICY DRIVER VOLUMESNAPSHOTCLASS VOLUMESNAPSHOT VOLUMESNAPSHOTNAMESPACE AGE
imported-aws-snapshot-content true 1073741824 Delete ebs.csi.aws.com ebs-csi-aws imported-aws-snapshot default 12s
VolumeSnapshot 생성
$ cat vs-csi.yaml
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: imported-aws-snapshot
namespace: default
spec:
volumeSnapshotClassName: ebs-csi-aws
source:
volumeSnapshotContentName: imported-aws-snapshot-content
$ kubectl apply -f vs-csi.yaml
volumesnapshot.snapshot.storage.k8s.io/imported-aws-snapshot created
$ kubectl get volumesnapshot imported-aws-snapshot
NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE
imported-aws-snapshot true imported-aws-snapshot-content 1Gi ebs-csi-aws imported-aws-snapshot-content 33m 60s
이렇게 VolumSnapshot을 만들면 이를 기반으로 PVC(PersistenVolumeClaim)을 만들 수 있다.
$ cat pvc-vs-csi.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: imported-aws-snapshot-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp3
resources:
requests:
storage: 1Gi
dataSource:
name: imported-aws-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
이를 기반으로 pod에서 PVC claimName을 변경해주어 적용할 수 있다.
$ cat test-pod-snap.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-imported-snapshot-csi
spec:
containers:
- name: app
image: centos
args:
- sleep
- "10000"
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: imported-aws-snapshot-pvc
실제로 pod가 사용하는 PVC를 변경하는 건 다음과 같은 방향으로 가능하지만 helm chart 등으로 주어진 환경마다 다를 수 있다. 해당 글에서는 helm chart로 구성된 grafana의 볼륨을 교체하는 과정에서 기존 PVC를 삭제하고 동일한 이름의 PVC를 VolumeSnapshot으로 부터 생성하였다고 한다. 필자의 경우는 다음과 같이 VolumeClaimTemplate의 Datasource를 추가하여 마이그레이션 하기도 했다.
이 또한 절대 좋은 방법이 아님을 느낀 것은 1. 재배포가 필요하였고 2. 스냅샷을 만든 시점부터는 데이터 동기화가 안되기에 실시간으로 데이터가 유지되어야한다면 다른 방법을 고민해 볼 필요가 있을 것이다.
참고
'IT' 카테고리의 다른 글
쿠버네티스 파드 네트워킹 (0) | 2025.02.26 |
---|---|
쿠버네티스[EKS] Cluster, Node, Add ons Upgrade (1) | 2025.02.21 |
쿠버네티스[EKS] SecurityGroupPolicy (0) | 2025.02.20 |
쿠버네티스[EKS] IRSA(IAM for ServiceAccount) (0) | 2025.02.20 |
스프링부트 Virtual Thread, Spring Data Redis(Lettuce) 도입기 (0) | 2025.01.09 |