ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [AWS] EKS - Storage(스터디 3주차)
    Infra/Cloud 2023. 5. 8. 22:16

    이번주 스터디에서는 EKS Storage에 대해 다루었다.

     

    On-premise 환경의 kubernetes에서 pv, pvc, hostpath, emptyDir 등을 다뤄본 경험이 있어서 조금은 친숙했다.

     

    하지만 직접 AWS에서 제공하는 Storage를 사용하는건 처음이라 동작원리와 실습이 재미있었다.

     

    EKS에서는 이러한 storage 사용에 대해 다양한 서비스를 제공하고 있었다.

     

    내가 필요할 때, 즉시 사용할 수 있도록 Provisioning 해준다라.. 이런 매력 때문에 돈내고 쓰는거겠지...??

     

     

    < 관리용 인스턴스 자동 접속  스크립트 수정 >

     

    GitHub - k8s-ho/eks-tools: I made a useful tool while doing eks study:)

    I made a useful tool while doing eks study:). Contribute to k8s-ho/eks-tools development by creating an account on GitHub.

    github.com

    git clone https://github.com/k8s-ho/eks-tools
    cd eks-tools
    chmod +x enter-eks-3.sh
    ./enter-eks-3.sh [key pair file]

    => 2주차에서 사용했던 Amazon EKS 윈클릭 배포 설정이 조금 달라진점이 있어 3주차에 맞게 수정했다.

     

     


     

    [참고] AWS에서 제공하는 Storage 관련 비교정리 블로그 

     

    [AWS] 📚 S3 / EBS / EFS 스토리지 서비스 비교

    S3 vs EBS vs EFS 스토리지 비교 EBS, EFS, S3 모두 데이터를 저장하는 파일 저장 공간 서비스임에는 같다. 하지만 각각 서비스 특징과 성능에 따라 사용 용도를 분별할 필요가 있다. 데이터 시점에서 보

    inpa.tistory.com

     

    - [참고] Node의 최대 Volume 갯수 설정

    kubectl get node -o yaml | grep -i Allocatable

    => AWC EC2 Type에 따라 다르지만 Volume의 최대 갯수를 설정할 수 있다.

     

     


     

    - 기본적인 Container에서 사용되는 임시 파일 시스템

    kubectl run test --image=nginx

    nginx image pod 생성과 pod가 배포된 node의 process 현황

    => Container에서 사용되는 임시 파일 시스템을 이해하기 위해서는 container가 간략하게 무엇인지 이해해야한다. container는 쉽게 말하면 하나의 격리된 Process라고 할 수 있으며 Container가 종료되게되면 Container에서 사용되던 공간이 사라지게된다. 이렇게 되는 이유는 Container의 Overlay 구조 때문이며 (각 layer는 read-only로 mount, 상위 layer만 쓰기가 존재) 여러개의 파일시스템을 하나로 합쳐 마치 하나의 파일시스템으로 보이는 것이 특징이다. 어찌되었던 이러한 각각의 layer이 모여 Container의 공간이 구현되며, 쓰기가 가능한 상위 layer는 container가 동작중일 때만 사용되고 재부팅되거나 종료되면 사라지게된다. 따라서 container나 Pod를 사용할 때는 기본적으로 언제든 사라질 수 있다 또는 일회성의 느낌이라는 생각을 가지고 사용해야한다. 즉, Pod는 Stateless하다.

     

     

     

    container가 재기동된다면??? 직접 확인해보자!!

    => test pod에 testtesttest라는 디렉터리를 생성하고 강제로 Pod를 재기동시켜보았다. 보다시피 Pod내의 Container가 재시작 된 것이 보였고 다시 Pod내의 container에 접속해보지만~??? 우리가 생성햇던 testtesttest 디렉터리는 없어졌따... 

     

     

     

    그렇다면 재기동시, Pod Container내에서 작업한 내용들이 언제나 사라지는 것을 지켜볼 수 밖에 없을까??

     

    Volumes

    On-disk files in a container are ephemeral, which presents some problems for non-trivial applications when running in containers. One problem occurs when a container crashes or is stopped. Container state is not saved so all of the files that were created

    kubernetes.io

    apiVersion: v1
    kind: Pod
    metadata:
      name: test
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - mountPath: /test-pd
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          path: /home/ec2-user/
          type: Directory

    Pod를 삭제 후, 다시생성해도 그대로 저장되어잇어 사용가능한 "hello" Directory

    => 당연히 아니다. 중요한 파일이나 설정파일, 로그 등을 별도로 mount하여 사용하는 설정이 존재하며 kubernetes에서는 PV, PVC를 이용해서 stateful한 사용이 가능하다. 가장 기본적으로 사용이 가능한 방법은 hostPath를 mount시켜서 사용하는 것이다. 간단히 말해 Pod가 배포된 Node의 공간을 mount해서 사용하는 것이다. 때문에 Pod가 삭제되어도 PV에 기록된 데이터는 삭제되지 않는다.

     

    => hostPath 사용에 주의할점이 있다면 실수로 해당 Pod가 배포된 Worker node가 아닌 작업용 인스턴스나 타 Node에서 경로를 만들고 제대로 작동안한다고 헤메는 경우가 있다. 이런 부분을 조심해아하며 보안적 측면에서는 "/", "/etc" 같은 중요 파일시스템을 Pod에 Mount하지 않는 것이다. 아무생각 없이 mount하게 된다면 악의적인 사용자나 오해로 인해 Node 자체에 치명적인 영향을 줄 수도 있다.

     


    [참고] Persistent Volumes Type

     

    Persistent Volumes

    This document describes persistent volumes in Kubernetes. Familiarity with volumes is suggested. Introduction Managing storage is a distinct problem from managing compute instances. The PersistentVolume subsystem provides an API for users and administrator

    kubernetes.io

     


    이러한 PV사용에는 정적 provisioning과 동적 provisioning이 있다.

    Provisioning이란??

    말그대로 사용자의 요구에 맞게 시스템 자원을 할당, 배치, 배포해 두었다가 필요 시 즉시 사용할 수 있는 상태로 미리 준비해 두는것이다.

     

    정적 provisioning의 경우, 일반적으로 On-premise에서 많이 사용되며 스토리지 관리자가 직접 저장소를 PV로 생성해놓아야한다(준비해야함)는 단점이 있다. 위에서 사용한 hostPath의 경우, Provisioner를 사용하지 않은 방식이며 해당 Pod가 스케줄링된 Node의 로컬 디스크 Volume을 사용한다. 그러나 만약 Pod에서 mount되도록 설정한 Volume이 존재하지 않는 다른 Node에서 해당 Pod가 실행된다면 로컬 디스크가 없으므로 Pod를 실행할 수 없게 된다.

     

    반면 동적 provisioning의 경우, Kubernetes에서 storageClass를 정의하고 해당 storageClass를 사용하여 필요에 따라 storage Volume을 동적으로 provisioning 할 수 있다. 모든 Node에서 로컬 스토리지 Volume을 provisioning 할 수 있으며, storageClass에서 정의한 용량 제한을 준수하여 Pod에 할당된다. 

     

     

    local-path-provisioner storageClass - 로컬 동적 provisioning

     

    GitHub - rancher/local-path-provisioner: Dynamically provisioning persistent local storage with Kubernetes

    Dynamically provisioning persistent local storage with Kubernetes - GitHub - rancher/local-path-provisioner: Dynamically provisioning persistent local storage with Kubernetes

    github.com

    # local-path-provisioner storageClass 배포
    curl -s -O https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
    kubectl apply -f local-path-storage.yaml
    
    
    # PVC 생성
    curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath1.yaml
    kubectl apply -f localpath1.yaml
    
    
    # Pod 생성
    curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath2.yaml
    kubectl apply -f localpath2.yaml

    => local-path storageClass를 생성하고 이를 이용해 Pod에 Volume을 할당하는 예제이며 local-path-provisioner은 Local storage에 대해 동적 Provisioning을 한다. 사용자가 필요한 PVC를 생성하고 Pod의 Spec에 해당 PVC 정보를 volumeMount spec으로 생성하게되면 local-path-provisioner가 동적으로 PV를 생성하여 PVC와 Binding 시켜준다. 이렇게 PV가 생성되면 Pod는 Pending상태에서 정상적으로 실행되며 자신이 설정한 것처럼 Volume을 사용할 수 있게된다.

     

    => 정적이던 동적이든 PV는 Pod가 삭제되어도 PV에 데이터가 존재한다는 것은 당연히 같다.

     

     

     

     

    CSI - Container Storage Interface

     

    Container Storage Interface (CSI) for Kubernetes GA

    Author: Saad Ali, Senior Software Engineer, Google The Kubernetes implementation of the Container Storage Interface (CSI) has been promoted to GA in the Kubernetes v1.13 release. Support for CSI was introduced as alpha in Kubernetes v1.9 release, and promo

    kubernetes.io

    CSI Driver

     

    스토리지 - Amazon EKS

    이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

    docs.aws.amazon.com

    기존의 Kubernetes에서의 Volume Plugin은 "in-tree"로 kubernetes code내의 일부로 포함되어 관리되고 있었다. 때문에 storage system을 kubernetes에서 지원하려는 vendor code와의 kubernetes 바이너리간의 보안 문제나 안정성 문제가 존재했으며, 이로인해 테스트나 유지보수가 어렵거나 불가능한 경우도 있었다고 한다. 

     

    이러한 문제를 해결하기 위해 도입된 것이 바로 CSI이다. CSI는 별도의 Controller 역할을 하는 Pod 를 통해 동작하며 Volume Plugin(Storage Provisioner)을 개발하고 관리하기 위한 표준 인터페이스를 제공한다. 이를 통해 Vendor들은 자체적으로 Volume Plugin을 개발하면서도 Kubernetes와 통합이 가능해졌으며 Kubernetes의 Version up과 별개로 Volume 기능을 제공할 수 있게 되었다. 

     

    [요약] Kubernetes CSI (Container Storage Interface)는 Kubernetes 클러스터에서 다양한 스토리지 프로비저너를 통합하고 표준화하기 위한 인터페이스이다.

     

    [참고] Kubernetes에서는 각기 다른 여러 기능을 제공하려다보니 제약이 생겨, 해결을 위한 표준을 만들게 되는 경우가 생각보다 많은 것 같다. 보안관련 사례로는 OPA project가 있다. 

     

     

     

     

    AWS CSI Driver

    AWS에서 제공하는 kubernetes 클러스터에서는 AWS CSI Driver를 이용햐여 AWS Storage Service(EBS,EFS 등)를 Kubernetes 클러스터에서 동적으로 Provisioning하여 사용할 수 있다. AWS CSI Driver는 Kubernetes Cluster 내에 csi-controller와 csi-node라는 Pod로 배포되어 기능한다.

     

    * csi-controller: AWS API를 호출하여 AWS Storage Resource를 관리

    * csi-node: Kubelet과 상호작용하며 AWS Storage를 Pod에 마운트시킴

     

    [요약] AWS의 EBS를 통해 PV를 생성하여 Pod가 사용할 수 있도록 해주는 역할을 하는 것이 EBS-CSI-Driver(csi-controller + csi-node)이다.

     

     

     

    - Kubernetes 공식문서 참고

     

    Volumes

    On-disk files in a container are ephemeral, which presents some problems for non-trivial applications when running in containers. One problem occurs when a container crashes or is stopped. Container state is not saved so all of the files that were created

    kubernetes.io

    => kubernetes v1.17까지(별도의 csi-controller driver가 나온 이후가 아닐까??)는 Volume type으로 awsElasticBlockStore을 지원했던 것으로 보여진다. 또한 위에서 설명한 대략적인 내용들도 kubernetes 공식문서에 작성되어있다.

     

     

    Elastic Block Store 사용시 주의사항

     

    Persistent Volumes

    This document describes persistent volumes in Kubernetes. Familiarity with volumes is suggested. Introduction Managing storage is a distinct problem from managing compute instances. The PersistentVolume subsystem provides an API for users and administrator

    kubernetes.io

    1. PersistentVolume, PersistentVolumeClaim의 accessModes는 ReadWriteOnce로 설정

    => 왜 ReadWriteOnce를 사용해야하는지는 잘 이해가 되지 않는다..ㅠ

     

     

    2. Pod와 EBS는 같은 AZ(Availability Zones)에 존재해야한다(EBS Stoarge의 기본설정이 동일 AZ에 있는 instance에만 연결이 가능하기 때문에)

     

     

     

     그럼 AWS CSI Driver를 사용해보자!

    - ISRA 설정: 

    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

    => Custom Policy가 아닌 AWS에서 제공하는 관리형 정책인 AmazonEBSCSIDriverPolicy 사용했다.

     

     

     

    aws-ebs-csi-driver는 eks에서 addon으로 제공하므로 추가

    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
    # addon 추가 확인
    eksctl get addon --cluster ${CLUSTER_NAME}

    addon 추가 확인

     

     

    ebs-csi driver 배포 여부 확인 및 관련 Pod Container 정보 확인

    Driver가 정상적으로 배포된 것을 확인할 수 있음

     

    ebs-csi-controller Pod

    k get pod -n kube-system ebs-csi-controller-67658f895c-662nj \
    -o jsonpath='{range .spec.containers[*]}{.name}{"\n"}{end}'

    ebs-csi-controller Pod 내부의 container 확인

    => 아까봤던 그림에서처럼 6개의 container로 이루어진 Pod인 것을 확인할 수 있었다.

     

    ebs-csi-node Pod

     

     

    StorageClass를 생성해보자

    cat <<EOT > gp3-sc.yaml
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: gp3
    allowVolumeExpansion: true # 자동 볼륨 확장
    provisioner: ebs.csi.aws.com
    volumeBindingMode: WaitForFirstConsumer
    parameters:
      type: gp3
      allowAutoIOPSPerGBIncrease: 'true'
      encrypted: 'true'  # Volume 암호화 옵션
      #fsType: ext4 # 기본값이 ext4 이며 xfs 등 변경 가능 >> 단 스냅샷 경우 ext4를 기본으로하여 동작하여 xfs 사용 시 문제가 될 수 있음 - 테스트해보자
    EOT

    gp3 StorageClass 생성 확인

     

    GitHub - kubernetes-sigs/aws-ebs-csi-driver: CSI driver for Amazon EBS https://aws.amazon.com/ebs/

    CSI driver for Amazon EBS https://aws.amazon.com/ebs/ - GitHub - kubernetes-sigs/aws-ebs-csi-driver: CSI driver for Amazon EBS https://aws.amazon.com/ebs/

    github.com

    => gp3 type의 StorageClass를 생성하였다. 참고로 gp2는 Default이다. StorageClass 관련 Parameter 관련 옵션은 위의 링크를 참고하자.

     

     

     

    생성된 StorageClass를 이용하여 PVC를 생성해보자

    cat <<EOT > awsebs-pvc.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: ebs-claim
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 4Gi
      storageClassName: gp3
    EOT
    kubectl apply -f awsebs-pvc.yaml

    PVC가 생성된 것을 확인

    => PVC가 생성되었으나 PV가 없으므로 아직 Pending 상태이다. 요청 spec은 gp3 StorageClass에 4Gi 크기이다.

     

     

     

    그렇다면 PVC으로 Volume을 사용하도록 설정한 Pod를 생성하면??

    Pod 생성전

    cat <<EOT > awsebs-pod.yaml
    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
    EOT
    kubectl apply -f awsebs-pod.yaml

    => Pod를 생성하였더니 ebs-csi controller에 의해 동적 Provisioning이 진행되어 PV가 생성되었고 PVC와 Bound되면서 Pod가 생성되었다.

     

     

    EBS volume이 추가된 것을 확인할 수 있었다.

    => AWS GUI에서도 PVC에 명시했던 gp3 StorageClass의 4GiB 짜리 Volume이 생성된 것을 확인할 수 있었다.

     

     

     

    동적 Provisioning된 PV 정보를 살펴보자

    => PV를 자세히보니 PV를 동적으로 Provisioning하기 위한 node 선택 조건 nodeAffinity가 명시되어있었다. 

     

     

     

    만약 Pod 종료하지않고 Pod에 mount된 volume의 용량을 늘리고 싶다면??

    kubectl patch pvc ebs-claim -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'

    => kubectl patch를 이용해서 용량 증가가 가능하다(한번만 가능한것인지.. 여러번하니까 안된다..). 참고로 위의 방법으로 변경하게되면 적용되어있는 PV, PVC spec 역시 자동으로 함께 변경된다. 크기를 줄이는 것도 시도해보았으나 이전 값보다 줄이는 것은 불가능하다는 문구가 나온다..ㅠ 줄이는 것은 PVC 삭제 후 다시 진행해야하므로 잘 고려해서 진행하자..

     

     

     

    [참고] krew plugin "df-pv"

     

    Krew – kubectl plugin manager

    © 2023 The Kubernetes Authors. Krew is a Kubernetes SIG CLI project. Edit Page ·

    krew.sigs.k8s.io

    => 현재 Pod가 사용하고 있는 PV의 정보를 한눈에 보여주는 plugin이다. 굉장히 유용하게 사용할 수 있을 것 같다:)

     

     

     


     

    AWS Volume SnapShots Controller

    - EBS Volume을 자동 백업할 때 사용되는 기능이다. EBS CSI-Driver의 Container 중에 snapshotter가 존재하지만 자동적으로 Volume snapshot이 진행되는 기능은 아직 준비중인 것으로 보인다고 한다. 때문에 현재는 사용자가 필요한 리소스들을 배포해줘야한다.

    # Install Snapshot CRDs
    curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
    curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
    curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
    kubectl apply -f snapshot.storage.k8s.io_volumesnapshots.yaml,snapshot.storage.k8s.io_volumesnapshotclasses.yaml,snapshot.storage.k8s.io_volumesnapshotcontents.yaml
    kubectl get crd | grep snapshot
    kubectl api-resources  | grep snapshot
    
    
    # Install Common Snapshot Controller
    curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
    curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
    kubectl apply -f rbac-snapshot-controller.yaml,setup-snapshot-controller.yaml
    kubectl get deploy -n kube-system snapshot-controller
    kubectl get pod -n kube-system -l app=snapshot-controller
    
    
    # Install Snapshotclass
    curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/master/examples/kubernetes/snapshot/manifests/classes/snapshotclass.yaml
    kubectl apply -f snapshotclass.yaml
    kubectl get vsclass # 혹은 volumesnapshotclasses

    => Snapshot을 사용하기 위해서는 먼저 kubernetes의 resource으로 만들어줘야한다. Kubernetes의 Custom Resource Definition을 이용해서 Custom Resource를 먼저 생성해주자. 생성이 완료되면 Crd 리소스로도 확인이 가능하며 api-resource로도 확인이 가능하다. 이후 Snapshot Controller와 SnapshotClass를 배포해주면 된다. 테스트에 사용될 Pod와 StorageClass, PVC는 이전에 위에서 사용했던 예시를 사용하였다.

     

     

    - Volume snapshot 진행

    # Volume 및 Pod 생성
    kubectl apply -f gp3-sc.yaml
    kubectl apply -f awsebs-pvc.yaml
    kubectl apply -f awsebs-pod.yaml
    
    
    # Snapshot 진행
    cat <<EOT > ebs-volume-snapshot.yaml
    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: ebs-volume-snapshot
    spec:
      volumeSnapshotClassName: csi-aws-vsc
      source:
        persistentVolumeClaimName: ebs-claim
    EOF
    
    k apply -f ebs-volume-snapshot.yaml

    snapshot이 생성된 것을 확인할 수 있다.

    => Snapshot을 진행하였더니 Volume이 Snapshot 된 것을 확인할 수 있었다.

    => 이러한 snapshot진행을 Lifecycle로 만들어서 백업해놓으면 조금더 안정성 있는 인프라를 구축하는데 도움이 될 수있다.

     

     

     

    Volume이 삭제되었다면?? -> Snapshot을 이용한 복구!!

    cat <<EOT > ebs-snapshot-restored-claim.yaml
    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
    EOT
    cat ebs-snapshot-restored-claim.yaml | yh
    kubectl apply -f ebs-snapshot-restored-claim.yaml

    awebs-pod.yaml에서 해당 부분만 snapshot Claim으로 수정 후 배포

    => 실수로 위에서 배포한 Pod/app과 PV를 삭제해버렸다면??? 하지만 우리는 snapshot을 가지고있다. 복구할 snapshot을 이용해 PVC를 만들고(spec.dataSource 부분) 다시 Pod를 배포하게되면 정상적으로 이전의 PV를 가져다 사용할 수 있게된다.

     

     


     

    AWS EFS Controller

    Elastic File Storage

    # EFS 정보 확인 
    aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
    
    # IAM 정책 생성
    curl -s -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
    
    # 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::${ACCOUNT_ID}:policy/AmazonEKS_EFS_CSI_Driver_Policy \
      --approve
    
    # ISRA 확인
    kubectl get sa -n kube-system efs-csi-controller-sa -o yaml | head -5
    eksctl get iamserviceaccount --cluster myeks
    
    # EFS Controller 설치
    helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/
    helm repo update
    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
    
    # 확인
    helm list -n kube-system
    kubectl get pod -n kube-system -l "app.kubernetes.io/name=aws-efs-csi-driver,app.kubernetes.io/instance=aws-efs-csi-driver"

    => EFS 경우 EBS와는 다르게 ISRA 설정시 AWS에서 제공하는 정책이 아닌 Custom IAM을 생성하여 정책을 적용해야한다. EBS와의 차이점은 당연히 있지만 어떤상황일때 EBS를 사용할지 EFS를 사용할지를 고려하는게 중요한 것 같다. EFS는 콘텐츠를 다룰 때 사용하는 것이 좋다고한다(코드 및 미디어 파일을 저장)

     

    => EFS의 네트워크 부분을 확인해보니 그림과 같이 가용영역이 연결된 것을 확인할 수 있었다.

     

     

     

    그렇다면 생성한 EFS를 Pod에서 사용할 수 있도록 설정해보자

    - 정적 Provisioning 방식

    # 실습 코드 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 스토리지클래스 생성
    kubectl apply -f storageclass.yaml
    kubectl get sc efs-sc
    
    # 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 | yh
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: efs-pv
    spec:
      capacity:
        storage: 5Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      storageClassName: efs-sc
      csi:
        driver: efs.csi.aws.com
        volumeHandle: fs-06e0ab15a3588e75d
    
    kubectl apply -f pv.yaml
    kubectl get pv; kubectl describe pv
    
    # PVC 생성 및 확인
    cat claim.yaml | yh
    kubectl apply -f claim.yaml
    kubectl get pvc
    
    # 파드 생성 및 연동 : 파드 내에 /data 데이터는 EFS를 사용
    cat pod1.yaml pod2.yaml | yh
    kubectl apply -f pod1.yaml,pod2.yaml
    kubectl df-pv
    
    # 파드 정보 확인 : PV에 5Gi 와 파드 내에서 확인한 NFS4 볼륨 크리 8.0E의 차이는 무엇? 파드에 6Gi 이상 저장 가능한가?
    kubectl get pods
    kubectl exec -ti app1 -- sh -c "df -hT -t nfs4"
    kubectl exec -ti app2 -- sh -c "df -hT -t nfs4"
    Filesystem           Type            Size      Used Available Use% Mounted on
    127.0.0.1:/          nfs4            8.0E         0      8.0E   0% /data
    
    # 공유 저장소 저장 동작 확인
    tree /mnt/myefs              # 작업용EC2에서 확인
    tail -f /mnt/myefs/out1.txt  # 작업용EC2에서 확인
    kubectl exec -ti app1 -- tail -f /data/out1.txt
    kubectl exec -ti app2 -- tail -f /data/out2.txt
    
    # 쿠버네티스 리소스 삭제
    kubectl delete pod app1 app2 
    kubectl delete pvc efs-claim && kubectl delete pv efs-pv && kubectl delete sc efs-sc

    => PV 작성시에 EFS를 사용할 것이기때문에 나의 EFS ID로 작성해주어야한다.

     

     

     

    - 적 Provisioning 방식

    # 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 | yh
    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 | yh
    kubectl apply -f pod.yaml
    kubectl get pvc,pv,pod
    
    # PVC/PV 생성 로그 확인
    kubectl logs -n kube-system -l app=efs-csi-controller -c csi-provisioner -f
    
    # 파드 정보 확인
    kubectl exec -it efs-app -- sh -c "df -hT -t nfs4"
    Filesystem           Type            Size      Used Available Use% Mounted on
    127.0.0.1:/          nfs4            8.0E         0      8.0E   0% /data
    
    # 공유 저장소 저장 동작 확인
    tree /mnt/myefs              # 작업용EC2에서 확인
    kubectl exec efs-app -- bash -c "cat data/out"
    
    # 쿠버네티스 리소스 삭제
    kubectl delete -f pod.yaml
    kubectl delete -f storageclass.yaml

    => 위와 같이 동적으로 Provisioing되어 Pod에서 사용할 수 있게 되었으며 EFS의 Access Points에서도 확인할 수 있었다.

     

     


     

    이번 주차에서는 AWS에서 제공하는 Storage 서비스들을 Kubernetes에서 사용할 수 있는 방법과 원리, 그리고 Volume을 제공하는 정적, 동적 Provisioning 방식 등에 대해 공부할 수 있는 시간이였다. 가장 많이 사용하는 몇가지 Storage 들에 대해 익혔으니 필요시 상황에 맞게 사용하면 될 것 같다. 아쉽게도 Storage에 대한 부분을 업무를 진행하며 자주 만날일은 없을 것같지만 내가 필요한 무언가를 구현하거나 구축할 때, 큰 도움이 될 것 같다. 

    반응형

    댓글

Designed by Tistory.