3주차 - 2. AWS EBS Controller, AWS Volume SnapShots Controller, AWS EFS Controller

bocopile·2025년 2월 22일

AEWS 3기 스터디 

목록 보기
6/18

2. AWS EBS CSI Driver

정의

Pod가 EBS를 사용하려면 CSI Controller, CSI-Node가 필요하다

missing 출처 : https://malwareanalysis.tistory.com/598
  • CSI-Controller : AWS API를 호출하면서 AWS 스토리지 관리
  • CSI-Node : kubelet과 상호작용 하면서 AWS 스토리지를 pod에 마운트

[CSI-Controller]

  • 클러스터 전채에서 EBS 볼륨을 관리하는 컨트롤러
  • 구성요소
구성요소역할
External ProvisionerPVC를 기반으로 EBS 볼륨을 동적으로 생성
External AttacherKubernetes에서 ControllerPublishVolume을 호출하여 EBS 볼륨을 특정 노드에 Attach
External Resizer볼륨 크게 요청이 들어오면 ControllerExpandVolume 을 호출하여 볼륨 크기 조절
External Snapshotter볼륨의 스냅샷을 관리
Control ServiceEBS 볼륨의 생성, 삭제, Attach/Detach, 크기 조정 등의 제어 작업을 수행하는 CSI 컨트롤러 컴포넌트

[CSI-Node]

  • 클러스터의 각 워커 노드에서 실행되며, EBS 볼륨을 실제 노드의 파일 시스템에 마운트하는 역핦
  • Node Service : EBS 볼륨을 노드에 마운트/언마운트하고 컨테이너에서 사용할 수 있도록 관리하는 CSI 노드 컴포넌트

EBS CSI Driver 설치

  • 버전 확인
    # 아래는 aws-ebs-csi-driver 전체 버전 정보와 기본 설치 버전(True) 정보 확인
    aws eks describe-addon-versions \
        --addon-name aws-ebs-csi-driver \
        --kubernetes-version 1.31 \
        --query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
        --output text
  • ISRA 설정 및 확인
    # ISRA 설정 : AWS관리형 정책 AmazonEBSCSIDriverPolicy 사용
    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
    
    # ISRA 확인
    eksctl get iamserviceaccount --cluster ${CLUSTER_NAME}
  • Amazon EBS CSI driver addon 배포
     # Amazon EBS CSI driver addon 배포(설치)
     export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
     eksctl create addon --name aws-ebs-csi-driver --cluster ${CLUSTER_NAME} --service-account-role-arn arn:aws:iam::${ACCOUNT_ID}:role/AmazonEKS_EBS_CSI_DriverRole --force
     kubectl get sa -n kube-system ebs-csi-controller-sa -o yaml | head -5
     
     # 확인
     eksctl get addon --cluster ${CLUSTER_NAME}
     kubectl get deploy,ds -l=app.kubernetes.io/name=aws-ebs-csi-driver -n kube-system
     kubectl get pod -n kube-system -l 'app in (ebs-csi-controller,ebs-csi-node)'
     kubectl get pod -n kube-system -l app.kubernetes.io/component=csi-driver
     
  • ebs-csi-controller 파드에 6개 컨테이너 확인
    kubectl get pod -n kube-system -l app=ebs-csi-controller -o jsonpath='{.items[0].spec.containers[*].name}' ; echo
  • csinodes 확인
       kubectl api-resources | grep -i csi
       kubectl get csinodes
       kubectl describe csinodes
       kubectl get csidrivers
       kubectl describe csidrivers ebs.csi.aws.com
  • (참고) 노드에 최대 EBS 부착 수량 변경 방법
    
    # 방법 1
    aws eks update-addon --cluster-name ${CLUSTER_NAME} --addon-name aws-ebs-csi-driver \
      --addon-version v1.39.0-eksbuild.1 --configuration-values '{
        "node": {
          "volumeAttachLimit": 31,
          "enableMetrics": true
        }
      }'
    # 방법 2
    *cat << EOF > node-attachments.yaml
    "node":
      "volumeAttachLimit": 31
      "enableMetrics": true
    EOF
    aws eks update-addon --cluster-name ${CLUSTER_NAME} --addon-name aws-ebs-csi-driver \
      --addon-version v1.39.0-eksbuild.1 --configuration-values 'file://node-attachments.yaml'
      
      
    #확인 명령어
    kubectl describe csinodes
    kubectl get ds -n kube-system ebs-csi-node -o yaml
    위의 명령어를 실행 하였을때 EBS 부착수량이 31으로 변경 된것을 확인할수 있다.

gp3 스토리지 클래스 생성

# gp3 스토리지 클래스 생성
kubectl get sc
cat <<EOF | kubectl apply -f -
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: gp3
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
allowVolumeExpansion: true
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  type: gp3
  allowAutoIOPSPerGBIncrease: 'true'
  encrypted: 'true'
  fsType: xfs # 기본값이 ext4
EOF
kubectl get sc
kubectl describe sc gp3 | grep Parameters

여기서 VolumeBindingMode 란?

⇒ 볼륨 바인딩 , 동적 프로비저닝 시작 시기를 제어

  • Immediate(기본값)
    • PVC가 생성되면 즉시 PV와 바인딩됨.
    • 바인딩 시점에서 노드 스케줄링 고려 없이 프로비저닝됨.
    • 단점: 바인딩된 PV가 특정 노드에 적합하지 않을 수도 있음.
  • WaitForFirstConsumer
    • PVC가 생성되어도 해당 볼륨을 사용하는 Pod이 스케줄링될 때까지 바인딩을 지연함.
    • Pod의 노드 요구사항(예: nodeSelector, affinity)을 고려한 후에 바인딩되므로, 클러스터 리소스를 더 효율적으로 사용 가능.
    • 주로 영구적인 로컬 스토리지(Local PV)나 가용 영역(AZ, Availability Zone)을 고려해야 하는 클라우드 스토리지에 사용됨.

PVC / PV 파드 테스트

  • 소스 코드
    # 워커노드에서 파드에 추가한 EBS 볼륨 모니터링
    while true; do aws ec2 describe-volumes --filters Name=tag:ebs.csi.aws.com/cluster,Values=true --query "Volumes[].{VolumeId: VolumeId, VolumeType: VolumeType, InstanceId: Attachments[0].InstanceId, State: Attachments[0].State}" --output text; date; sleep 1; done
    
    # PVC 생성
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: ebs-claim
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 4Gi
      storageClassName: gp3
    EOF
    kubectl get pvc,pv
    
    # 파드 생성
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: app
    spec:
      terminationGracePeriodSeconds: 3
      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
    EOF
    
    # PVC, 파드 확인
    kubectl get pvc,pv,pod
    kubectl get VolumeAttachment
    kubectl df-pv

모니터링 후 파드를 생성하면 EBS가 생성 된것을 확인 할수 있습니다.

해당 내용은 Console에서도 확인이 가능합니다.

  • 추가된 EBS 볼륨 상세 확인

    # 추가된 EBS 볼륨 상세 정보 확인 : AWS 관리콘솔 EC2(EBS)에서 확인
    aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq

  • 생성 확인
    
    kubectl get node --label-columns=topology.ebs.csi.aws.com/zone,topology.k8s.aws/zone-id
    
    # 파일 내용 추가 저장 확인
    kubectl exec app -- tail -f /data/out.txt
    
    ## 파드 내에서 볼륨 정보 확인
    kubectl exec -it app -- sh -c 'df -hT --type=overlay'
    kubectl exec -it app -- sh -c 'df -hT --type=xfs'

볼륨 증가

만약 볼륨 증가가 필요하면 다음과 같이 적용 가능 ,단 볼륨을 줄일 순 없다.

  • 볼륨 증가

    # 볼륨 증가
    kubectl patch pvc ebs-claim -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'

  • 확인

    kubectl exec -it app -- sh -c 'df -hT --type=xfs'
    kubectl df-pv
    aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq

3. AWS Volume SnapShots Controller

정의

  • Amazon EBS와 같은 스토리지의 스냅샷 기능을 활용하여 데이터 백업 및 복구를 가능하게 하는 중요한 구성 요소

Volume Snapsot 컨트롤러 설치

  • Snapshot CRDs 설치

    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
    kubectl get crd | grep snapshot
    kubectl api-resources  | grep snapshot

  • Common Snapshot Controller 설치

    # Install Common Snapshot Controller
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
    kubectl get deploy -n kube-system snapshot-controller
    kubectl get pod -n kube-system

  • SnapshotClass 설치

    # Install Snapshotclass
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/master/examples/kubernetes/snapshot/manifests/classes/snapshotclass.yaml
    kubectl get vsclass # 혹은 volumesnapshotclasses
    kubectl describe vsclass

테스트 PVC / 파드 생성

  • PVC, 파드 생성
    # PVC 생성
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: ebs-claim
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 4Gi
      storageClassName: gp3
    EOF
    kubectl get pvc,pv
    
    # 파드 생성
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: app
    spec:
      terminationGracePeriodSeconds: 3
      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
    EOF
    
    # 파일 내용 추가 저장 확인
    kubectl exec app -- tail -f /data/out.txt
  • VolumeShot 생성

    # VolumeSnapshot 생성 : Create a VolumeSnapshot referencing the PersistentVolumeClaim name
     # AWS 관리 콘솔 EBS 스냅샷 확인
     cat <<EOF | kubectl apply -f -
     apiVersion: snapshot.storage.k8s.io/v1
     kind: VolumeSnapshot
     metadata:
       name: ebs-volume-snapshot
     spec:
       volumeSnapshotClassName: csi-aws-vsc
       source:
         persistentVolumeClaimName: ebs-claim
     EOF
    
     # VolumeSnapshot 확인
     kubectl get volumesnapshot
     kubectl get volumesnapshot ebs-volume-snapshot -o jsonpath={.status.boundVolumeSnapshotContentName} ; echo
     kubectl describe volumesnapshot.snapshot.storage.k8s.io ebs-volume-snapshot
     kubectl get volumesnapshotcontents
    
     # VolumeSnapshot ID 확인 
     kubectl get volumesnapshotcontents -o jsonpath='{.items[*].status.snapshotHandle}' ; echo
    
     # AWS EBS 스냅샷 확인
     aws ec2 describe-snapshots --owner-ids self | jq
     aws ec2 describe-snapshots --owner-ids self --query 'Snapshots[]' --output table
    

  • 강제 제거
    # app & pvc 제거 : 강제로 장애 재현
    kubectl delete pod app && kubectl delete pvc ebs-claim
  • 스냅샷으로 복원

    • pv, pvc 확인
      kubectl get pvc,pv
    • 스냅샷으로 PVC 복원 및 파드 생성
      # 스냅샷에서 PVC 로 복원
      
      cat <<EOF | kubectl apply -f -
      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: ebs-snapshot-restored-claim
      spec:
        storageClassName: gp3
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 4Gi
        dataSource:
          name: ebs-volume-snapshot
          kind: VolumeSnapshot
          apiGroup: snapshot.storage.k8s.io
      EOF
      
      # 확인
      kubectl get pvc,pv
      
      # 파드 생성
      cat <<EOF | kubectl apply -f -
      apiVersion: v1
      kind: Pod
      metadata:
        name: app
      spec:
        terminationGracePeriodSeconds: 3
        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-snapshot-restored-claim
      EOF
  • 파일 내용 확인

    • 파드 삭제 전 의 기록, 파드 재생성 후의 기록이 잘 저장 됨

      # 파일 내용 저장 확인 : 파드 삭제 전까지의 저장 기록이 남아 있다. 이후 파드 재생성 후 기록도 잘 저장되고 있다
      kubectl exec app -- cat /data/out.txt

  • 삭제
    # 삭제
    kubectl delete pod app && kubectl delete pvc ebs-snapshot-restored-claim && kubectl delete volumesnapshots ebs-volume-snapshot

4. AWS EFS Controller

Amazon EFS (Elastic File System)

  • AWS에서 제공하는 완전 관리형 NFS (Network File System) 파일 스토리지

EFS 주요 특징

  1. 완전 관리형
    • AWS 에서 운영, 유지보수 관리 하므로 사용자는 관리 부담 없이 사용 가능
  2. 자동 확장
    • 사전 할당 없이 필요한 만큼 저장 공간 사용 가능
  3. 고성능 & 저 지연
    • 병렬 처리를 지원하여 높은 Troughput 제공
    • 수천 개의 EC2 인스턴스가 동시에 엑세스 가능
  4. 멀티 AZ 지원
    • AWS 리전 내에 여러 가용 영역에 데이터를 저장
  5. 온프레미스 및 컨테이너 지원
    • AWS Direct Connect, VPN을 통해 온프레미스 서버에서도 EFS 접근 가능

아키텍처

missing 출처 : https://dev.to/awscommunity-asean/aws-eks-with-efs-csi-driver-and-irsa-using-cdk-dgc
  1. EFS 볼륨은 AWS에서 프로비저닝되며, VPC, 가용 영역, 서브넷, 보안 그룹과 연결됨.
    • NFS 프로토콜을 사용해 어디든 마운트 가능 (랩톱 또는 Kubernetes에서도 가능).
  2. EFS 프로비저너(EFS CSI Driver)가 Kubernetes에 배포되면, 새로운 StorageClass("efs")가 생성됨.
    • Kubernetes에서 PVC(PersistentVolumeClaim)를 생성하면, 이 StorageClass를 참조하여 EFS 프로비저너가 PVC를 처리함.
  3. PVC 처리 과정
    • EFS 볼륨 내에 PVC 전용 하위 디렉토리 생성
    • 해당 디렉토리의 URI와 NFS 정보를 포함한 PV(PersistentVolume) 생성
    • PV를 PVC에 바인딩
  4. 포드(Pod)에서 PVC를 사용하면 자동으로 EFS 볼륨의 하위 디렉토리에 연결됨.
    • Kubernetes에서 EFS 스토리지를 동적으로 프로비저닝하여 사용 가능.

EFS 생성

  • EFS 정보 확인
    # EFS 정보 확인 
    aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
  • aws-efs-csi-driver 전체 버전 확인
    aws eks describe-addon-versions \
        --addon-name aws-efs-csi-driver \
        --kubernetes-version 1.31 \
        --query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
        --output text
    
  • IRSA 설정 및 확인

    # ISRA 설정 : 고객관리형 정책 AmazonEKS_EFS_CSI_Driver_Policy 사용
    eksctl create iamserviceaccount \
     --name efs-csi-controller-sa \
     --namespace kube-system \
     --cluster ${CLUSTER_NAME} \
     --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
     --approve \
     --role-only \
     --role-name AmazonEKS_EFS_CSI_DriverRole
    
    # ISRA 확인
    eksctl get iamserviceaccount --cluster ${CLUSTER_NAME}

  • Amazon EFS CSI Driver 배포
    # Amazon EFS CSI driver addon 배포(설치)
    export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
    eksctl create addon --name aws-efs-csi-driver --cluster ${CLUSTER_NAME} --service-account-role-arn arn:aws:iam::${ACCOUNT_ID}:role/AmazonEKS_EFS_CSI_DriverRole --force
    kubectl get sa -n kube-system efs-csi-controller-sa -o yaml | head -5
  • 확인
    # 확인
    eksctl get addon --cluster ${CLUSTER_NAME}
    kubectl get pod -n kube-system -l "app.kubernetes.io/name=aws-efs-csi-driver,app.kubernetes.io/instance=aws-efs-csi-driver"
    kubectl get pod -n kube-system -l app=efs-csi-controller -o jsonpath='{.items[0].spec.containers[*].name}' ; echo
    kubectl get csidrivers efs.csi.aws.com -o yaml

파드 생성 및 EFS 파일 시스템 적용

  • 노드 모니터링
    # 노드 모니터링
    watch 'kubectl get sc efs-sc; echo; kubectl get pv,pvc,pod'
  • 실습 코드 clone
    # [운영 서버 EC2]
    # 실습 코드 clone
    git clone https://github.com/kubernetes-sigs/aws-efs-csi-driver.git /root/efs-csi
    cd /root/efs-csi/examples/kubernetes/multiple_pods/specs && tree
  • EFS 스토리지 클래스 생성 , 확인
    # EFS 스토리지클래스 생성 및 확인
    cat storageclass.yaml
    kubectl apply -f storageclass.yaml
    kubectl get sc efs-sc
  • PV 생성, 확인
     # PV 생성 및 확인 : volumeHandle을 자신의 EFS 파일시스템ID로 변경
     EfsFsId=$(aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text)
     sed -i "s/fs-4af69aab/$EfsFsId/g" pv.yaml
     cat pv.yaml
     
     kubectl apply -f pv.yaml
     kubectl get pv; kubectl describe pv
  • PVC 생성, 확인
    # PVC 생성 및 확인
    cat claim.yaml
    kubectl apply -f claim.yaml
    kubectl get pvc
  • 파드 생성 및 연동
    # 파드 생성 및 연동 : 파드 내에 /data 데이터는 EFS를 사용
    # 추후에 파드1,2가 각기 다른 노드에 배포되게 추가해두자!
    cat pod1.yaml pod2.yaml
    kubectl apply -f pod1.yaml,pod2.yaml
    kubectl df-pv
  • 파드 정보 확인
    # 파드 정보 확인 : PV에 5Gi 와 파드 내에서 확인한 NFS4 볼륨 크리 8.0E의 차이는 무엇?
    kubectl get pods
    kubectl exec -ti app1 -- sh -c "df -hT -t nfs4"
    kubectl exec -ti app2 -- sh -c "df -hT -t nfs4"
  • 공유 저장소 확인
    # 공유 저장소 저장 동작 확인
    tree /mnt/myefs              # 운영서버 EC2 에서 확인
    tail -f /mnt/myefs/out1.txt  # 운영서버 EC2 에서 확인
    tail -f /mnt/myefs/out2.txt  # 운영서버 EC2 에서 확인
    kubectl exec -ti app1 -- tail -f /data/out1.txt
    kubectl exec -ti app2 -- tail -f /data/out2.txt

Dynamic provisioning using EFS

  • EFS 스토리지클래스 생성 및 확인
    # [운영 서버 EC2]
    # EFS 스토리지클래스 생성 및 확인
    curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml
    cat storageclass.yaml
    sed -i "s/fs-92107410/$EfsFsId/g" storageclass.yaml
    kubectl apply -f storageclass.yaml
    kubectl get sc efs-sc
  • PVC/ 파드 생성, 확인
    curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml
    cat pod.yaml
    kubectl apply -f pod.yaml
    kubectl get pvc,pv,pod
  • PVC / PV 생성 로그 확인
    kubectl krew install stern
    kubectl stern -n kube-system -l app=efs-csi-controller -c csi-provisioner
  • 파드 정보 확인
    kubectl exec -it efs-app -- sh -c "df -hT -t nfs4"
  • 공유 저장소 저장 동작 확인
    tree /mnt/myefs              # 운영서버 EC2 에서 확인
    kubectl exec efs-app -- bash -c "cat /data/out"
    kubectl exec efs-app -- bash -c "ls -l /data/out"
    kubectl exec efs-app -- bash -c "stat /data/"

EFS Access Point 확인

  • EFS Access Point는 EFS의 특정 부분을 격리하고, UID/GID를 강제하여 보안성을 높임.
  • 여러 팀, 여러 애플리케이션이 같은 EFS를 사용할 때 Access Point를 활용하면 보안과 관리가 용이.
특징일반적인 EFS 사용EFS Access Point 사용
접근 방식파일 시스템 전체 접근Access Point별 특정 디렉터리 접근
보안IAM으로 파일 시스템 전체 권한 관리Access Point별 IAM 권한 관리로 보안 강화
관리여러 사용자 권한 관리 부담Access Point별 권한 관리로 용이
사용 사례단순 환경, 파일 시스템 전체 접근 필요다중 사용자 환경, 애플리케이션별 접근 제한 필요
profile
DevOps Engineer

0개의 댓글