3주차 1편에서는 EKS가 어떻게 AWS스토리지를 사용할 수 있으며, 사용 예제를 소개합니다.
EKS가 AWS스토리지를 사용하는 원리
쿠버네티스에서는 다양한 스토리지 연계를 위해 CSI 인터페이스를 제공합니다. CSI 인터페이스 덕분에 쿠버네티스에서 쉽게 스토리지(EBS, EFS 등)를 사용할 수 있습니다.
쿠버네티스 CSI 인터페이스에 맞춰 개발된 AWS CSI를 CSI 드라이버라고 부릅니다. EKS에서 EBS, EFS 등 AWS 스토리지를 다루려면 스토리지별로 AWS CSI 드라이버를 설치해야 합니다. AWS CSI드라이버 설치 방법은 EKS공식문서에 안내하고 있습니다.
AWS CSI 드라이버는 크게 2개 구성요소가 있습니다. AWS API를 호출하면서 AWS 스토리지를 관리하는 CSI-Controller와 kubelet과 상호작용하면서 AWS스토리지를 pod에 마운트하는 CSI-Node가 있습니다.
CSI-Conroller와 CSI-Node는 pod로 실행됩니다.
kubectl -n kube-system get po -l app.kubernetes.io/component=csi-driver
설치
사용하려는 AWS 스토리지마다 CSI 드라이버를 설치해야 합니다. 예를 들어 AWS EBS를 사용하고 싶으면 EBS CSI 드라이버를 설치해야 합니다. 이 예제에서는 EBS를 사용하므로 EBS CSI드라이버를 설치하는 과정을 다룹니다.
ODIC proivder 설치
EBS CSI드라이버가 AWS API를 사용해야 하므로 CSI-controller pod에 IAM policy가 필요합니다. 이 예제에서는 IRSA를 사용합니다. 그러므로 EKS OIDC provider를 설치해야 합니다.
CLUSTER_NAME="baisc-cluster"
eksctl utils associate-iam-oidc-provider --cluster ${CLUSTER_NAME} --approve
IRSA 설치
공식문서를 참고하여 eksctl명령어로 IRSA를 생성했습니다. IAM policy는 AWS관리형 policy "AmazonEBSCSIDriverPolicy"를 사용했습니다.
CLUSTER_NAME="baisc-cluster"
eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster ${CLUSTER_NAME} \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EBS_CSI_DriverRole
eksctl명령어가 성공적으로 실행되면 쿠버네티스 serviceaccount와 IAM role이 생성됩니다. serviceaccount는 annotation으로 IAM role이 매핑되어 있습니다. IAM role은 EBS를 제어할 수 있는IAM policy가 설정되어 있습니다.
EBS CSI 드라이버 설치
EBS CSI 드라이버는 eksctl 또는 helm으로 설치할 수 있습니다. 이 예제에서는 eksctl로 설치합니다. eksctl로 설치 할 때 addon명령어를 사용합니다.
ROLE_ARN="arn:aws:iam::${your_org_id}:role/AmazonEKS_EBS_CSI_DriverRole"
CLUSTER_NAME="baisc-cluster"
eksctl create addon --name aws-ebs-csi-driver \
--cluster ${CLUSTER_NAME} \
--service-account-role-arn ${ROLE_ARN} --force
EBS CSI드라이버가 설치되면 CSI-Controller와 CSI-Node pod가 생성됩니다.
kubectl -n kube-system get po -l app.kubernetes.io/component=csi-driver
EBS 사용시 주의사항
AccessMode설정 주의
persistentvolume, persistentvolumeclaim의 accessModes는 ReadWriteOnce로 설정해야 합니다. EBS스토리지 기본 설정이 동일 AZ에 있는 EC2 인스턴스만 연결 할 수 있기 때문입니다.
사용 예제1 - 정적 프로비저닝
정적 프로비저닝은 미리 AWS스토리지를 만든 후, 쿠버네티스 리소스를 배포하는 방식입니다. storageclass와 persistentvolume csi필드에 AWS 스토리지 정보를 설정합니다. 아래 예제는 gp2 storageclasss를 지정했으므로 gp2타입 EBS스토리지를 생성했습니다.
persistentvolumeclaim은 persistentvolume에 정의한 storageclass를 설정해야 합니다.
전체 yaml파일은 아래와 같습니다. yaml설정에서 EBS스토리지 ID가 필요합니다. EBS스토리지 ID는 persistentvolume에 설정합니다. p2 storageclass는 EKS설치 시 기본으로 생성되어 있어 생략했습니다.
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-pv
spec:
storageClassName: "gp2"
accessModes:
- ReadWriteOnce
capacity:
storage: 1Gi
csi:
driver: ebs.csi.aws.com
fsType: ext4
# EBS스토리지를 먼저 생성하고, EBS ID를 설정하세요
volumeHandle: vol-089eb3486b57f95f0
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: topology.ebs.csi.aws.com/zone
operator: In
values:
- ap-northeast-2a
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-claim
spec:
storageClassName: "gp2" # Empty string must be explicitly set otherwise default StorageClass will be set
volumeName: test-pv
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.ebs.csi.aws.com/zone
operator: In
values:
- ap-northeast-2a
containers:
- name: app
image: centos
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: ebs-claim
kubectl apply명령어로 배포하면 pv, pvc가 Bound상태로 되어 있습니다. 그리고 pod가 Running상태입니다.
kubectl apply -f example.yaml
kubectl get po,pv,pvc
AWS console에서 EBS상태를 확인하면 In-use상태로 변경됩니다.
삭제 방법은 쿠버네티스 리소스를 삭제 한 후, AWS console에서 EBS 스토리지를 삭제합니다.
kubectl delete -f example.yaml
사용 예제2 - 동적 프로비저닝
동적 프로비저닝은 AWS 스토리지를 생성하지 않고 쿠버네티스 리소스를 배포합니다. persistentvolumeclaim이 생성되면 AWS CSI 드라이버가 persistentvolume과 AWS 스토리지를 동적으로 생성합니다. 그래서 이름이 동적 프로비저닝입니다.
그래서, 아래 yaml처럼 persistentvolume이 없습니다.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: ebs-sc
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: centos
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: ebs-claim
kubectl apply로 배포하면, persistentvolume이 생성되고 bound상태로 되어 있습니다.
kubectl apply -f example.yaml
kubectl get po,pv,pvc
그리고 EBS스토리지가 생성되어 In-use상태로 되어 있습니다.
삭제하는 방법은 쿠버네티스 리소스만 삭제하면 됩니다. persistentvolume RECLAIM Policy가 Delete이므로 persistentvolume, persistentvolumeclaim이 삭제되면 EBS스토리지도 자동으로 삭제됩니다.
kubectl delete -f example.yaml
참고자료
- 책: https://www.oreilly.com/library/view/production-kubernetes/9781492092292/ch04.html
- invoex 기술 블로그: https://www.inovex.de/de/blog/kubernetes-storage-volume-cloning-ephemeral-inline-volumes-snapshots/
- 일본 ppt: https://speakerdeck.com/bells17/introduction-to-csi?slide=36
이하공백
'연재 시리즈' 카테고리의 다른 글
EKS 스터디 - 4주차 1편 - 컨트롤 플레인 로깅 (0) | 2023.05.07 |
---|---|
EKS 스터디 - 3주차 2편 - EKS Fargate와 원리 (0) | 2023.04.30 |
EKS 스터디 - 2주차 3편 - ALB Controller (2) | 2023.04.23 |
EKS 스터디 - 2주차 2편 - EKS POD IP는 무한대로 할당할 수 있을까? (0) | 2023.04.19 |
EKS 스터디 - 2주차 1편 - EKS는 어떤 CNI를 사용할까? (2) | 2023.04.18 |