Ssoon

[3주차] EKS 스토리지 - EFS CSI driver 본문

AWS EKS Workshop Study

[3주차] EKS 스토리지 - EFS CSI driver

구구달스 2023. 5. 12. 00:26
CloudNet@ 팀의 AWS EKS Workshop Study 3주차 정리입니다.
# Amazon EKS User Guide 참고

 

  • Kubernetes 클러스터 내에서 EFS (Elastic File System)를 사용하기 위한 드라이버입니다. 
  • 이 드라이버는 EFS 파일 시스템을 마운트하여 컨테이너에 공유 스토리지를 제공하고 관리합니다.

출처 : https://www.opcito.com/blogs/deployment-automation-of-shared-storage-pvs-on-eks-using-aws-efs-and-csi-driver
출처 : https://dev.to/awscommunity-asean/aws-eks-with-efs-csi-driver-and-irsa-using-cdk-dgc

🔹 유연한 스토리지 공유: EFS CSI 드라이버는 Amazon EFS 파일 시스템을 Kubernetes 클러스터 내의 여러 컨테이너 간에 쉽게 공유할 수 있도록 합니다. 이를 통해 여러 컨테이너가 동일한 파일 시스템에 액세스하여 데이터를 공유하고 동기화할 수 있습니다.

🔹 동적 프로비저닝: EFS CSI 드라이버는 필요한 경우에 동적으로 EFS 파일 시스템을 프로비저닝합니다. 이는 클러스터 내에서 새로운 PVC (Persistent Volume Claim)를 생성할 때 필요한 파일 시스템을 자동으로 생성하고 마운트합니다.

🔹 쉬운 설정 및 관리: EFS CSI 드라이버는 Kubernetes의 CSI (Container Storage Interface) 표준을 따르므로, 설정 및 관리가 용이합니다. Kubernetes의 Persistent Volume 및 Persistent Volume Claim 개념과 함께 사용되며, 기존의 PVC 관리 방식과 일관된 방식으로 EFS를 사용할 수 있습니다.

🔹 스냅샷 및 복원: EFS CSI 드라이버를 사용하면 EFS 파일 시스템의 스냅샷을 생성하고 복원할 수 있습니다. 이는 파일 시스템의 상태를 특정 시점으로 저장하거나 이전 상태로 복원하는 데 유용합니다.

🔹 데이터 지속성 및 확장성: EFS는 데이터의 지속성과 확장성을 제공하는 관리형 파일 스토리지 서비스입니다. EFS CSI 드라이버를 통해 EFS를 사용하면 애플리케이션의 데이터를 신뢰성 있게 보호하고 필요한 경우 확장할 수 있습니다.

 

[ IAM 정책 및 역할 생성 ]

사용자를 대신하여 CSI 드라이버 서비스 계정에서 AWS API를 호출할 수 있도록 하는 IAM 정책을 만듭니다.

 

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

  • 정책을 생성합니다.
aws iam create-policy \
--policy-name AmazonEKS_EFS_CSI_Driver_Policy \
--policy-document file://iam-policy-example.json

  • IAM 역할을 생성하여 여기에 IAM 정책을 연결합니다.
eksctl create iamserviceaccount \
    --cluster myeks \
    --namespace kube-system \
    --name efs-csi-controller-sa \
    --attach-policy-arn arn:aws:iam::계정ID:policy/AmazonEKS_EFS_CSI_Driver_Policy \
    --approve \
    --region ap-northeast-2

 

[ EFS 드라이버 설치 ]

Helm을 이용해 드라이버를 설치합니다.

Helm 리포지토리를 추가합니다.

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

리포지토리를 업데이트합니다.

Helm 차트를 사용하여 드라이버 릴리스를 설치합니다.

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

--set image.repository= Amazon 컨테이너 이미지 레지스트리

 

 

[Amazon EFS 파일 시스템 생성 ]

EKS 클러스터에 대한 Amazon EFS 파일 시스템 생성

  • VPC ID를 검색하여 변수에 저장합니다.
vpc_id=$(aws eks describe-cluster \
    --name myeks \
    --query "cluster.resourcesVpcConfig.vpcId" \
    --output text)
  • 클러스터의 VPC에 대한 CIDR 범위 변수에 저장합니다.
cidr_range=$(aws ec2 describe-vpcs \
    --vpc-ids $vpc_id \
    --query "Vpcs[].CidrBlock" \
    --output text \
    --region ap-northeast-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

 

EKS 클러스터에 대한 Amazon EFS 파일 시스템 생성 

  • 파일 시스템을 만듭니다.
file_system_id=$(aws efs create-file-system \
    --region ap-northeast-2 \
    --performance-mode generalPurpose \
    --query 'FileSystemId' \
    --output text)
  • 클러스터 노드의 IP 주소를 확인합니다.
  • VPC에 있는 서브넷의 ID와 서브넷이 속한 가용 영역을 확인합니다.
aws ec2 describe-subnets \
    --filters "Name=vpc-id,Values=$vpc_id" \
    --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \
    --output table

  • Node 가 있는 서브넷에 대한 mount targets 을 추가합니다.
aws efs create-mount-target \
    --file-system-id $file_system_id \
    --subnet-id subnet-0d8be3835fe60e983 \
    --security-groups $security_group_id

 

[ 샘플 애플리케이션 배포 ]

PersistentVolume Dynamic Provisioning

  • EFS에 대한 스토리지 클래스를 만듭니다.
  • Amazon EFS 파일 시스템 ID를 검색합니다.
aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text

  • EFS의 StorageClass 매니페스트를 다운로드하고 fileSystemId 값을 파일 시스템 ID로 바꿉니다.
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml

 

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: fs-0bc323723990451e0
  directoryPerms: "700"
  gidRangeStart: "1000" # optional
  gidRangeEnd: "2000" # optional
  basePath: "/dynamic_provisioning"
  • 스토리지 클래스를 배포합니다.

  • PersistentVolumeClaim을 사용하는 포드를 배포하여 자동 프로비저닝을 테스트합니다.
  • pod와 PersistentVolumeClaim을 배포하는 매니페스트를 다운로드하고 배포합니다.
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/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 logs efs-csi-controller-6f64dcc5dc-hrtmz \
    -n kube-system \
    -c csi-provisioner \
    --tail 10

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

  • STATUS가 Running이 될 때까지, 샘플 앱 pod의 상태를 봅니다.

  • 하지만 계속 ContainerCreating 상태에서 변경되지 않습니다.
  • 노드가 있는 서브넷에 대한 마운트 타겟을 추가됬는지 확인결과 마운트 타겟은 node1로 pod는 node3에 생성이 되어 pod.yaml를 삭제 후 생성되는 pod의 node를 nodeSelector로 지정한 후 다시 배포하였습니다.
  nodeSelector:
    kubernetes.io/hostname: ip-192-168-1-231.ap-northeast-2.compute.internal

  • 데이터가 볼륨에 기록되었는지 확인합니다

Comments