[EKS Study 3주차] EKS Storage - EFS CSI Controller
- -
CloudNet@ 팀의 가시다님께서 Leading 하시는 AEWS Study 3주차 스터디 내용 정리
이번 포스팅에서는 EKS Storage 중 EFS CSI Driver 에 대해 알아보겠습니다.
1. EFS CSI Driver Install
EFS CSI Driver 는 EBS CSI Driver 와 마찬가지로 Amazon EFS 서비스를 EKS 에서 사용할 수 있도록 해주는 CSI Driver 입니다.
Cross-AZ 기능이 지원되지 않는 EBS Storage 와는 다르게,
Cross-AZ 가 가능한 공유 스토리지이기 때문에 여러 가용영역의 Pod 가 동일한 데이터를 사용해야 한다면 고려할 수 있는 서비스입니다.

1.1. IRSA 를 위한 IAM Policy 생성
AWS 관리형 정책을 사용하는 EBS CSI Controller 와는 다르게,
EFS CSI Controller 는 고객 관리형 정책을 사용합니다.
그렇기 때문에, EFS 권한을 가진 정책을 생성해줍니다.
AWS 콘솔에서 직접 만들어도 되지만 aws cli 를 통해 쉽게 만들 수 있습니다.
Policy JSON 파일 생성
cat << EOT > efs-csi-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "elasticfilesystem:DescribeAccessPoints", "elasticfilesystem:DescribeFileSystems", "elasticfilesystem:DescribeMountTargets", "ec2:DescribeAvailabilityZones" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "elasticfilesystem:CreateAccessPoint" ], "Resource": "*", "Condition": { "StringLike": { "aws:RequestTag/efs.csi.aws.com/cluster": "true" } } }, { "Effect": "Allow", "Action": [ "elasticfilesystem:TagResource" ], "Resource": "*", "Condition": { "StringLike": { "aws:ResourceTag/efs.csi.aws.com/cluster": "true" } } }, { "Effect": "Allow", "Action": "elasticfilesystem:DeleteAccessPoint", "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/efs.csi.aws.com/cluster": "true" } } } ] } EOT
IAM Role 생성
- 방금 생성한 JSON 정책을 사용하여 AmazonEKS_EFS_CSI_Driver_Policy 라는 이름의 역할을 생성합니다.
aws iam create-policy \ --policy-name AmazonEKS_EFS_CSI_Driver_Policy \ --policy-document file://efs-csi-policy.json
1.2. EFS CSI Driver 설치를 위한 IRSA 설정
- 다음 eksctl 명령어로 IRSA 를 생성합니다.
eksctl create iamserviceaccount \ --name efs-csi-controller-sa \ --namespace kube-system \ --cluster ${CLUSTER_NAME} \ --attach-policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AmazonEKS_EFS_CSI_Driver_Policy \ --approve
터미널 생성 화면

AWS CloudFormation Stack 화면

생성된 IRSA 는 다음 명령어로 확인할 수 있습니다.
- kubectl
kubectl get sa -n kube-system efs-csi-controller-sa -o yaml | head -5

- eksctl
eksctl get iamserviceaccount --cluster myeks

1.3. EFS CSI Driver 설치 - helm
IRSA 설정이 완료되었다면, EFS Controller 를 설치합니다.
# EFS CSI Driver Helm Repo 추가 helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/ # Helm 업데이트 helm repo update # Helm Set 옵션으로 원하는 값만 변경 후, Helm 배포 helm upgrade -i aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver \ --namespace kube-system \helm upgrade -i aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver \ --namespace kube-system \ --set image.repository=602401143452.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/eks/aws-efs-csi-driver \ --set controller.serviceAccount.create=false \ --set controller.serviceAccount.name=efs-csi-controller-sa --set image.repository=602401143452.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/eks/aws-efs-csi-driver \ --set controller.serviceAccount.create=false \ --set controller.serviceAccount.name=efs-csi-controller-sa

다음 명령어로 EFS CSI Driver 설치를 확인할 수 있습니다.
# 배포된 Helm Repo 확인 helm list -n kube-system # kube-system 에 배포된 EFS CSI Driver 관련 Pod 확인 kubectl get pod \ -n kube-system \ -l "app.kubernetes.io/name=aws-efs-csi-driver,app.kubernetes.io/instance=aws-efs-csi-driver"

2. EFS CSI Driver 사용
2.1. EFS Test Code 다운로드
git clone https://github.com/kubernetes-sigs/aws-efs-csi-driver.git /root/efs-csi cd /root/efs-csi/examples/kubernetes/multiple_pods/specs
2.2. EFS Storage Class 생성
EFS Storage 를 사용하기 위해 StorageClass 를 생성합니다.
cat storageclass.yaml | yh kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: efs-sc provisioner: efs.csi.aws.com
kubectl apply -f storageclass.yaml

2.3. EFS 사용을 위한 PV/PVC 생성
EFS 를 사용하기 위해서는 PV 에 EFS ID 를 넣어주어야 합니다.
다음 명령어로 PV.yaml 에 EFS ID 를 대입해줍니다.
EfsFsId=$(aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text) sed -i "s/fs-4af69aab/$EfsFsId/g" pv.yaml

kubectl apply -f pv.yaml
PVC 생성
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: efs-claim spec: accessModes: - ReadWriteMany storageClassName: efs-sc resources: requests: storage: 5Gi
kubectl apply -f claim.yaml
2.4. EFS 를 사용하는 Pod 생성
- app1 : /data/out1.txt 에 5초마다 현재 시간을 출력
- app2 : /data/out2.txt 에 5초마다 현재 시간을 출력
apiVersion: v1 kind: Pod metadata: name: app1 spec: containers: - name: app1 image: busybox command: ["/bin/sh"] args: ["-c", "while true; do echo $(date -u) >> /data/out1.txt; sleep 5; done"] volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim: claimName: efs-claim apiVersion: v1 kind: Pod metadata: name: app2 spec: containers: - name: app2 image: busybox command: ["/bin/sh"] args: ["-c", "while true; do echo $(date -u) >> /data/out2.txt; sleep 5; done"] volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim: claimName: efs-claim
kubectl apply -f pod1.yaml,pod2.yamlkubectl apply -f pod1.yaml,pod2.yaml
Pod 에서 EFS Attach 확인
kubectl exec -ti app1 -- sh -c "df -hT -t nfs4" kubectl exec -ti app2 -- sh -c "df -hT -t nfs4"

App1 에서 /data/out1.txt , /data/out2.txt 에 대한 내용 출력
kubectl exec -ti app1 -- tail -f /data/out1.txt kubectl exec -ti app1 -- tail -f /data/out2.txt

모두 출력이 되므로, 서로 EFS 스토리지를 통해 데이터를 공유하고 있음을 알 수 있습니다.