[AWS] EKS에서 Amazon EFS 사용하기

2024. 11. 20. 23:54AWS/EKS

안녕하세요!
Onezero 입니다 :)

EKS에서 여러 pods가 하나의 Storage를 사용하게 할 수 있습니다.
EBS의 경우, 단일 AZ로만 사용가능하여 다른 AZ에서는 접근이 불가능하다는 단점이 있습니다.
이 부분을 해결하기 위해 다른 AZ에서도 사용 가능한 EFS를 사용합니다.


Step1. IAM 정책 및 역할 생성

 

Github에서 IAM 정책 문서 "iam-policy-example.json" 를 다운로드합니다.

curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/docs/iam-policy-example.json

 

"AmazonEKS_EFS_CSI_Driver_Policy" 정책을 생성합니다.

aws iam create-policy \
--policy-name AmazonEKS_EFS_CSI_Driver_Policy \
--policy-document file://iam-policy-example.json

 

IAM 역할을 생성하여 여기에 IAM 정책을 연결합니다.

eksctl create iamserviceaccount \
--cluster [Cluster_Name] \
--namespace kube-system \
--name efs-csi-controller-sa \
--attach-policy-arn arn:aws:iam::[Account_ID]:policy/AmazonEKS_EFS_CSI_Driver_Policy \
--approve \
--override-existing-serviceaccounts \
--region ap-northeast-2

 

완료 후 IAM 콘솔 > Policy > AmazonEKS_EFS_CSI_Driver_Policy 를 보면 아래와 같이 연결된 엔터티를 확인할 수 있습니다.


Step2. EFS Driver 설치 (Helm 이용)

 

아래 명령어를 통해 Helm repo에 추가합니다.

helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/

 

Helm repo를 업데이트합니다.

helm repo update

 

Helm 차트를 사용하여 Driver Release를 설치합니다.

helm upgrade -i aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver \
--namespace kube-system \
--set image.repository=602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/aws-efs-csi-driver \
--set controller.serviceAccount.create=false \
--set controller.serviceAccount.name=efs-csi-controller-sa

Step3. Amazon EFS 파일 시스템 생성

 

(1) EKS Cluster에 대한 Amazon EFS 파일 시스템 생성

# VPC ID를 검색하여 변수에 저장합니다.
vpc_id=$(aws eks describe-cluster \
--name zero-cluster \
--query "cluster.resourcesVpcConfig.vpcId" \
--output text)

# Cluster의 VPC에 대한 CIDR 범위를 변수에 저장합니다.
cidr_range=$(aws ec2 describe-vpcs \
--vpc-ids $vpc_id \
--query "Vpcs[].CidrBlock" \
--output text \
--region ap-northeast-2)

 

(2) EFS mount points 에 대한 인바운드 보안 그룹 생성

# 보안그룹을 생성합니다.
security_group_id=$(aws ec2 create-security-group \
--group-name MyEfsSecurityGroup \
--description "My EFS security group" \
--vpc-id $vpc_id \
--output text)

# Cluster 의 VPC에 대한 CIDR에서 인바운드 NFS 트래픽을 허용하는 인바운드 규칙을 생성합니다.
aws ec2 authorize-security-group-ingress \
--group-id $security_group_id \
--protocol tcp \
--port 2049 \
--cidr $cidr_range

 

콘솔에 접속하여 보안그룹을 보면 확인이 가능합니다.

 

(3) EKS Cluster에 대한 EFS 파일 시스템 생성

# 파일시스템을 생성합니다.
file_system_id=$(aws efs create-file-system \
--region ap-northeast-2 \
--performance-mode generalPurpose \
--query 'FileSystemId' \
--output text)

# Node가 있는 서브넷에 대한 mount targets을 추가합니다.
aws efs create-mount-target \
--file-system-id [File System ID] \
--subnet-id [Subnet ID] \
--security-groups [Security Group ID]

 

EFS 생성된 콘솔 화면 결과 입니다.


Step4. Sample Application 배포

 

EFS에 대한 StorageClass 매니페스트를 다운로드 후 생성한 파일시스템 ID값을 fileSystemID에 넣어줍니다.

curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml

 

# Storageclass.yaml (File System ID값을 넣어줍니다.)

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: [File System ID]
  directoryPerms: "700"
  gidRangeStart: "1000" # optional
  gidRangeEnd: "2000" # optional
  basePath: "/dynamic_provisioning" # optional
  subPathPattern: "${.PVC.namespace}/${.PVC.name}" # optional
  ensureUniqueDirectory: "true" # optional
  reuseAccessPoint: "false" # optional

 

아래 명령어를 통해 StorageClass를 배포합니다.

kubectl apply -f storageclass.yaml

 

StorageClass 배포가 완료되면, pod와 PersistentVolumeClaim을 배포하는 매니페스트를 다운로드하고 배포합니다.

curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml

 

# pod.yaml 내용입니다.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: efs-app
spec:
  containers:
    - name: app
      image: centos
      command: ["/bin/sh"]
      args: ["-c", "while true; do echo $(date -u) >> /data/out; sleep 5; done"]
      volumeMounts:
        - name: persistent-storage
          mountPath: /data
  volumes:
    - name: persistent-storage
      persistentVolumeClaim:
        claimName: efs-claim

 

아래 명령어를 통해 배포합니다.

kubectl apply -f pod.yaml

 

Controller가 변경 사항을 수집하는지 확인합니다.

kubectl logs efs-csi-controller-6b7f7dc47-fq95x \
-n kube-system \
-c csi-provisioner \
--tail 10

 

PersistentVolume 이 Bound 상태가 PersistentVolumeClaim으로 설정되어 생성되었는지 확인합니다.

 

데이터가 볼륨에 기록이 되었는지 아래 명령어를 통해 확인합니다.

kubectl exec efs-app -- bash -c "cat data/out"

 

 

감사합니다!