EFS로 영구 볼륨 프로비저닝

이 페이지에서는 EFS CSI 드라이버를 사용해서 AWS용 GKE에서 사용할 EFS 기반 PersistentVolume을 설정하는 방법을 설명합니다. Elastic File System(EFS)은 클러스터에 네트워크 파일 시스템을 제공하는 기본 AWS 메커니즘입니다. EFS 기반 PersistentVolume은 EFS 액세스 포인트를 통해 워크로드에서 스토리지를 사용할 수 있게 해주고 워크로드가 연결되지 않은 경우에도 스토리지가 유지되도록 하는 클러스터 리소스입니다.

AWS용 GKE는 PersistentVolume의 정적 프로비저닝과 동적 프로비저닝을 모두 지원합니다. 동적 프로비저닝은 약간 다른 설정을 사용하지만 이후 관리 작업에 드는 수고가 줄어듭니다.

시작하기 전에

이 페이지의 단계를 수행하려면 먼저 다음을 완료합니다.

정적 프로비저닝 개요

Elastic File System(EFS)을 만들고 정적 프로비저닝을 통해 클러스터의 워크로드에 사용할 수 있게 하는 4단계는 다음과 같습니다.

  • EFS 리소스 만들기
  • 네트워크 구성
  • 마운트 대상 만들기
  • PersistentVolume 만들기

마지막 단계는 PersistentVolumeClaim을 실행하여 영구 스토리지를 요청하는 워크로드입니다.

동적 프로비저닝 개요

EFS 리소스를 만들고 동적 프로비저닝을 통해 사용할 수 있게 하려면 다음 4단계도 필요합니다.

  • EFS 리소스 만들기
  • 네트워크 구성
  • 마운트 대상 만들기
  • StorageClass 만들기

StorageClass 만들기는 일회성 작업입니다. 지정된 특성을 가진 스토리지 클래스가 정의되면 워크로드는 PersistentVolumeClaim을 실행하거나 영구 스토리지를 요청할 수 있습니다. 이러한 특성을 가진 스토리지에 대한 모든 PersistentVolumeClaim은 동일한 StorageClass를 요청할 수 있습니다.

일반적인 단계

클러스터에서 정적 프로비저닝 또는 동적 프로비저닝을 사용하는지 여부에 관계없이 여기에 나온 설정 단계로 시작한 다음 필요에 따라 정적 또는 동적 프로비저닝 단계를 계속 진행해야 합니다. EFS를 만들고 액세스할 수 있게 되면 워크로드는 액세스하기 위한 최종 단계를 수행해야 합니다. 이를 수행하는 단계는 EFS 스토리지 사용에 설명되어 있습니다.

AWS EFS 리소스 만들기

정적 또는 동적 프로비저닝을 사용하는지에 관계없이 EFS 리소스가 필요합니다. 클러스터에서 둘 다 사용하는 경우 별도의 EFS 리소스를 만들거나 둘 다 같은 리소스를 사용할 수 있습니다. EFS 리소스 만들기에 대한 자세한 내용은 Amazon EFS 파일 시스템 만들기를 참조하세요.

기존 EFS를 다시 사용할 수도 있으며, 이 경우 이 섹션을 건너뛰고 마운트 대상 만들기를 진행하면 됩니다.

  1. 클러스터가 실행되는 AWS 리전을 가져옵니다.

    gcloud container aws clusters describe CLUSTER_NAME \
      --location=LOCATION \
      --format="value(awsRegion)"
    

    다음을 바꿉니다.

    • CLUSTER_NAME: AWS 클러스터의 이름입니다.
    • LOCATION: AWS 클러스터의 Google Cloud 위치입니다.
  2. 다음 명령어를 사용하여 동일한 AWS 리전에 EFS 리소스 시스템을 만듭니다.

    aws efs create-file-system \
      --region AWS_REGION \
      --performance-mode generalPurpose \
      --query 'FileSystemId' \
      --output text
    

    다음을 바꿉니다.

    • AWS_REGION: 클러스터가 실행되는 AWS 리전입니다.

출력에는 파일 시스템의 ID가 포함됩니다. 이 값을 저장합니다. 서비스 계정의 고유 ID 값을 적어둡니다.

마운트 대상 만들기

EFS용 CSI 드라이버는 EFS 마운트 대상을 통해 파일 시스템에 액세스합니다. 마운트 대상은 AWS 보안 그룹을 사용하여 기본 EFS에 대한 액세스를 제어하는 비공개 IP 주소입니다.

클러스터의 노드 풀이 다른 서브넷에서 실행되는 경우 각 노드 풀 서브넷에 별도의 마운트 대상을 만들어야 합니다.

이 예시에서 각 마운트 대상에 대한 액세스는 마운트 대상 및 노드 풀 머신을 모두 포함하는 단일 보안 그룹으로 보호됩니다. VPC 구성 및 보안 요구사항에 따라 마운트 대상과 노드 풀 워커 노드에 하나씩 2개(또는 그 이상)의 보안 그룹으로 이 구성을 분할해야 할 수 있습니다.

  1. EFS 액세스를 제어하는 전용 보안 그룹 만들기

    클러스터가 실행되는 AWS VPC의 ID를 가져옵니다.

    gcloud container aws clusters describe CLUSTER_NAME \
      --location=LOCATION \
      --format="value(networking.vpcId)"
    

    다음을 바꿉니다.

    • CLUSTER_NAME
    • LOCATION

    출력에는 VPC의 ID가 포함됩니다. 이 값을 저장합니다. 서비스 계정의 고유 ID 값을 적어둡니다.

  2. EFS 마운트 대상에 대한 액세스 제어를 위해 보안 그룹을 만듭니다.

    aws ec2 create-security-group \
      --group-name gke-efs-security-group \
      --description "EFS security group" \
      --vpc-id VPC_ID \
      --output text
    

    VPC_ID를 클러스터가 실행되는 AWS VPC의 ID로 바꿉니다.

    출력에는 새 보안 그룹의 ID가 포함됩니다. 이 값을 저장합니다. 서비스 계정의 고유 ID 값을 적어둡니다.

  3. 기본적으로 AWS는 모든 아웃바운드 트래픽을 허용하는 기본 규칙을 사용해서 보안 그룹을 만듭니다. 기본 아웃바운드 규칙을 삭제합니다.

    aws ec2 revoke-security-group-egress \
      --group-id SECURITY_GROUP_ID
      --ip-permissions '[{"IpProtocol":"-1","FromPort":-1,"ToPort":-1,"IpRanges":[{"CidrIp":"0.0.0.0/0"}]}]'
    

    SECURITY_GROUP_ID를 AWS 보안 그룹의 ID로 바꿉니다.

  4. EFS의 인바운드 및 아웃바운드 트래픽을 승인합니다(포트 2049).

    aws ec2 authorize-security-group-ingress \
        --group-id SECURITY_GROUP_ID \
        --protocol tcp \
        --port 2049 \
        --source-group SECURITY_GROUP_ID
    
    aws ec2 authorize-security-group-egress \
        --group-id SECURITY_GROUP_ID \
        --protocol tcp \
        --port 2049 \
        --source-group SECURITY_GROUP_ID
    
  5. 각 노드 풀 서브넷에서 EFS 마운트 대상을 만듭니다.

    모든 노드 풀과 연관된 서브넷을 나열합니다.

    gcloud container aws node-pools list \
      --cluster=CLUSTER_NAME \
      --location=LOCATION \
      --format="value(subnetId)"
    

    다음을 바꿉니다.

    • CLUSTER_NAME
    • LOCATION

    출력은 서브넷 ID 목록입니다. 이 값을 저장합니다. 서비스 계정의 고유 ID 값을 적어둡니다.

  6. 각 서브넷에 대해 보안 그룹이 적용된 연관된 EFS 마운트 대상을 만듭니다.

    aws efs create-mount-target \
        --file-system-id EFS_ID \
        --subnet-id SUBNET_ID \
        --security-groups SECURITY_GROUP_ID
    

    다음을 바꿉니다.

    • EFS_ID: EFS 리소스의 ID입니다.
    • SUBNET_ID: 노드 풀의 서브넷 ID입니다.
    • SECURITY_GROUP_ID
  7. EFS 보안 그룹을 모든 클러스터 노드 풀에 추가합니다.

    모든 노드 풀의 목록을 가져옵니다.

    gcloud container aws node-pools list \
      --cluster=CLUSTER_NAME \
      --location=LOCATION
    

    다음을 바꿉니다.

    • CLUSTER_NAME
    • LOCATION

    출력에는 클러스터의 노드 풀 이름이 포함됩니다. 이 값을 저장합니다. 서비스 계정의 고유 ID 값을 적어둡니다.

  8. 새 EFS 보안 그룹을 포함하도록 각 노드 풀을 업데이트합니다.

    gcloud container aws node-pools update NODE_POOL_NAME \
      --cluster=CLUSTER_NAME \
      --location=LOCATION  \
      --security-group-ids=SECURITY_GROUP_IDS
    

    다음을 바꿉니다.

    • NODE_POOL_NAME: 노드 풀의 이름입니다.
    • CLUSTER_NAME: 클러스터 이름입니다.
    • LOCATION
    • SECURITY_GROUP_IDS: 워커 노드의 보안 그룹 ID 목록입니다.

PersistentVolume(정적) 또는 StorageClass(동적) 만들기

정적 프로비저닝을 사용하는 경우 다음 단계는 PersistentVolume을 만드는 것입니다. 동적 프로비저닝을 사용하는 경우 EFS 드라이버가 대신 해당 PersistentVolumeClaim에 지정할 워크로드의 StorageClass를 정의합니다. 선택한 프로비저닝 방법과 일치하는 탭을 선택합니다.

정적 프로비저닝

정적 프로비저닝을 사용하는 경우 다음 단계는 EFS 공유를 마운트하는 PersistentVolume을 만드는 것입니다.

  1. EFS 공유에 직접 또는 액세스 포인트를 통해 연결하는지에 따라 적절한 탭을 선택합니다.

    직접 연결하기

    다음 YAML 매니페스트를 efs-volume.yaml이라는 파일에 복사합니다. 매니페스트는 이전에 만든 EFS 스토리지 클래스를 참조합니다.

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: VOLUME_NAME
    spec:
      capacity:
        # Note: storage capacity is not used by the EFS CSI driver.
        # It is required by the PersistentVolume spec.
        storage: 5Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      storageClassName: "" # storageClassName is not required, see note in the following section.
      claimRef:
        name: CLAIM_NAME
        namespace: default
      csi:
        driver: efs.csi.aws.com
        volumeHandle: EFS_ID
    

    다음을 바꿉니다.

    • VOLUME_NAME을 영구 볼륨의 이름으로 바꿉니다.
    • CLAIM_NAME을 PersistentVolumeClaim에 사용할 이름으로 바꿉니다.
    • EFS_ID를 EFS 리소스 ID로 바꿉니다. 예를 들면 fs-12345678a입니다.

    액세스 포인트

    액세스 포인트 기반 볼륨을 만들려면 이를 수동으로 프로비저닝해야 합니다. 자세한 내용은 EFS 액세스 포인트 작업을 참조하세요.

    다음 YAML 매니페스트를 efs-volume.yaml이라는 파일에 복사합니다. 매니페스트는 이전에 만든 EFS 스토리지 클래스를 참조합니다.

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: VOLUME_NAME
    spec:
      capacity:
        # Note: storage capacity is not used by the EFS CSI driver.
        # It is required by the PersistentVolume spec.
        storage: 5Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      # Set storageClassName to empty string for static provisioning. See [Use an EFS resource](/kubernetes-engine/multi-cloud/docs/aws/how-to/use-efs)
      storageClassName: ""
      claimRef:
        name: CLAIM_NAME
        namespace: default
      csi:
        driver: efs.csi.aws.com
        volumeHandle: EFS_ID::ACCESS_POINT_ID
    

    다음을 바꿉니다.

    • VOLUME_NAME을 영구 볼륨의 이름으로 바꿉니다.
    • CLAIM_NAME을 PersistentVolumeClaim에 사용할 이름으로 바꿉니다.
    • EFS_ID를 EFS 리소스 ID로 바꿉니다. 예를 들면 fs-12345678a입니다.
    • ACCESS_POINT_ID를 액세스 포인트의 ID로 바꿉니다. 예를 들면 fsap-1234567890abcde입니다.
  2. YAML을 클러스터에 적용합니다.

    kubectl apply -f efs-volume.yaml
    

    출력에서 PersistentVolume의 생성을 확인합니다.

    persistentvolume/VOLUME_NAME created
    
    

동적 프로비저닝

이 섹션에서는 앞에서 만든 EFS 리소스를 참조하는 StorageClass를 만드는 방법을 설명합니다. 이렇게 하면 개발자는 EFS 리소스 사용에 설명된 단계에 따라 EFS 리소스에 액세스할 수 있습니다.

  1. EFS 리소스 ID를 참조하는 StorageClass를 만듭니다.

    다음 yaml 프래그먼트를 efs-storage-class.yaml이라는 새 파일에 복사합니다. 이 파일에서 설명하는 StorageClass의 특성을 조정하는 방법에 대한 자세한 내용은 EFS StorageClass 매개변수 문서를 참조하세요.

    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: EFS_STORAGE_CLASS_NAME
    provisioner: efs.csi.aws.com
    mountOptions:
      - tls
    parameters:
      provisioningMode: efs-ap
      fileSystemId: EFS_ID
      directoryPerms: "700"
    
    

    다음과 같이 바꿉니다.

    • EFS_STORAGE_CLASS_NAME을 StorageClass에 대해 선택한 이름으로 바꿉니다.
    • EFS_ID를 EFS 리소스 ID(예: fs-12345678a)로 바꿉니다.
  2. YAML을 클러스터에 적용합니다.

    kubectl apply -f efs-storage-class.yaml
    

    성공하면 이 명령어 출력에 다음과 비슷한 행이 포함됩니다.

    storageclass/EFS_STORAGE_CLASS_NAME created

삭제

이전 섹션에서 만든 리소스를 삭제하려면 다음 명령어를 실행합니다.

  1. kubectl을 사용하여 클러스터에서 EFS 클레임 리소스를 삭제합니다.

    kubectl delete -f efs-claim.yaml
    
  2. 정적 프로비저닝을 사용하는 경우 kubectl을 사용하여 클러스터에서 연결된 리소스를 삭제합니다.

    kubectl delete -f efs-volume.yaml
    
  3. 동적 프로비저닝을 사용하는 경우 kubectl을 사용하여 클러스터에서 연결된 리소스를 삭제합니다.

    kubectl delete -f efs-storage-class.yaml
    
  4. 마운트 대상 ID 확인:

    aws efs describe-mount-targets \
    --file-system-id EFS_ID \
    --profile adminuser \
    --region AWS_REGION
    

    다음을 바꿉니다.

    • EFS_ID: EFS 리소스의 ID입니다.
    • AWS_REGION: 클러스터가 실행되는 AWS 리전입니다.

    출력에 마운트 대상 ID가 포함됩니다. 이 값을 저장합니다. 서비스 계정의 고유 ID 값을 적어둡니다.

  5. EFS 마운트 대상을 삭제합니다.

    aws efs delete-mount-target \
    --mount-target-id MOUNT_TARGET_ID \
    --profile adminuser \
    --region AWS_REGION
    

    다음을 바꿉니다.

    • MOUNT_TARGET_ID: EFS 마운트 대상의 ID입니다.
    • AWS_REGION: 마운트 대상의 AWS 리전입니다.
  6. 생성한 모든 보안 그룹을 삭제합니다.

  7. delete-file-system CLI 명령어를 사용하여 파일 시스템을 삭제합니다. describe-file-systems CLI 명령어를 사용하여 파일 시스템 목록을 가져올 수 있습니다. 응답에 파일 시스템 ID가 있습니다.

    aws efs delete-file-system \
      --file-system-id EFS_ID \
      --profile adminuser \
      --region AWS_REGION
    

    다음을 바꿉니다.

    • EFS_ID
    • AWS_REGION

다음 단계