참조 : https://tech.gluesys.com/blog/2022/06/21/CSI.html
참조 : https://nice-engineer.tistory.com/entry/Kubernetes-EBS-for-CSI-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84-CSI%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80
- CSI는 Storage를 제어하는 Plugin, Volume Life Cycle, 컨테이너 오케스트레이션 시스템과 CSI Plugin 사이의 인터페이스를 정의한다
- Provisioner : PV 생성
- Attacher : Pod가 PVC 사용 시, PV를 Mount
- Controller : Volume 생성 및 삭제
- NodeServer : Pod가 배포될 Node에 Volume이 Mount될 수 있도록 환경 구성
- 컨트롤러 Plugin : 스토리지 중앙 관리 기능을 담당하며, 아무 노드에서 동작해도 상관 없다
- 노드 Plugin : 컨테이너가 동작하는 모든 노드에서 동작하는 Plugin으로, 각 Node를 제어한다
- CREATED -> NODE READY -> Volume Ready -> PUBLISHED -> Delete Volume
참조 : https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/csi-iam-role.html
- 이전에 생성한 OIDC 자격 공급 증명자를 선택하고, 대상을 선택하자
- 정책 추가에서 AmazonEBSCSIDriverPolicy를 선택하자
- 생성한 역할의 신뢰 관계 편집에 들어가자
aud": "sts.amazonaws.com"
# 위와 같이 써있는 곳을 찾자
sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa"
# 해당 부분을 위와 같이 바꾸자
- aud": "sts.amazonaws.com"라고 써있는 부분을 찾아서 바꾸자
- 해당 프로비저너는 Kubernetes Source Code 내부에 존재하는 AWS EBS 프로비저너로, Kubernetes Release Lifecycle을 따라서 배포된다. 따라서 프로비저너의 신규 기능을 사용하려면 Kubernetes 버전을 업그레이드 해야 한다
- 따라서 내부에 내장된 EBS 프로비저너를 사용하지 않고, EBS CSI 드라이버를 설치하여 ' EBS CSI Controller Pod ' 를 통해 볼륨 프로비저닝이 가능하도록 하겠다
- EKS 클러스터 콘솔에 들어가서 ' 추가 기능 가져오기 ' 를 누르자
- Amazon EBS CSI 드라이버를 선택하자
- 위에서 생성한 역할을 지정하자
[honguser@ip-192-168-11-50 work]$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
ebs-csi-controller-6875b778b5-24nq9 6/6 Running 0 104s
ebs-csi-controller-6875b778b5-nb2dj 6/6 Running 0 103s
ebs-csi-node-d9swx 3/3 Running 0 104s
ebs-csi-node-qtxn2 3/3 Running 0 104s
- EBS CSI 컨트롤러와 노드가 배포되었다
[honguser@ip-192-168-11-50 work]$ kubectl get sa -n kube-system
NAME SECRETS AGE
ebs-csi-controller-sa 0 3m
ebs-csi-node-sa 0 2m59s
- EBS CSI를 위한 Service Account도 배포되었다
EBS 볼륨은 Pod가 생성되는 Node와 동일한 가용 영역에 있어야 한다
EBS는 특정 가용 영역에 생성되어 단일 EC2 인스턴스에 붙는 스토리지이므로 해당 EC2 인스턴스에 배포된 Pod 끼리만 공유 가능하다. 다른 인스턴스에 배포된 Pod와 스토리지를 공유하고 싶으면, EFS를 사용해야 한다
- 따라서, PV의 accessModes가 ReadWriteOnce만 지원한다. 다른 인스턴스와 EBS 볼륨을 동시에 공유할 수 없기 때문이다
- EFS는 EBS보다 가격이 비싸고, IO가 느린 단점이 있다
참조 : https://kubernetes.io/ko/docs/concepts/storage/storage-classes/
- 즉, 동적 프로비저닝은 StorageClass와 프로비저너를 사용하여 자동으로 PV를 생성해서 PVC와 Bound 시키는 기능이다
- volumeBindingMode : PV의 바인딩과 프로비저닝 동작 설정
- ReclainPolicy : PV 재사용 시, PV 내용을 지울지 말지에 대한 설정
- 사용할 프로비저너 지정 및 생성할 볼륨 사양에 대해서도 설정할 수 있다
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: hong-ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: Immediate
reclaimPolicy: Delete
parameters:
csi.storage.k8s.io/fstype: ext4
type: gp2
allowedTopologies:
- matchLabelExpressions:
- key: topology.ebs.csi.aws.com/zone
values:
- ap-northeast-2a
- ap-northeast-2c
- provisioner : 사용할 프로비저너인 EBS CSI를 지정
- volumeBindingMode - Immediate : pvc 생성 시, 프로비저닝과 바인딩이 바로 발생하도록 설정
- WaitForFirstConsumer라면, pvc를 사용하는 Pod가 배포될 때까지 Provisioning과 Mount를 지연시킨다
- reclaimPolicy - Delete : 볼륨 사용이 끝나면, 삭제하도록 설정
- parameters : EBS 볼륨 타입과 볼륨 파일 시스템 지정
- allowedTopologies : 프로비저닝을 제한하기 위한 설정. Key와 Value를 통해 설정한다
- Key - topology.ebs.csi.aws.com/zone : EBS 볼륨이 생성되는 가용 영역을 제한하기 위해 사용
- values - 가용 영역 : EKS 클러스터 워커 노드가 위치한 가용 영역에 EBS 볼륨이 생성되게 설정
kubectl apply -f storageclass.yaml
- 배포해주자
[honguser@ip-192-168-11-50 work]$ kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 2d3h
hong-ebs-sc ebs.csi.aws.com Delete Immediate false 40m
- 배포된 StorageClass를 확인하자. 잘 배포되었다
- EKS에 기본적으로 내장된 프로비저너인 kubernetes.io/aws-ebs를 위한 StorageClass가 배포되있는 것을 확인할 수 있다
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: hongspace
name: hong-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: hong-ebs-sc
- resources : 요구하는 볼륨 사양
- storageClassName : 사용하는 StorageClass. 특정 storageClass를 가진 pv는 해당 storageClass를 사용하는 pvc에만 연결된다
- accessModes : Volume의 Read / Write 권한에 대한 옵션
- ReadWriteMany : 여러개의 노드가 Read / Write 가능
- ReadOnlyMany : 여러개의 노드가 Read 가능
- ReadWriteOnce : 하나의 노드에서만 Read / Write 가능
EBS는 accessModes에서 ReadWriteOnce만 지원한다! EBS는 단일 인스턴스에만 붙으므로, 다른 노드와 공유할 수 없기 때문이다. 다른 옵션을 사용하면 PVC 생성이 안된다
kubectl apply -f pvc.yaml
- 배포해주자
[honguser@ip-192-168-11-50 work]$ kubectl get pv,pvc -n hongspace
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-d0ef839b-f17a-410d-be9a-4ea35b1f15be 2Gi RWO Delete Bound hongspace/hong-pvc hong-ebs-sc 2s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/hong-pvc Bound pvc-d0ef839b-f17a-410d-be9a-4ea35b1f15be 2Gi RWO hong-ebs-sc 5s
- PVC가 잘 배포되었으며, StorageClass를 통해 요구 사양에 맞는 PV도 프로비저닝되어 Bound되었다
- 실제로 EBS 볼륨이 잘 생성되었다. 유형은 storageClass 에서 정의했으며, 크기는 pvc 에서 정의했다
apiVersion: apps/v1
kind: Deployment
metadata:
name: hong-deploy1
namespace: hongspace
spec:
replicas: 3
selector:
matchLabels:
app: hongdeploy1
template:
metadata:
name: replica1
labels:
app: hongdeploy1
spec:
volumes: # volume 정의
- name: hongvolume1 # volume 이름
persistentVolumeClaim: # 사용할 Volume 방식. 이번에는 pvc를 사용한다
claimName: hong-pvc # 사용할 pvc
containers:
- name: hongtainer1
image: nginx
ports:
- containerPort: 80
volumeMounts: # 컨테이너와 volume mount 정의
- name: hongvolume1 # 사용할 volume
mountPath: /hongdata # mount할 경로
---
apiVersion: v1
kind: Service
metadata:
namespace: hongspace
name: hong-svc1
spec:
ports:
- name: hong-svc-port
port: 80
targetPort: 80
selector:
app: hongdeploy1
- volumeMounts 는 컨테이너의 특정 경로와 볼륨을 Mount 시켜준다
- Pod의 spec 정의란에 Volume을 정의하자. 사용할 PVC와 Volume 이름을 정의하면 된다
- 위와 같이 NFS를 통해 Volume을 사용할 수도 있다
kubectl apply -f deploy.yaml
- 배포해주자
[ec2-user@ip-192-168-11-50 work]$ kubectl describe deploy -n hongspace hong-deploy1
.
.
.
Containers:
hongtainer1:
Image: nginx
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts:
/hongdata from hongvolume1 (rw)
Volumes:
hongvolume1:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: hong-pvc
ReadOnly: false
.
.
.
- 배포한 Deployment 상세 정보를 확인하면, Volume이 잘 Mount된 것을 확인할 수 있다
[honguser@ip-192-168-11-50 work]$ kubectl get pv,pvc -n hongspace
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-3b4d964e-bd66-406e-82bf-475f77e57ff0 2Gi RWO Delete Bound hongspace/hong-pvc3 hong-ebs-sc 7s
persistentvolume/pvc-7c25f68c-f248-411e-893c-7790f3321e72 2Gi RWO Delete Bound hongspace/hong-pvc2 hong-ebs-sc 11s
persistentvolume/pvc-d0ef839b-f17a-410d-be9a-4ea35b1f15be 2Gi RWO Delete Bound hongspace/hong-pvc hong-ebs-sc 39m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/hong-pvc Bound pvc-d0ef839b-f17a-410d-be9a-4ea35b1f15be 2Gi RWO hong-ebs-sc 39m
persistentvolumeclaim/hong-pvc2 Bound pvc-7c25f68c-f248-411e-893c-7790f3321e72 2Gi RWO hong-ebs-sc 15s
persistentvolumeclaim/hong-pvc3 Bound pvc-3b4d964e-bd66-406e-82bf-475f77e57ff0 2Gi RWO hong-ebs-sc 11s
- 각 Deployment를 위한 PV, PVC를 확인하자. 모두 잘 Bound 되었다
- 2 개의 EBS Volume이 추가적으로 생성되었다
- 2 개의 Deployment에 pvc를 이용한 Volume과 Volume Mount를 정의하고, 배포하자
- 각 Deployment 내부의 Pod에 대해 Volume이 잘 Mount 되었다
[honguser@ip-192-168-11-50 work]$ kubectl get deploy -n hongspace
NAME READY UP-TO-DATE AVAILABLE AGE
hong-deploy1 3/3 1 3 6h29m
hong-deploy2 3/3 1 3 6h25m
hong-deploy3 3/3 1 3 6h25m
- 배포한 Deployment도 잘 작동한다
- 위와 같은 구조이며, Provisiong & Mount 과정은 아래와 같다
- pvc가 배포
- 사용하는 StorageClass가 Provisioner인 AWS EBS-CSI Plugin에 요청
- 요구 사항에 맞는 EBS Volume 생성 및 PV 배포
- StorageClass Name과 요구 사양을 통해 PV와 Bound
- volumeBindingMode가 WaitForFirstConsumer라면, pvc를 사용하는 Pod가 배포될 때까지 Provisioning과 Mount를 지연시킨다
- Pod 배포 시, 사용하는 pvc를 통해 Pod와 PV가 Mount
- yaml 코드로 구조를 보면 위와 같다