

 **이 페이지 개선에 도움 주기** 

이 사용자 가이드에 기여하려면 모든 페이지의 오른쪽 창에 있는 **GitHub에서 이 페이지 편집** 링크를 선택합니다.

# 클러스터에 애플리케이션 데이터 스토리지 사용
<a name="storage"></a>

애플리케이션의 스토리지 요구 사항에 맞게 Amazon EKS와 함께 다양한 AWS 스토리지 서비스를 사용할 수 있습니다. AWS에서 지원하는 광범위한 컨테이너 스토리지 인터페이스(CSI) 드라이버를 통해 Amazon EKS에서 실행되는 애플리케이션의 스토리지 요구 사항에 따라 Amazon EBS, Amazon S3, Amazon EFS, Amazon FSX, Amazon File Cache를 쉽게 사용할 수 있습니다. Amazon EKS 클러스터의 백업을 관리하려면 [AWS Backup support for Amazon EKS](https://docs.aws.amazon.com/aws-backup/latest/devguide/working-with-supported-services.html#working-with-eks)를 참조하세요.

이 장에서는 Amazon EKS 클러스터를 위한 스토리지 옵션에 관해 다룹니다.

**Topics**
+ [Amazon EBS와 함께 Kubernetes 볼륨 스토리지 사용](ebs-csi.md)
+ [Amazon EFS와 함께 탄력적 파일 시스템 스토리지 사용](efs-csi.md)
+ [Amazon FSx for Lustre와 함께 고성능 앱 스토리지 사용](fsx-csi.md)
+ [FSx for NetApp ONTAP과 함께 고성능 앱 스토리지 사용](fsx-ontap.md)
+ [Amazon FSx for OpenZFS와 함께 데이터 스토리지 사용](fsx-openzfs-csi.md)
+ [Amazon File Cache를 사용한 지연 시간 최소화](file-cache-csi.md)
+ [Mountpoint for Amazon S3 CSI 드라이버를 통해 Amazon S3 객체에 액세스](s3-csi.md)
+ [CSI 볼륨의 스냅샷 기능 활성화](csi-snapshot-controller.md)

# Amazon EBS와 함께 Kubernetes 볼륨 스토리지 사용
<a name="ebs-csi"></a>

**참고**  
 **신규:** Amazon EKS Auto Mode는 블록 스토리지에 대한 일상적인 작업을 자동화합니다. [EKS Auto Mode에 샘플 상태 저장 워크로드 배포](sample-storage-workload.md) 방법에 대해 알아봅니다.

[Amazon Elastic Block Store(Amazon EBS) CSI(Container Storage Interface) 드라이버](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/)에서는 Amazon EBS 볼륨의 수명 주기를 사용자가 생성하는 Kubernetes 볼륨의 스토리지로 관리합니다. Amazon EBS CSI 드라이버는 Amazon EBS 볼륨을 Kubernetes 볼륨 유형인 일반 [임시 볼륨](https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/) 및 [영구 볼륨](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)에 사용할 수 있도록 만듭니다.

## 고려 사항
<a name="ebs-csi-considerations"></a>
+ Amazon EBS CSI 컨트롤러를 EKS Auto Mode 클러스터에 설치할 필요가 없습니다.
+ Amazon EBS 볼륨을 Fargate 포드에 탑재할 수 없습니다.
+ Amazon EBS CSI 컨트롤러는 Fargate 노드에서 실행할 수 있지만 Amazon EBS CSI 노드 `DaemonSet`은(는) Amazon EC2 인스턴스에서만 실행할 수 있습니다.
+ Amazon EBS 볼륨 및 Amazon EBS CSI 드라이버는 Amazon EKS Hybrid Nodes와 호환되지 않습니다.
+ 최신 추가 기능 버전과 하나의 이전 버전에 대한 지원이 제공됩니다. 최신 버전에서 발견된 버그나 취약성에 대한 수정 사항은 새 마이너 버전의 이전 릴리스로 백포트됩니다.
+ EKS 자동 모드를 사용하려면 스토리지 클래스에서 `ebs.csi.eks.amazonaws.com`을 프로비저너로 사용해야 합니다. 표준 Amazon EBS CSI 드라이버(`ebs.csi.aws.com`)는 자체 볼륨을 별도로 관리합니다. EKS 자동 모드에서 기존 볼륨을 사용하려면 볼륨 스냅샷을 사용하여 자동 모드 프로비저너를 사용하는 스토리지 클래스로 마이그레이션합니다.

**중요**  
Amazon EBS CSI 드라이버의 스냅샷 기능을 사용하려면 먼저 CSI 스냅샷 컨트롤러를 설치해야 합니다. 자세한 내용은 [CSI 볼륨의 스냅샷 기능 활성화](csi-snapshot-controller.md) 섹션을 참조하세요.

## 사전 조건
<a name="ebs-csi-prereqs"></a>
+ 기존 클러스터가 있어야 합니다. 필요한 플랫폼 버전을 확인하려면 다음 명령을 실행합니다.

  ```
  aws eks describe-addon-versions --addon-name aws-ebs-csi-driver
  ```
+ EBS CSI 드라이버에는 AWS IAM 권한이 필요합니다.
  +  AWS는 EKS Pod Identity 사용을 제안합니다. 자세한 내용은 [EKS Pod Identity 설정 개요](pod-identities.md#pod-id-setup-overview) 섹션을 참조하세요.
  + 서비스 계정에 대한 IAM 역할에 대한 자세한 내용은 [클러스터에 대한 IAM OIDC 공급자 생성](enable-iam-roles-for-service-accounts.md) 섹션을 참조하세요.

## 1단계-IAM 역할 생성
<a name="csi-iam-role"></a>

Amazon EBS CSI 플러그 인이 사용자를 대신하여 AWS API를 직접 호출하려면 IAM 권한이 필요합니다. 이 단계를 수행하지 않는 경우 추가 기능을 설치하려고 시도하고 `kubectl describe pvc`를 실행하면 `failed to provision volume with StorageClass` 오류와 함께 `could not create volume in EC2: UnauthorizedOperation`가 표시됩니다. 자세한 내용은 GitHub의 [Set up driver permission](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/master/docs/install.md#set-up-driver-permissions)을 참조하세요.

**참고**  
IMDS에 대한 액세스 권한을 차단하지 않는 한 포드는 IAM 역할에 할당된 권한에 대한 액세스 권한이 있습니다. 자세한 내용은 [모범 사례로 Amazon EKS 클러스터 보호](security-best-practices.md) 섹션을 참조하세요.

다음 절차에서는 IAM 역할을 생성하고 AWS 관리형 정책을 연결하는 방법을 보여줍니다. 이 절차를 구현하려면 다음 도구 중 하나를 사용할 수 있습니다.
+  [`eksctl`](#eksctl_store_app_data) 
+  [AWS Management Console](#console_store_app_data) 
+  [AWS CLI](#awscli_store_app_data) 

**참고**  
범위가 축소된 권한으로 자체 관리형 정책을 생성할 수 있습니다. [https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonEBSCSIDriverPolicy.html](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonEBSCSIDriverPolicy.html)를 검토하고 권한이 감소된 사용자 지정 IAM 정책을 생성합니다.

**참고**  
이 절차의 특정 단계는 드라이버를 Amazon EKS 추가 기능으로 사용하기 위해 작성되었습니다. 드라이버를 자체 관리형 추가 기능으로 드라이버를 사용하려면 여러 단계가 필요합니다. 자세한 내용은 GitHub의 [Set up driver permissions](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/master/docs/install.md#set-up-driver-permissions)를 참조하세요.

### `eksctl`
<a name="eksctl_store_app_data"></a>

1. IAM 역할을 생성하여 정책을 연결합니다. AWS은(는) AWS 관리형 정책을 유지 관리하거나 자체 사용자 지정 정책을 생성할 수 있습니다. IAM 역할을 생성하고 다음 명령을 사용하여 AWS 관리형 정책을 연결할 수 있습니다. *my-cluster*를 해당 클러스터의 이름으로 바꿉니다. 이 명령은 IAM 역할을 생성하고 IAM 정책을 연결하는 AWS CloudFormation 스택을 배포합니다.

   ```
   eksctl create iamserviceaccount \
           --name ebs-csi-controller-sa \
           --namespace kube-system \
           --cluster my-cluster \
           --role-name AmazonEKS_EBS_CSI_DriverRole \
           --role-only \
           --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
           --approve
   ```

1. 사용자 지정 [KMS 키](https://aws.amazon.com/kms/)를 사용하지 않는 경우 이 단계를 건너뛸 수 있습니다. Amazon EBS 볼륨의 암호화에 사용자 지정 KMS 키를 사용하는 경우 필요에 따라 IAM 역할을 사용자 지정합니다. 예를 들어, 다음을 수행합니다.

   1. 다음 코드를 복사하여 새로운 `kms-key-for-encryption-on-ebs.json` 파일에 붙여 넣습니다. *custom-key-arn*을 사용자 지정 [KMS 키 ARN](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awskeymanagementservice.html#awskeymanagementservice-key)으로 바꿉니다.

      ```
      {
            "Version":"2012-10-17",		 	 	 
            "Statement": [
              {
                "Effect": "Allow",
                "Action": [
                  "kms:CreateGrant",
                  "kms:ListGrants",
                  "kms:RevokeGrant"
                ],
                "Resource": ["arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"],
                "Condition": {
                  "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                  }
                }
              },
              {
                "Effect": "Allow",
                "Action": [
                  "kms:Encrypt",
                  "kms:Decrypt",
                  "kms:ReEncrypt*",
                  "kms:GenerateDataKey*",
                  "kms:DescribeKey"
                ],
                "Resource": ["arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"]
              }
            ]
          }
      ```

   1. 정책을 생성합니다. *KMS\$1Key\$1For\$1Encryption\$1On\$1EBS\$1Policy*를 다른 이름으로 변경할 수 있습니다. 그러나 이렇게 하는 경우 이후 단계에서도 변경해야 합니다.

      ```
      aws iam create-policy \
            --policy-name KMS_Key_For_Encryption_On_EBS_Policy \
            --policy-document file://kms-key-for-encryption-on-ebs.json
      ```

   1. 다음 명령을 사용하여 IAM 정책을 역할에 연결합니다. *111122223333*을 계정 ID로 바꿉니다.

      ```
      aws iam attach-role-policy \
            --policy-arn arn:aws:iam::111122223333:policy/KMS_Key_For_Encryption_On_EBS_Policy \
            --role-name AmazonEKS_EBS_CSI_DriverRole
      ```

### AWS Management Console
<a name="console_store_app_data"></a>

1. IAM 콘솔(https://console.aws.amazon.com/iam/)을 엽니다.

1. 왼쪽 탐색 창에서 **역할**을 선택합니다.

1. **역할** 페이지에서 **역할 생성**을 선택합니다.

1. **신뢰할 수 있는 엔터티 선택** 페이지에서 다음을 수행합니다.

   1. **신뢰할 수 있는 엔터티 유형** 섹션에서 **웹 자격 증명**을 선택합니다.

   1. **아이덴티티 제공업체(Identity provider)**의 경우 클러스터에 대해 **OpenID Connect 공급자 URL(OpenID Connect provider URL)**을 선택합니다(Amazon EKS의 **개요**에 표시된 대로).

   1. **대상**에서 `sts.amazonaws.com`을 입력합니다.

   1. **다음**을 선택합니다.

1. **권한 추가** 페이지에서 다음을 수행합니다.

   1. **필터 정책** 상자에 `AmazonEBSCSIDriverPolicy`를 입력합니다.

   1. 검색에서 반환된 `AmazonEBSCSIDriverPolicy` 왼쪽에 있는 확인란을 선택합니다.

   1. **다음**을 선택합니다.

1. **이름, 검토 및 생성** 페이지에서 다음을 수행합니다.

   1. **역할 이름**에 역할의 고유한 이름(예: *AmazonEKS\$1EBS\$1CSI\$1DriverRole*)을 입력합니다.

   1. **태그 추가(선택사항)**에서 태그를 키-값 페어로 연결하여 메타데이터를 역할에 추가합니다. IAM에서 태그 사용에 대한 자세한 내용을 알아보려면 [IAM 사용 설명서](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html)의 *IAM 리소스에 태깅*을 참조하세요.

   1. **역할 생성**을 선택합니다.

1. 역할을 생성한 후 편집할 수 있도록 콘솔에서 이 역할을 선택하여 엽니다.

1. **신뢰 관계** 탭을 선택한 후 **신뢰 정책 편집**을 선택합니다.

1. 다음과 비슷한 줄을 찾습니다.

   ```
   "oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
   ```

   이전 줄의 끝에 쉼표를 추가한 다음 이전 줄 뒤에 다음 줄을 추가합니다. *region-code*를 클러스터가 있는 AWS 리전으로 바꿉니다. *EXAMPLED539D4633E53DE1B71EXAMPLE*을 클러스터의 OIDC 공급자 ID로 바꿉니다.

   ```
   "oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa"
   ```

1. **신뢰 정책 업데이트**를 선택하여 종료합니다.

1. Amazon EBS 볼륨의 암호화에 사용자 지정 [KMS 키](https://aws.amazon.com/kms/)를 사용하는 경우 필요에 따라 IAM 역할을 사용자 지정합니다. 예를 들어, 다음을 수행합니다.

   1. 왼쪽 탐색 창에서 **정책**을 선택합니다.

   1. **정책** 페이지에서 **정책 생성**을 선택합니다.

   1. **정책 생성** 페이지에서 **JSON** 탭을 선택합니다.

   1. 다음 코드를 복사하여 편집기에 붙여 넣어 *custom-key-arn*을 사용자 지정 [KMS 키 ARN](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awskeymanagementservice.html#awskeymanagementservice-key)으로 바꿉니다.

      ```
      {
            "Version":"2012-10-17",		 	 	 
            "Statement": [
              {
                "Effect": "Allow",
                "Action": [
                  "kms:CreateGrant",
                  "kms:ListGrants",
                  "kms:RevokeGrant"
                ],
                "Resource": ["arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"],
                "Condition": {
                  "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                  }
                }
              },
              {
                "Effect": "Allow",
                "Action": [
                  "kms:Encrypt",
                  "kms:Decrypt",
                  "kms:ReEncrypt*",
                  "kms:GenerateDataKey*",
                  "kms:DescribeKey"
                ],
                "Resource": ["arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"]
              }
            ]
          }
      ```

   1. **다음: 태그**를 선택합니다.

   1. **태그 추가(선택사항)** 페이지에서 **다음: 검토**를 선택합니다.

   1. **이름**에 정책의 고유한 이름(예: *KMS\$1Key\$1For\$1Encryption\$1On\$1EBS\$1Policy*)을 입력합니다.

   1. **정책 생성**을 선택합니다.

   1. 왼쪽 탐색 창에서 **역할**을 선택합니다.

   1. 콘솔에서 ** *AmazonEKS\$1EBS\$1CSI\$1DriverRole* **을 선택하여 열고 편집합니다.

   1. **권한 추가** 드롭다운 목록에서 **정책 연결**을 선택합니다.

   1. **정책 필터링** 상자에 *KMS\$1Key\$1For\$1Encryption\$1On\$1EBS\$1Policy*를 입력합니다.

   1. 검색에서 반환된 *KMS\$1Key\$1For\$1Encryption\$1On\$1EBS\$1Policy* 왼쪽의 확인란을 선택합니다.

   1. **정책 연결**을 선택합니다.

### AWS CLI
<a name="awscli_store_app_data"></a>

1. 클러스터의 OIDC 공급자 URL을 확인합니다. *<cluster-name>*을 클러스터 이름으로 바꿉니다. 명령의 출력이 `None`인 경우 **사전 요구 사항**을 검토합니다.

   ```
   aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text
   ```

   예제 출력은 다음과 같습니다.

   ```
   https://oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE
   ```

1. IAM 역할을 생성하여 `AssumeRoleWithWebIdentity` 작업을 부여합니다.

   1. 다음 콘텐츠를 `aws-ebs-csi-driver-trust-policy.json`이라는 파일에 복사합니다. *111122223333*을 계정 ID로 바꿉니다. *EXAMPLED539D4633E53DE1B71EXAMPLE* 및 *region-code*를 이전 단계에서 반환된 값으로 바꿉니다.

      ```
      {
            "Version":"2012-10-17",		 	 	 
            "Statement": [
              {
                "Effect": "Allow",
                "Principal": {
                  "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
                },
                "Action": "sts:AssumeRoleWithWebIdentity",
                "Condition": {
                  "StringEquals": {
                    "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com",
                    "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa"
                  }
                }
              }
            ]
          }
      ```

   1. 역할을 생성합니다. *AmazonEKS \$1EBS\$1CSI\$1DriverRole*을 다른 이름으로 변경할 수 있습니다. 변경하는 경우 이후 단계에서 변경해야 합니다.

      ```
      aws iam create-role \
            --role-name AmazonEKS_EBS_CSI_DriverRole \
            --assume-role-policy-document file://"aws-ebs-csi-driver-trust-policy.json"
      ```

1. 정책을 연결합니다. AWS은(는) AWS 관리형 정책을 유지 관리하거나 자체 사용자 지정 정책을 생성할 수 있습니다. 다음 명령으로 AWS 관리형 정책을 역할에 연결합니다.

   ```
   aws iam attach-role-policy \
         --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
         --role-name AmazonEKS_EBS_CSI_DriverRole
   ```

1. Amazon EBS 볼륨의 암호화에 사용자 지정 [KMS 키](https://aws.amazon.com/kms/)를 사용하는 경우 필요에 따라 IAM 역할을 사용자 지정합니다. 예를 들어, 다음을 수행합니다.

   1. 다음 코드를 복사하여 새로운 `kms-key-for-encryption-on-ebs.json` 파일에 붙여 넣습니다. *custom-key-arn*을 사용자 지정 [KMS 키 ARN](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awskeymanagementservice.html#awskeymanagementservice-key)으로 바꿉니다.

      ```
      {
            "Version":"2012-10-17",		 	 	 
            "Statement": [
              {
                "Effect": "Allow",
                "Action": [
                  "kms:CreateGrant",
                  "kms:ListGrants",
                  "kms:RevokeGrant"
                ],
                "Resource": ["arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"],
                "Condition": {
                  "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                  }
                }
              },
              {
                "Effect": "Allow",
                "Action": [
                  "kms:Encrypt",
                  "kms:Decrypt",
                  "kms:ReEncrypt*",
                  "kms:GenerateDataKey*",
                  "kms:DescribeKey"
                ],
                "Resource": ["arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"]
              }
            ]
          }
      ```

   1. 정책을 생성합니다. *KMS\$1Key\$1For\$1Encryption\$1On\$1EBS\$1Policy*를 다른 이름으로 변경할 수 있습니다. 그러나 이렇게 하는 경우 이후 단계에서도 변경해야 합니다.

      ```
      aws iam create-policy \
            --policy-name KMS_Key_For_Encryption_On_EBS_Policy \
            --policy-document file://kms-key-for-encryption-on-ebs.json
      ```

   1. 다음 명령을 사용하여 IAM 정책을 역할에 연결합니다. *111122223333*을 계정 ID로 바꿉니다.

      ```
      aws iam attach-role-policy \
            --policy-arn arn:aws:iam::111122223333:policy/KMS_Key_For_Encryption_On_EBS_Policy \
            --role-name AmazonEKS_EBS_CSI_DriverRole
      ```

이제 Amazon EBS CSI 드라이버 IAM 역할을 생성했으므로 다음 섹션을 계속 진행할 수 있습니다. 이 IAM 역할을 사용하여 추가 기능을 배포하면 `ebs-csi-controller-sa`라는 서비스 계정을 생성하고 사용하도록 구성됩니다. 이 서비스 계정은 필요한 Kubernetes 권한이 할당된 Kubernetes `clusterrole`에 바인딩되어 있습니다.

## 2단계: Amazon EBS CSI 드라이버 받기
<a name="managing-ebs-csi"></a>

보안을 강화하고 작업량을 줄이려면 Amazon EKS 추가 기능을 통해 Amazon EBS CSI 드라이버를 설치하는 것이 좋습니다. Amazon EKS 추가 기능을 클러스터에 추가하려면 [Amazon EKS 추가 기능 생성](creating-an-add-on.md) 섹션을 참조하세요. Amazon EKS 추가 기능에 대한 자세한 내용은 [Amazon EKS 추가 기능](eks-add-ons.md) 섹션을 참조하세요.

**중요**  
Amazon EBS 드라이버를 Amazon EKS 추가 기능으로 추가하기 전에 클러스터에 자체 관리형 버전의 드라이버가 설치되어 있지 않은지 확인하세요. 설치되어 있다면 GitHub의 [Uninstalling a self-managed Amazon EBS CSI driver](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/master/docs/install.md#uninstalling-the-ebs-csi-driver)를 참조하세요.

**참고**  
기본적으로 EBS CSI에서 사용하는 RBAC 역할에는 테인트 제거 기능을 지원하기 위해 노드를 변경할 권한이 있습니다. Kubernetes RBAC의 제한 사항으로 인해 이때 클러스터의 다른 노드도 변경할 수 있습니다. 헬름 차트에는 ebs-csi-node 서비스 계정에 대한 노드 RBAC 권한 변경을 비활성화하는 파라미터(`node.serviceAccount.disableMutation`)가 있습니다. 이를 활성화하면 테인트 제거와 같은 드라이버 기능이 작동하지 않습니다.

대신 Amazon EBS CSI 드라이버의 자체 관리형 설치를 원하는 경우 GitHub의 [Installation](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/master/docs/install.md)을 참조하세요.

## 3단계: 샘플 애플리케이션 배포
<a name="ebs-sample-app"></a>

다양한 샘플 앱을 배포하고 필요에 따라 수정할 수 있습니다. 자세한 내용은 GitHub의 [Kubernetes Examples](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/tree/master/examples/kubernetes)를 참조하세요.

# Amazon EFS와 함께 탄력적 파일 시스템 스토리지 사용
<a name="efs-csi"></a>

 [Amazon Elastic File System](https://docs.aws.amazon.com/efs/latest/ug/whatisefs.html)(Amazon EFS)은 완전히 탄력적인 서버리스 파일 스토리지를 제공하므로 스토리지 용량과 성능을 프로비저닝하거나 관리하지 않고도 파일 데이터를 공유할 수 있습니다. [Amazon EBS 컨테이너 스토리지 인터페이스(CSI) 드라이버](https://github.com/kubernetes-sigs/aws-efs-csi-driver)는 AWS에서는 Kubernetes 클러스터가 Amazon EFS 파일 시스템의 수명 주기를 관리할 수 있게 해주는 CSI 인터페이스를 제공합니다. 이 주제에서는 Amazon EFS CSI 드라이버를 Amazon EKS 클러스터에 배포하는 방법을 설명합니다.

## 고려 사항
<a name="efs-csi-considerations"></a>
+ Amazon EFS CSI 드라이버는 Windows 기반 컨테이너 이미지와 호환되지 않습니다.
+ Fargate 노드에는 영구 볼륨에 대해 [동적 프로비저닝](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/examples/kubernetes/dynamic_provisioning/README.md)을 사용할 수 없지만 [정적 프로비저닝](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/examples/kubernetes/static_provisioning/README.md)은 사용할 수 있습니다.
+  [동적 프로비저닝](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/examples/kubernetes/dynamic_provisioning/README.md)은 [1.2](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/CHANGELOG-1.x.md#v12) 이상의 드라이버가 필요합니다. 모든 지원되는 Amazon EKS 클러스터 버전에서 드라이버 버전 `1.1`을 사용하여 영구 볼륨에 대해 [정적 프로비저닝](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/examples/kubernetes/static_provisioning/README.md)을 사용할 수 있습니다. ([Amazon EKS 지원 버전](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html) 참조)
+ 이 드라이버의 버전 [1.3.2](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/CHANGELOG-1.x.md#v132) 이상은 Amazon EC2 Graviton 기반 인스턴스를 포함하여 Arm64 아키텍처를 지원합니다.
+ 이 드라이버의 버전 [1.4.2](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/CHANGELOG-1.x.md#v142) 이상은 파일 시스템 탑재에 FIPS 사용을 지원합니다.
+ Amazon EFS의 리소스 할당량을 기록해 둡니다. 예를 들어, 각 Amazon EFS 파일 시스템에 대해 생성할 수 있는 액세스 포인트 할당량은 1,000개입니다. 자세한 내용은 [변경할 수 없는 Amazon EFS 리소스 할당량](https://docs.aws.amazon.com/efs/latest/ug/limits.html#limits-efs-resources-per-account-per-region)을 참조하세요.
+ 버전 [2.0.0](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/CHANGELOG-2.x.md#v200)부터 이 드라이버는 TLS 연결에 `stunnel`를 사용하던 것을 `efs-proxy`로 전환했습니다. `efs-proxy`를 사용하면 실행 중인 노드의 코어 수에 1을 더한 것과 같은 수의 스레드가 열립니다.
+ Amazon EFS CSI 드라이버는 Amazon EKS Hybrid Nodes와 호환되지 않습니다.

## 사전 조건
<a name="efs-csi-prereqs"></a>
+ Amazon EFS CSI 드라이버에는 AWS Identity and Access Management(IAM) 권한이 필요합니다.
  +  AWS는 EKS Pod Identity 사용을 제안합니다. 자세한 내용은 [EKS Pod Identity 설정 개요](pod-identities.md#pod-id-setup-overview) 섹션을 참조하세요.
  + 서비스 계정의 IAM 역할 및 클러스터의 IAM OpenID Connect(OIDC) 공급자 설정에 대한 자세한 내용은 [클러스터에 대한 IAM OIDC 공급자 생성](enable-iam-roles-for-service-accounts.md) 섹션을 참조하세요.
+ 장치에 설치 및 구성된 AWS 명령줄 인터페이스(AWS CLI)의 버전 `2.12.3` 이상 또는 버전 `1.27.160` 이상 또는 AWS CloudShell. 현재 버전을 확인하려면 `aws --version | cut -d / -f2 | cut -d ' ' -f1`을 사용합니다. `yum`, `apt-get` 또는 macOS용 Homebrew와 같은 패키지 관리자는 최신 버전의 AWS CLI 이전에 나온 버전이 몇 가지 있을 때도 있습니다. 최신 버전을 설치하려면 * AWS 명령줄 인터페이스 사용 설명서*에서 [설치](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) 및 [aws config를 사용하여 빠른 구성](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)을 참조하세요. AWS CloudShell에 설치된 AWS CLI 버전도 최신 버전보다 여러 버전 이전일 수도 있습니다. 업데이트하려면 * AWS CloudShell 사용 설명서*의 [홈 디렉터리에 AWS CLI 설치하기](https://docs.aws.amazon.com/cloudshell/latest/userguide/vm-specs.html#install-cli-software)를 참조하세요.
+ `kubectl` 명령줄 도구는 장치 또는 AWS CloudShell에 설치됩니다. 버전은 클러스터의 Kubernetes 버전과 동일하거나 최대 하나 이전 또는 이후의 마이너 버전일 수 있습니다. 예를 들어, 클러스터 버전이 `1.29`인 경우 `kubectl` 버전 `1.28`, `1.29` 또는 `1.30`를 함께 사용할 수 있습니다. `kubectl`을 설치하거나 업그레이드하려면 [`kubectl` 및 `eksctl` 설정](install-kubectl.md) 부분을 참조하세요.

**참고**  
Fargate에서 실행되는 포드는 수동 드라이버 설치 단계 없이 Amazon EFS 파일 시스템을 자동으로 탑재합니다.

## 1단계-IAM 역할 생성
<a name="efs-create-iam-resources"></a>

Amazon EFS CSI 드라이버가 파일 시스템과 상호 작용하려면 IAM 권한이 필요합니다. IAM 역할을 생성하고 필요한 AWS 관리형 정책을 연결합니다. 이 절차를 구현하려면 다음 도구 중 하나를 사용할 수 있습니다.
+  [`eksctl`](#eksctl_efs_store_app_data) 
+  [AWS Management Console](#console_efs_store_app_data) 
+  [AWS CLI](#awscli_efs_store_app_data) 

**참고**  
이 절차의 특정 단계는 드라이버를 Amazon EKS 추가 기능으로 사용하기 위해 작성되었습니다. 자체 관리형 설치에 대한 자세한 내용은 GitHub의 [Set up driver permission](https://github.com/kubernetes-sigs/aws-efs-csi-driver#set-up-driver-permission)을 참조하세요.

### `eksctl`
<a name="eksctl_efs_store_app_data"></a>

#### Pod Identity를 사용하는 경우
<a name="efs-eksctl-pod-identities"></a>

다음 명령을 실행하여 `eksctl`로 IAM 역할과 Pod Identity 연결을 생성할 수 있습니다. `my-cluster`을 클러스터 이름으로 교체합니다. 또한 `AmazonEKS_EFS_CSI_DriverRole`을 다른 이름으로 바꿀 수 있습니다.

```
export cluster_name=my-cluster
export role_name=AmazonEKS_EFS_CSI_DriverRole
eksctl create podidentityassociation \
    --service-account-name efs-csi-controller-sa \
    --namespace kube-system \
    --cluster $cluster_name \
    --role-name $role_name \
    --permission-policy-arns arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy
```

#### 서비스 계정에 IAM 역할을 사용하는 경우
<a name="efs-eksctl-irsa"></a>

다음 명령을 실행하여 `eksctl`로 IAM 역할을 만들 수 있습니다. `my-cluster`을 클러스터 이름으로 교체합니다. 또한 `AmazonEKS_EFS_CSI_DriverRole`을 다른 이름으로 바꿀 수 있습니다.

```
export cluster_name=my-cluster
export role_name=AmazonEKS_EFS_CSI_DriverRole
eksctl create iamserviceaccount \
    --name efs-csi-controller-sa \
    --namespace kube-system \
    --cluster $cluster_name \
    --role-name $role_name \
    --role-only \
    --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
    --approve
TRUST_POLICY=$(aws iam get-role --output json --role-name $role_name --query 'Role.AssumeRolePolicyDocument' | \
    sed -e 's/efs-csi-controller-sa/efs-csi-*/' -e 's/StringEquals/StringLike/')
aws iam update-assume-role-policy --role-name $role_name --policy-document "$TRUST_POLICY"
```

### AWS Management Console
<a name="console_efs_store_app_data"></a>

다음을 실행하여 AWS Management Console를 사용하여 IAM 역할을 만듭니다.

1. IAM 콘솔(https://console.aws.amazon.com/iam/)을 엽니다.

1. 왼쪽 탐색 창에서 **역할**을 선택합니다.

1. **역할** 페이지에서 **역할 생성**을 선택합니다.

1. **신뢰할 수 있는 엔터티 선택** 페이지에서 다음을 수행합니다.

   1. EKS Pod Identity를 사용하는 경우

      1. **신뢰할 수 있는 엔터티 유형** 섹션에서 **AWS 서비스**를 선택합니다.

      1. **서비스 또는 사용 사례** 드롭다운에서 **EKS**를 선택합니다.

      1. **사용 사례** 섹션에서 **EKS - Pod Identity**를 선택합니다.

      1. **다음**을 선택합니다.

   1. 서비스 계정에 IAM 역할을 사용하는 경우

      1. **신뢰할 수 있는 엔터티 유형** 섹션에서 **웹 자격 증명**을 선택합니다.

      1. **아이덴티티 제공업체(Identity provider)**의 경우 클러스터에 대해 **OpenID Connect 공급자 URL(OpenID Connect provider URL)**을 선택합니다(Amazon EKS의 **개요**에 표시된 대로).

      1. **대상**에서 `sts.amazonaws.com`을 입력합니다.

      1. **다음**을 선택합니다.

1. **권한 추가** 페이지에서 다음을 수행합니다.

   1. **필터 정책** 상자에 `AmazonEFSCSIDriverPolicy`를 입력합니다.

   1. 검색에서 반환된 `AmazonEFSCSIDriverPolicy` 왼쪽에 있는 확인란을 선택합니다.

   1. **다음**을 선택합니다.

1. **이름, 검토 및 생성** 페이지에서 다음을 수행합니다.

   1. **역할 이름**에 역할의 고유한 이름(예: `AmazonEKS_EFS_CSI_DriverRole`)을 입력합니다.

   1. **태그 추가(선택사항)**에서 태그를 키-값 페어로 연결하여 메타데이터를 역할에 추가합니다. IAM에서 태그 사용에 대한 자세한 내용을 알아보려면 IAM 사용 설명서의 [IAM 리소스에 태깅](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html)을 참조하세요.

   1. **역할 생성**을 선택합니다.

1. 역할이 생성된 후

   1. EKS Pod Identity를 사용하는 경우

      1. [Amazon EKS 콘솔](https://console.aws.amazon.com/eks/home#/clusters)을 엽니다.

      1. 왼쪽 탐색 창에서 **클러스터**를 선택한 다음 EKS Pod Identity 연결을 구성할 클러스터의 이름을 선택합니다.

      1. **액세스** 탭을 선택합니다.

      1. **Pod Identity 연결**에서 **생성**을 선택합니다.

      1. **IAM 역할** 드롭다운을 선택하고 새로 생성된 역할을 선택합니다.

      1. **Kubernetes 네임스페이스** 필드를 선택하고 `kube-system`을 입력합니다.

      1. **Kubernetes 서비스 계정** 필드를 선택하고 `efs-csi-controller-sa`를 입력합니다.

      1. **생성(Create)**을 선택합니다.

      1. Pod Identity 연결 생성에 대한 자세한 내용은 [pod identity 연결 생성(AWS 콘솔)](pod-id-association.md#pod-id-association-create) 섹션을 참조하세요.

   1. 서비스 계정에 IAM 역할을 사용하는 경우

      1. 역할을 선택하여 편집을 위해 엽니다.

      1. **신뢰 관계** 탭을 선택한 후 **신뢰 정책 편집**을 선택합니다.

      1. 다음과 비슷한 줄을 찾습니다.

         ```
         "oidc.eks.region-code.amazonaws.com/id/<EXAMPLED539D4633E53DE1B71EXAMPLE>:aud": "sts.amazonaws.com"
         ```

         이전 줄 위에 다음 줄을 추가합니다. `<region-code>`를 클러스터가 있는 AWS 리전으로 바꿉니다. `<EXAMPLED539D4633E53DE1B71EXAMPLE>`을 클러스터의 OIDC 공급자 ID로 바꿉니다.

         ```
         "oidc.eks.<region-code>.amazonaws.com/id/<EXAMPLED539D4633E53DE1B71EXAMPLE>:sub": "system:serviceaccount:kube-system:efs-csi-*",
         ```

      1. `Condition` 운영자를 `"StringEquals"`에서 `"StringLike"`(으)로 수정합니다.

      1. **신뢰 정책 업데이트**를 선택하여 종료합니다.

### AWS CLI
<a name="awscli_efs_store_app_data"></a>

다음 명령을 실행하여 AWS CLI로 IAM 역할을 만들 수 있습니다.

#### Pod Identity를 사용하는 경우
<a name="efs-cli-pod-identities"></a>

1. `pods.eks.amazonaws.com` 서비스에 `AssumeRole` 및 `TagSession` 작업을 부여하는 IAM 역할을 생성합니다.

   1. 다음 콘텐츠를 `aws-efs-csi-driver-trust-policy-pod-identity.json`라는 파일에 복사합니다.

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Sid": "AllowEksAuthToAssumeRoleForPodIdentity",
                  "Effect": "Allow",
                  "Principal": {
                      "Service": "pods.eks.amazonaws.com"
                  },
                  "Action": [
                      "sts:AssumeRole",
                      "sts:TagSession"
                  ]
              }
          ]
      }
      ```

   1. 역할을 생성합니다. `my-cluster`을 클러스터 이름으로 교체합니다. 또한 `AmazonEKS_EFS_CSI_DriverRole`을 다른 이름으로 바꿀 수 있습니다.

      ```
      export cluster_name=my-cluster
      export role_name=AmazonEKS_EFS_CSI_DriverRole
      aws iam create-role \
        --role-name $role_name \
        --assume-role-policy-document file://"aws-efs-csi-driver-trust-policy-pod-identity.json"
      ```

1. 다음 명령어로 필요한 AWS 관리형 정책을 역할에 연결합니다.

   ```
   aws iam attach-role-policy \
     --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
     --role-name $role_name
   ```

1. 다음 명령을 실행하여 Pod Identity 연결을 생성합니다. ` arn:aws:iam::<111122223333>:role/my-role`을 이전 단계에서 생성한 역할로 바꿉니다.

   ```
   aws eks create-pod-identity-association --cluster-name $cluster_name --role-arn {arn-aws}iam::<111122223333>:role/my-role --namespace kube-system --service-account efs-csi-controller-sa
   ```

1. Pod Identity 연결 생성에 대한 자세한 내용은 [pod identity 연결 생성(AWS 콘솔)](pod-id-association.md#pod-id-association-create) 섹션을 참조하세요.

#### 서비스 계정에 IAM 역할을 사용하는 경우
<a name="efs-cli-irsa"></a>

1. 클러스터의 OIDC 공급자 URL을 확인합니다. `my-cluster`을 클러스터 이름으로 교체합니다. 또한 `AmazonEKS_EFS_CSI_DriverRole`을 다른 이름으로 바꿀 수 있습니다.

   ```
   export cluster_name=my-cluster
   export role_name=AmazonEKS_EFS_CSI_DriverRole
   aws eks describe-cluster --name $cluster_name --query "cluster.identity.oidc.issuer" --output text
   ```

   예제 출력은 다음과 같습니다.

   ```
   https://oidc.eks.<region-code>.amazonaws.com/id/<EXAMPLED539D4633E53DE1B71EXAMPLE>
   ```

   명령의 출력이 `None`인 경우 **사전 요구 사항**을 검토합니다.

1. `AssumeRoleWithWebIdentity` 작업을 부여하는 IAM 역할을 생성합니다.

   1. 다음 콘텐츠를 `aws-efs-csi-driver-trust-policy.json`라는 파일에 복사합니다. `<111122223333>`을 계정 ID로 바꿉니다. `<EXAMPLED539D4633E53DE1B71EXAMPLE>` 및 `<region-code>`를 이전 단계에서 반환된 값으로 바꿉니다.

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
              "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
              "StringLike": {
                "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:kube-system:efs-csi-*",
                "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
              }
            }
          }
        ]
      }
      ```

   1. 역할을 생성합니다.

      ```
      aws iam create-role \
        --role-name $role_name \
        --assume-role-policy-document file://"aws-efs-csi-driver-trust-policy.json"
      ```

1. 다음 명령어로 필요한 AWS 관리형 정책을 역할에 연결합니다.

   ```
   aws iam attach-role-policy \
     --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
     --role-name $role_name
   ```

## 2단계: Amazon EFS CSI 드라이버 받기
<a name="efs-install-driver"></a>

Amazon EKS 추가 기능을 통해 Amazon EFS CSI 드라이버를 설치하는 것이 좋습니다. Amazon EKS 추가 기능을 클러스터에 추가하려면 [Amazon EKS 추가 기능 생성](creating-an-add-on.md) 섹션을 참조하세요. Amazon EKS 추가 기능에 대한 자세한 내용은 [Amazon EKS 추가 기능](eks-add-ons.md) 섹션을 참조하세요. Amazon EKS 추가 기능을 사용할 수 없는 경우, 사용할 수 없는 이유에 대한 문제를 [컨테이너 로드맵 GitHub 리포지토리에](https://github.com/aws/containers-roadmap/issues) 제출하는 것이 좋습니다.

**중요**  
Amazon EFS 드라이버를 Amazon EKS 추가 기능으로 추가하기 전에 클러스터에 자체 관리형 버전의 드라이버가 설치되어 있지 않은지 확인하세요. 그러한 경우 GitHub에서 [Amazon EFS CSI 드라이버 제거](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/docs/README.md#uninstalling-the-amazon-efs-csi-driver)를 참조하세요.

대신 Amazon EFS CSI 드라이버의 자체 관리형 설치를 원하는 경우 GitHub의 [Installation](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/docs/README.md#installation)을 참조하세요.

## 3단계: Amazon EFS 파일 시스템 생성
<a name="efs-create-filesystem"></a>

Amazon EFS 파일 시스템을 생성하려면 GitHub의 [Create an Amazon EFS file system for Amazon EKS](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/docs/efs-create-filesystem.md)를 참조하세요.

## 4단계: 샘플 애플리케이션 배포
<a name="efs-sample-app"></a>

다양한 샘플 앱을 배포하고 필요에 따라 수정할 수 있습니다. 자세한 내용은 GitHub의 [Examples](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/docs/README.md#examples)를 참조하세요.

# Amazon FSx for Lustre와 함께 고성능 앱 스토리지 사용
<a name="fsx-csi"></a>

[Amazon FSx for Lustre 컨테이너 스토리지(CSI) 드라이버](https://github.com/kubernetes-sigs/aws-fsx-csi-driver)에서는 Amazon EKS 클러스터가 Amazon FSx for Lustre 파일 시스템의 수명 주기를 관리할 수 있게 해주는 CSI 인터페이스를 제공합니다. 자세한 내용을 알아보려면 [Amazon FSx for Lustre 사용 설명서](https://docs.aws.amazon.com/fsx/latest/LustreGuide/what-is.html)를 참조하세요.

Amazon FSx for Lustre CSI 드라이버를 Amazon EKS 클러스터에 배포하고 제대로 작동하는지 확인하는 방법에 대한 자세한 내용은 [FSx for Lustre CSI 드라이버 배포](fsx-csi-create.md) 섹션을 참조하세요.

# FSx for Lustre CSI 드라이버 배포
<a name="fsx-csi-create"></a>

이 주제에서는 [FSx for Lustre CSI 드라이버](fsx-csi.md)를 Amazon EKS 클러스터에 배포하고 제대로 작동하는지 확인하는 방법에 관해 설명합니다. 드라이버는 최신 버전을 사용하는 것이 좋습니다. 사용 가능한 버전은 GitHub의 [CSI Specification Compatibility Matrix](https://github.com/kubernetes-sigs/aws-fsx-csi-driver/blob/master/docs/README.md#csi-specification-compatibility-matrix)를 참조하세요.

**참고**  
드라이버는 Fargate 또는 Amazon EKS Hybrid Nodes에서 지원되지 않습니다.

사용할 수 있는 파라미터에 대한 자세한 설명과 드라이버의 기능을 보여주는 전체 예제는 GitHub의 [FSx for Lustre Container Storage Interface (CSI) driver](https://github.com/kubernetes-sigs/aws-fsx-csi-driver) 프로젝트를 참조하세요.

## 사전 조건
<a name="fsx-csi-prereqs"></a>
+ 기존 클러스터가 있어야 합니다.
+ Amazon FSx CSI 드라이버 EKS 추가 기능을 사용하려면 인증을 위해 EKS Pod Identity 에이전트가 필요합니다. 이 구성 요소가 없으면 `Amazon EKS Pod Identity agent is not installed in the cluster` 오류와 함께 추가 기능이 실패하여 볼륨 작업을 수행하지 못합니다. FSx CSI 드라이버 추가 기능을 배포하기 전 또는 후에 Pod Identity 에이전트를 설치합니다. 자세한 내용은 [Amazon EKS Pod Identity 에이전트 설정](pod-id-agent-setup.md) 섹션을 참조하세요.
+ 장치에 설치 및 구성된 AWS 명령줄 인터페이스(AWS CLI)의 버전 `2.12.3` 이상 또는 버전 `1.27.160` 이상 또는 AWS CloudShell. 현재 버전을 확인하려면 `aws --version | cut -d / -f2 | cut -d ' ' -f1`을 사용합니다. `yum`, `apt-get` 또는 macOS용 Homebrew와 같은 패키지 관리자는 최신 버전의 AWS CLI 이전에 나온 버전이 몇 가지 있을 때도 있습니다. 최신 버전을 설치하려면 * AWS 명령줄 인터페이스 사용 설명서*에서 [설치](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) 및 [aws config를 사용하여 빠른 구성](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)을 참조하세요. AWS CloudShell에 설치된 AWS CLI 버전도 최신 버전보다 여러 버전 이전일 수도 있습니다. 업데이트하려면 * AWS CloudShell 사용 설명서*의 [홈 디렉터리에 AWS CLI 설치하기](https://docs.aws.amazon.com/cloudshell/latest/userguide/vm-specs.html#install-cli-software)를 참조하세요.
+ 장치에 설치된 `eksctl` 명령줄 도구의 버전 `0.215.0` 이상 또는 AWS CloudShell이 필요합니다. `eksctl`을 설치 또는 업그레이드하려면 `eksctl` 설명서에서 [설치](https://eksctl.io/installation)를 참조하세요.
+ `kubectl` 명령줄 도구는 장치 또는 AWS CloudShell에 설치됩니다. 버전은 클러스터의 Kubernetes 버전과 동일하거나 최대 하나 이전 또는 이후의 마이너 버전일 수 있습니다. 예를 들어, 클러스터 버전이 `1.29`인 경우 `kubectl` 버전 `1.28`, `1.29` 또는 `1.30`를 함께 사용할 수 있습니다. `kubectl`을 설치하거나 업그레이드하려면 [`kubectl` 및 `eksctl` 설정](install-kubectl.md) 부분을 참조하세요.

## 1단계-IAM 역할 생성
<a name="fsx-create-iam-role"></a>

Amazon FSx CSI 플러그인이 사용자를 대신하여 AWS API를 직접적으로 호출하려면 IAM 권한이 필요합니다.

**참고**  
IMDS에 대한 액세스 권한을 차단하지 않는 한 포드는 IAM 역할에 할당된 권한에 대한 액세스 권한이 있습니다. 자세한 내용은 [모범 사례로 Amazon EKS 클러스터 보호](security-best-practices.md) 섹션을 참조하세요.

다음 절차에서는 IAM 역할을 생성하고 AWS 관리형 정책을 연결하는 방법을 보여줍니다.

1. 다음 명령을 사용하여 IAM 역할을 생성하고 AWS 관리형 정책을 연결합니다. `my-cluster`를 사용하려는 클러스터의 이름으로 바꿉니다. 이 명령은 IAM 역할을 생성하고 IAM 정책을 연결하는 AWS CloudFormation 스택을 배포합니다.

   ```
   eksctl create iamserviceaccount \
       --name fsx-csi-controller-sa \
       --namespace kube-system \
       --cluster my-cluster \
       --role-name AmazonEKS_FSx_CSI_DriverRole \
       --role-only \
       --attach-policy-arn arn:aws:iam::aws:policy/AmazonFSxFullAccess \
       --approve
   ```

   서비스 계정이 생성되면 여러 줄의 출력이 표시됩니다. 출력의 마지막 줄은 다음과 유사합니다.

   ```
   [ℹ]  1 task: {
       2 sequential sub-tasks: {
           create IAM role for serviceaccount "kube-system/fsx-csi-controller-sa",
           create serviceaccount "kube-system/fsx-csi-controller-sa",
       } }
   [ℹ]  building iamserviceaccount stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-fsx-csi-controller-sa"
   [ℹ]  deploying stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-fsx-csi-controller-sa"
   [ℹ]  waiting for CloudFormation stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-fsx-csi-controller-sa"
   [ℹ]  created serviceaccount "kube-system/fsx-csi-controller-sa"
   ```

   배포된 AWS CloudFormation 스택의 이름을 기록합니다. 이전 예제 출력에서 스택의 이름이 `eksctl-my-cluster-addon-iamserviceaccount-kube-system-fsx-csi-controller-sa`로 지정되어 있습니다.

이제 Amazon FSx CSI 드라이버 IAM 역할을 생성했으므로 다음 섹션을 계속 진행할 수 있습니다. 이 IAM 역할을 사용하여 추가 기능을 배포하면 `fsx-csi-controller-sa`라는 서비스 계정을 생성하고 사용하도록 구성됩니다. 이 서비스 계정은 필요한 Kubernetes 권한이 할당된 Kubernetes `clusterrole`에 바인딩되어 있습니다.

## 2단계: Amazon FSx CSI 드라이버 설치
<a name="fsx-csi-deploy-driver"></a>

보안을 강화하고 작업량을 줄이려면 Amazon FSx 추가 기능을 통해 Amazon EBS CSI 드라이버를 설치하는 것이 좋습니다. Amazon EKS 추가 기능을 클러스터에 추가하려면 [Amazon EKS 추가 기능 생성](creating-an-add-on.md) 섹션을 참조하세요. Amazon EKS 추가 기능에 대한 자세한 내용은 [Amazon EKS 추가 기능](eks-add-ons.md) 섹션을 참조하세요.

**중요**  
클러스터에 기존 Amazon FSx CSI 드라이버를 설치하면 추가 기능 설치에 실패할 수 있습니다. 비 EKS FSx CSI 드라이버가 있는 동안 Amazon EKS 추가 기능 버전을 설치하려고 하면 리소스 충돌로 인해 설치가 실패합니다 설치 중 `OVERWRITE` 플래그를 사용하여 이 문제를 해결합니다.  

```
aws eks create-addon --addon-name aws-fsx-csi-driver --cluster-name my-cluster --resolve-conflicts OVERWRITE
```

대신 Amazon FSx CSI 드라이버의 자체 관리형 설치를 원하는 경우 GitHub의 [Installation](https://github.com/kubernetes-sigs/aws-fsx-csi-driver/blob/master/docs/install.md)을 참조하세요.

## 3단계: 스토리지 클래스, 영구 볼륨 클레임 및 샘플 앱 배포
<a name="fsx-csi-deploy-storage-class"></a>

이 절차에서는 [FSx for Lustre Container Storage Interface(CSI) 드라이버](https://github.com/kubernetes-sigs/aws-fsx-csi-driver) GitHub 리포지토리를 사용하여 동적으로 프로비저닝된 FSx for Lustre 볼륨을 사용합니다.

1. 클러스터의 보안 그룹을 기록합니다. 이는 **네트워킹** 섹션 아래의 AWS Management Console에서 또는 다음을 AWS CLI 명령을 사용하여 볼 수 있습니다. `my-cluster`를 사용하려는 클러스터의 이름으로 바꿉니다.

   ```
   aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.clusterSecurityGroupId
   ```

1. Amazon FSx for Lustre 사용 설명서의 [Amazon VPC 보안 그룹](https://docs.aws.amazon.com/fsx/latest/LustreGuide/limit-access-security-groups.html#fsx-vpc-security-groups)에 표시된 기준에 따라 Amazon FSx 파일 시스템에 대한 보안 그룹을 생성합니다. **VPC**의 경우 **네트워킹** 섹션 아래 표시된 대로 클러스터의 VPC를 선택합니다. “Lustre 클라이언트와 연결된 보안 그룹”의 경우 클러스터 보안 그룹을 사용합니다. 아웃바운드 규칙을 그대로 두어 **모든 트래픽**을 허용할 수 있습니다.

1. 다음 명령을 사용하여 스토리지 클래스 매니페스트를 다운로드합니다.

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

1. `storageclass.yaml` 파일의 파라미터 섹션을 편집합니다. 모든 예제 값을 자신의 값으로 바꾸세요.

   ```
   parameters:
     subnetId: subnet-0eabfaa81fb22bcaf
     securityGroupIds: sg-068000ccf82dfba88
     deploymentType: PERSISTENT_1
     automaticBackupRetentionDays: "1"
     dailyAutomaticBackupStartTime: "00:00"
     copyTagsToBackups: "true"
     perUnitStorageThroughput: "200"
     dataCompressionType: "NONE"
     weeklyMaintenanceStartTime: "7:09:00"
     fileSystemTypeVersion: "2.12"
   ```
   +  **`subnetId`** -Amazon FSx for Lustre 파일 시스템을 생성해야 하는 서브넷 ID. Amazon FSx for Lustre는 일부 가용 영역에서 지원되지 않습니다. https://console.aws.amazon.com/fsx/에서 Amazon FSx for Lustre 콘솔을 열어 사용하려는 서브넷이 지원되는 가용 영역에 있는지 확인합니다. 서브넷은 노드를 포함할 수도 있고 다른 서브넷이나 VPC일 수도 있습니다.
     + **컴퓨팅** 섹션에서 노드 그룹을 선택하여 AWS Management Console에서 노드 서브넷을 확인할 수 있습니다.
     + 지정한 서브넷이 노드가 있는 서브넷과 다른 경우 VPC가 [연결](https://docs.aws.amazon.com/whitepapers/latest/aws-vpc-connectivity-options/amazon-vpc-to-amazon-vpc-connectivity-options.html)되어 있어야 하며 보안 그룹에 필요한 포트가 열려 있는지 확인해야 합니다.
   +  **`securityGroupIds`** -파일 시스템에 대해 생성한 보안 그룹의 ID.
   +  ** `deploymentType` (선택사항)** - 파일 시스템 배포 유형입니다. 유효한 값은 `SCRATCH_1`, `SCRATCH_2`, `PERSISTENT_1` 및 `PERSISTENT_2`입니다. 배포 유형에 대한 자세한 내용은 [Amazon FSx for Lustre 파일 시스템 생성](https://docs.aws.amazon.com/fsx/latest/LustreGuide/getting-started-step1.html)을 참조하세요.
   +  **기타 파라미터(선택 사항)** - 기타 파라미터에 대한 자세한 내용을 알아보려면 GitHub의 [스토리지 클래스 편집](https://github.com/kubernetes-sigs/aws-fsx-csi-driver/tree/master/examples/kubernetes/dynamic_provisioning#edit-storageclass)을 참조하세요.

1. 스토리지 클래스 매니페스트를 생성합니다.

   ```
   kubectl apply -f storageclass.yaml
   ```

   예제 출력은 다음과 같습니다.

   ```
   storageclass.storage.k8s.io/fsx-sc created
   ```

1. 영구 볼륨 클레임 매니페스트를 다운로드합니다.

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

1. (선택사항) `claim.yaml` 파일을 편집합니다. 스토리지 요구 사항과 이전 단계에서 선택한 `deploymentType`에 따라 `1200Gi`를 다음 증분 값 중 하나로 변경합니다.

   ```
   storage: 1200Gi
   ```
   +  `SCRATCH_2` 및 `PERSISTENT` - `1.2 TiB`, `2.4 TiB` 또는 2.4TiB 대비 2.4TiB씩 증가합니다.
   +  `SCRATCH_1` – `1.2 TiB`, `2.4 TiB`, `3.6 TiB` 또는 3.6TiB 대비 3.6TiB의 증분.

1. 영구 볼륨 클레임을 생성합니다.

   ```
   kubectl apply -f claim.yaml
   ```

   예제 출력은 다음과 같습니다.

   ```
   persistentvolumeclaim/fsx-claim created
   ```

1. 파일 시스템이 프로비저닝되었는지 확인합니다.

   ```
   kubectl describe pvc
   ```

   예제 출력은 다음과 같습니다.

   ```
   Name:          fsx-claim
   Namespace:     default
   StorageClass:  fsx-sc
   Status:        Bound
   [...]
   ```
**참고**  
`Status`는 `Bound`로 변경되기 전에 5\$110분 동안 `Pending`으로 표시될 수 있습니다. `Status`가 `Bound`가 될 때까지 다음 단계를 계속하지 마세요. `Status`에 10분 이상 동안 `Pending`이 표시되는 경우 모든 문제를 해결하기 위한 참조로 `Events`의 경고 메시지를 사용합니다.

1. 샘플 애플리케이션을 배포합니다.

   ```
   kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-fsx-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml
   ```

1. 샘플 애플리케이션이 실행 중인지 확인합니다.

   ```
   kubectl get pods
   ```

   예제 출력은 다음과 같습니다.

   ```
   NAME      READY   STATUS              RESTARTS   AGE
   fsx-app   1/1     Running             0          8s
   ```

1. 파일 시스템이 애플리케이션에 의해 올바르게 탑재되었는지 확인합니다.

   ```
   kubectl exec -ti fsx-app -- df -h
   ```

   예제 출력은 다음과 같습니다.

   ```
   Filesystem                   Size  Used Avail Use% Mounted on
   overlay                       80G  4.0G   77G   5% /
   tmpfs                         64M     0   64M   0% /dev
   tmpfs                        3.8G     0  3.8G   0% /sys/fs/cgroup
   192.0.2.0@tcp:/abcdef01      1.1T  7.8M  1.1T   1% /data
   /dev/nvme0n1p1                80G  4.0G   77G   5% /etc/hosts
   shm                           64M     0   64M   0% /dev/shm
   tmpfs                        6.9G   12K  6.9G   1% /run/secrets/kubernetes.io/serviceaccount
   tmpfs                        3.8G     0  3.8G   0% /proc/acpi
   tmpfs                        3.8G     0  3.8G   0% /sys/firmware
   ```

1. 샘플 앱에서 데이터가 FSx for Lustre 파일 시스템에 작성되었는지 확인합니다.

   ```
   kubectl exec -it fsx-app -- ls /data
   ```

   예제 출력은 다음과 같습니다.

   ```
   out.txt
   ```

   이 출력 예는 샘플 앱이 파일 시스템에 `out.txt` 파일을 성공적으로 기록했다는 것을 보여줍니다.

**참고**  
클러스터를 삭제하기 전에 FSx for Lustre 파일 시스템을 삭제해야 합니다. 자세한 내용은 *FSx for Lustre 사용 설명서*의 [리소스 정리](https://docs.aws.amazon.com/fsx/latest/LustreGuide/getting-started-step4.html)를 참조하세요.

## FSx for Lustre의 성능 튜닝
<a name="_performance_tuning_for_fsx_for_lustre"></a>

Amazon EKS와 함께 FSx for Lustre를 사용하는 경우 노드 초기화 중 Lustre 튜닝을 적용하여 성능을 최적화할 수 있습니다. 권장 접근 방식은 시작 템플릿 사용자 데이터를 사용하여 모든 노드에서 일관된 구성을 보장하는 것입니다.

이러한 튜닝에는 다음이 포함됩니다.
+ 네트워크 및 RPC 최적화
+ Lustre 모듈 관리
+ LRU(리소스 잠금 단위) 튜닝
+ 클라이언트 캐시 제어 설정
+ OST 및 MDC에 대한 RPC 제어

이러한 성능 튜닝을 실행하는 방법에 대한 자세한 지침은 다음과 같습니다.
+ 표준 노드(비 EFA)의 성능을 최적화하려면 [노드에서 Amazon FSx for Lustre 성능 최적화(비 EFA)](fsx-csi-tuning-non-efa.md)에서 시작 템플릿 사용자 데이터에 추가할 수 있는 전체 스크립트를 참조하세요.
+ EFA 지원 노드의 성능 최적화는 [노드에서 Amazon FSx for Lustre 성능 최적화(EFA)](fsx-csi-tuning-efa.md) 섹션을 참조하세요.

# 노드에서 Amazon FSx for Lustre 성능 최적화(EFA)
<a name="fsx-csi-tuning-efa"></a>

이 주제에서는 Amazon EKS 및 Amazon FSx for Lustre를 사용하여 Elastic Fabric Adapter(EFA) 튜닝을 설정하는 방법을 설명합니다.

**참고**  
FSx for Lustre CSI 드라이버 생성 및 배포에 대한 자세한 내용은 [FSx for Lustre CSI 드라이버 배포](fsx-csi-create.md) 섹션을 참조하세요.
EFA 없이 표준 노드를 최적화하려면 [노드에서 Amazon FSx for Lustre 성능 최적화(비 EFA)](fsx-csi-tuning-non-efa.md) 섹션을 참조하세요.

## 1단계. EKS 클러스터 생성
<a name="create-eks-cluster"></a>

제공된 구성 파일을 사용하여 클러스터를 생성합니다.

```
# Create cluster using efa-cluster.yaml
eksctl create cluster -f efa-cluster.yaml
```

예제 :`efa-cluster.yaml`

```
#efa-cluster.yaml

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: csi-fsx
  region: us-east-1
  version: "1.30"

iam:
  withOIDC: true

availabilityZones: ["us-east-1a", "us-east-1d"]

managedNodeGroups:
  - name: my-efa-ng
    instanceType: c6gn.16xlarge
    minSize: 1
    desiredCapacity: 1
    maxSize: 1
    availabilityZones: ["us-east-1b"]
    volumeSize: 300
    privateNetworking: true
    amiFamily: Ubuntu2204
    efaEnabled: true
    preBootstrapCommands:
      - |
        #!/bin/bash
        eth_intf="$(/sbin/ip -br -4 a sh | grep $(hostname -i)/ | awk '{print $1}')"
        efa_version=$(modinfo efa | awk '/^version:/ {print $2}' | sed 's/[^0-9.]//g')
        min_efa_version="2.12.1"

        if [[ "$(printf '%s\n' "$min_efa_version" "$efa_version" | sort -V | head -n1)" != "$min_efa_version" ]]; then
            sudo curl -O https://efa-installer.amazonaws.com/aws-efa-installer-1.37.0.tar.gz
            tar -xf aws-efa-installer-1.37.0.tar.gz && cd aws-efa-installer
            echo "Installing EFA driver"
            sudo apt-get update && apt-get upgrade -y
            sudo apt install -y pciutils environment-modules libnl-3-dev libnl-route-3-200 libnl-route-3-dev dkms
            sudo ./efa_installer.sh -y
            modinfo efa
        else
            echo "Using EFA driver version $efa_version"
        fi

        echo "Installing Lustre client"
        sudo wget -O - https://fsx-lustre-client-repo-public-keys.s3.amazonaws.com/fsx-ubuntu-public-key.asc | gpg --dearmor | sudo tee /usr/share/keyrings/fsx-ubuntu-public-key.gpg > /dev/null
        sudo echo "deb [signed-by=/usr/share/keyrings/fsx-ubuntu-public-key.gpg] https://fsx-lustre-client-repo.s3.amazonaws.com/ubuntu jammy main" > /etc/apt/sources.list.d/fsxlustreclientrepo.list
        sudo apt update | tail
        sudo apt install -y lustre-client-modules-$(uname -r) amazon-ec2-utils | tail
        modinfo lustre

        echo "Loading Lustre/EFA modules..."
        sudo /sbin/modprobe lnet
        sudo /sbin/modprobe kefalnd ipif_name="$eth_intf"
        sudo /sbin/modprobe ksocklnd
        sudo lnetctl lnet configure

        echo "Configuring TCP interface..."
        sudo lnetctl net del --net tcp 2> /dev/null
        sudo lnetctl net add --net tcp --if $eth_intf

        # For P5 instance type which supports 32 network cards,
        # by default add 8 EFA interfaces selecting every 4th device (1 per PCI bus)
        echo "Configuring EFA interface(s)..."
        instance_type="$(ec2-metadata --instance-type | awk '{ print $2 }')"
        num_efa_devices="$(ls -1 /sys/class/infiniband | wc -l)"
        echo "Found $num_efa_devices available EFA device(s)"

        if [[ "$instance_type" == "p5.48xlarge" || "$instance_type" == "p5e.48xlarge" ]]; then
           for intf in $(ls -1 /sys/class/infiniband | awk 'NR % 4 == 1'); do
               sudo lnetctl net add --net efa --if $intf --peer-credits 32
          done
        else
        # Other instances: Configure 2 EFA interfaces by default if the instance supports multiple network cards,
        # or 1 interface for single network card instances
        # Can be modified to add more interfaces if instance type supports it
            sudo lnetctl net add --net efa --if $(ls -1 /sys/class/infiniband | head -n1) --peer-credits 32
            if [[ $num_efa_devices -gt 1 ]]; then
               sudo lnetctl net add --net efa --if $(ls -1 /sys/class/infiniband | tail -n1) --peer-credits 32
            fi
        fi

        echo "Setting discovery and UDSP rule"
        sudo lnetctl set discovery 1
        sudo lnetctl udsp add --src efa --priority 0
        sudo /sbin/modprobe lustre

        sudo lnetctl net show
        echo "Added $(sudo lnetctl net show | grep -c '@efa') EFA interface(s)"
```

## 2단계. 노드 그룹 생성
<a name="create-node-group"></a>

EFA 지원 노드 그룹을 생성합니다.

```
# Create node group using efa-ng.yaml
eksctl create nodegroup -f efa-ng.yaml
```

**중요**  
=== `# 5. Mount FSx filesystem` 섹션에서 환경에 맞게 이러한 값을 조정합니다.

```
FSX_DNS="<your-fsx-filesystem-dns>" # Needs to be adjusted.
MOUNT_NAME="<your-mount-name>" # Needs to be adjusted.
MOUNT_POINT="</your/mount/point>" # Needs to be adjusted.
```

===

예제 :`efa-ng.yaml`

```
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: final-efa
  region: us-east-1

managedNodeGroups:
  - name: ng-1
    instanceType: c6gn.16xlarge
    minSize: 1
    desiredCapacity: 1
    maxSize: 1
    availabilityZones: ["us-east-1a"]
    volumeSize: 300
    privateNetworking: true
    amiFamily: Ubuntu2204
    efaEnabled: true
    preBootstrapCommands:
      - |
        #!/bin/bash
        exec 1> >(logger -s -t $(basename $0)) 2>&1

        #########################################################################################
        #                                    Configuration Section                              #
        #########################################################################################

        # File System Configuration
        FSX_DNS="<your-fsx-filesystem-dns>" # Needs to be adjusted.
        MOUNT_NAME="<your-mount-name>" # Needs to be adjusted.
        MOUNT_POINT="</your/mount/point>" # Needs to be adjusted.

        # Lustre Tuning Parameters
        LUSTRE_LRU_MAX_AGE=600000
        LUSTRE_MAX_CACHED_MB=64
        LUSTRE_OST_MAX_RPC=32
        LUSTRE_MDC_MAX_RPC=64
        LUSTRE_MDC_MOD_RPC=50

        # File paths
        FUNCTIONS_SCRIPT="/usr/local/bin/lustre_functions.sh"
        TUNINGS_SCRIPT="/usr/local/bin/apply_lustre_tunings.sh"
        SERVICE_FILE="/etc/systemd/system/lustre-tunings.service"

        #EFA
        MIN_EFA_VERSION="2.12.1"

        # Function to check if a command was successful
        check_success() {
            if [ $? -eq 0 ]; then
                echo "SUCCESS: $1"
            else
                echo "FAILED: $1"
                return 1
            fi
        }

        echo "********Starting FSx for Lustre configuration********"

        # 1. Install Lustre client
        if grep -q '^ID=ubuntu' /etc/os-release; then
            echo "Detected Ubuntu, proceeding with Lustre setup..."
            # Add Lustre repository
            sudo wget -O - https://fsx-lustre-client-repo-public-keys.s3.amazonaws.com/fsx-ubuntu-public-key.asc | sudo gpg --dearmor | sudo tee /usr/share/keyrings/fsx-ubuntu-public-key.gpg > /dev/null

            echo "deb [signed-by=/usr/share/keyrings/fsx-ubuntu-public-key.gpg] https://fsx-lustre-client-repo.s3.amazonaws.com/ubuntu jammy main" | sudo tee /etc/apt/sources.list.d/fsxlustreclientrepo.list

            sudo apt-get update
            sudo apt-get install -y lustre-client-modules-$(uname -r)
            sudo apt-get install -y lustre-client
        else
            echo "Not Ubuntu, exiting"
            exit 1
        fi

        check_success "Install Lustre client"

        # Ensure Lustre tools are in the PATH
        export PATH=$PATH:/usr/sbin

        # 2. Apply network and RPC tunings
        echo "********Applying network and RPC tunings********"
        if ! grep -q "options ptlrpc ptlrpcd_per_cpt_max" /etc/modprobe.d/modprobe.conf; then
            echo "options ptlrpc ptlrpcd_per_cpt_max=64" | sudo tee -a /etc/modprobe.d/modprobe.conf
            check_success "Set ptlrpcd_per_cpt_max"
        else
            echo "ptlrpcd_per_cpt_max already set in modprobe.conf"
        fi

        if ! grep -q "options ksocklnd credits" /etc/modprobe.d/modprobe.conf; then
            echo "options ksocklnd credits=2560" | sudo tee -a /etc/modprobe.d/modprobe.conf
            check_success "Set ksocklnd credits"
        else
            echo "ksocklnd credits already set in modprobe.conf"
        fi

        # 3. Load Lustre modules
        manage_lustre_modules() {
            echo "Checking for existing Lustre modules..."
            if lsmod | grep -q lustre; then
                echo "Existing Lustre modules found."

                # Check for mounted Lustre filesystems
                echo "Checking for mounted Lustre filesystems..."
                if mount | grep -q "type lustre"; then
                    echo "Found mounted Lustre filesystems. Attempting to unmount..."
                    mounted_fs=$(mount | grep "type lustre" | awk '{print $3}')
                    for fs in $mounted_fs; do
                        echo "Unmounting $fs"
                        sudo umount $fs
                        check_success "Unmount filesystem $fs"
                    done
                else
                    echo "No Lustre filesystems mounted."
                fi

                # After unmounting, try to remove modules
                echo "Attempting to remove Lustre modules..."
                sudo lustre_rmmod
                if [ $? -eq 0 ]; then
                    echo "SUCCESS: Removed existing Lustre modules"
                else
                    echo "WARNING: Could not remove Lustre modules. They may still be in use."
                    echo "Please check for any remaining Lustre processes or mounts."
                    return 1
                fi
            else
                echo "No existing Lustre modules found."
            fi

            echo "Loading Lustre modules..."
            sudo modprobe lustre
            check_success "Load Lustre modules" || exit 1

            echo "Checking loaded Lustre modules:"
            lsmod | grep lustre
        }

        # Managing Lustre kernel modules
        echo "********Managing Lustre kernel modules********"
        manage_lustre_modules

        # 4. Initializing Lustre networking
        echo "********Initializing Lustre networking********"
        sudo lctl network up
        check_success "Initialize Lustre networking" || exit 1

        # 4.5 EFA Setup and Configuration
        setup_efa() {
            echo "********Starting EFA Setup********"

            # Get interface and version information
            eth_intf="$(/sbin/ip -br -4 a sh | grep $(hostname -i)/ | awk '{print $1}')"
            efa_version=$(modinfo efa | awk '/^version:/ {print $2}' | sed 's/[^0-9.]//g')
            min_efa_version=$MIN_EFA_VERSION

            # Install or verify EFA driver
            if [[ "$(printf '%s\n' "$min_efa_version" "$efa_version" | sort -V | head -n1)" != "$min_efa_version" ]]; then
                echo "Installing EFA driver..."
                sudo curl -O https://efa-installer.amazonaws.com/aws-efa-installer-1.37.0.tar.gz
                tar -xf aws-efa-installer-1.37.0.tar.gz && cd aws-efa-installer

                # Install dependencies
                sudo apt-get update && apt-get upgrade -y
                sudo apt install -y pciutils environment-modules libnl-3-dev libnl-route-3-200 libnl-route-3-dev dkms

                # Install EFA
                sudo ./efa_installer.sh -y
                modinfo efa
            else
                echo "Using existing EFA driver version $efa_version"
            fi
        }

        configure_efa_network() {
            echo "********Configuring EFA Network********"

            # Load required modules
            echo "Loading network modules..."
            sudo /sbin/modprobe lnet
            sudo /sbin/modprobe kefalnd ipif_name="$eth_intf"
            sudo /sbin/modprobe ksocklnd

            # Initialize LNet
            echo "Initializing LNet..."
            sudo lnetctl lnet configure

            # Configure TCP interface
            echo "Configuring TCP interface..."
            sudo lnetctl net del --net tcp 2> /dev/null
            sudo lnetctl net add --net tcp --if $eth_intf

            # For P5 instance type which supports 32 network cards,
            # by default add 8 EFA interfaces selecting every 4th device (1 per PCI bus)
            echo "Configuring EFA interface(s)..."
            instance_type="$(ec2-metadata --instance-type | awk '{ print $2 }')"
            num_efa_devices="$(ls -1 /sys/class/infiniband | wc -l)"
            echo "Found $num_efa_devices available EFA device(s)"

            if [[ "$instance_type" == "p5.48xlarge" || "$instance_type" == "p5e.48xlarge" ]]; then
                # P5 instance configuration
                for intf in $(ls -1 /sys/class/infiniband | awk 'NR % 4 == 1'); do
                    sudo lnetctl net add --net efa --if $intf --peer-credits 32
                done
            else
                # Standard configuration
                # Other instances: Configure 2 EFA interfaces by default if the instance supports multiple network cards,
                # or 1 interface for single network card instances
                # Can be modified to add more interfaces if instance type supports it
                sudo lnetctl net add --net efa --if $(ls -1 /sys/class/infiniband | head -n1) --peer-credits 32
                if [[ $num_efa_devices -gt 1 ]]; then
                    sudo lnetctl net add --net efa --if $(ls -1 /sys/class/infiniband | tail -n1) --peer-credits 32
                fi
            fi

            # Configure discovery and UDSP
            echo "Setting up discovery and UDSP rules..."
            sudo lnetctl set discovery 1
            sudo lnetctl udsp add --src efa --priority 0
            sudo /sbin/modprobe lustre

            # Verify configuration
            echo "Verifying EFA network configuration..."
            sudo lnetctl net show
            echo "Added $(sudo lnetctl net show | grep -c '@efa') EFA interface(s)"
        }

        # Main execution
        setup_efa
        configure_efa_network

        # 5. Mount FSx filesystem
        if [ ! -z "$FSX_DNS" ] && [ ! -z "$MOUNT_NAME" ]; then
            echo "********Creating mount point********"
            sudo mkdir -p $MOUNT_POINT
            check_success "Create mount point"

            echo "Mounting FSx filesystem..."
            sudo mount -t lustre ${FSX_DNS}@tcp:/${MOUNT_NAME} ${MOUNT_POINT}
            check_success "Mount FSx filesystem"
        else
            echo "Skipping FSx mount as DNS or mount name is not provided"
        fi

        # 6. Applying Lustre performance tunings
        echo "********Applying Lustre performance tunings********"

        # Get number of CPUs
        NUM_CPUS=$(nproc)

        # Calculate LRU size (100 * number of CPUs)
        LRU_SIZE=$((100 * NUM_CPUS))

        #Apply LRU tunings
        echo "Apply LRU tunings"
        sudo lctl set_param ldlm.namespaces.*.lru_max_age=${LUSTRE_LRU_MAX_AGE}
        check_success "Set lru_max_age"
        sudo lctl set_param ldlm.namespaces.*.lru_size=$LRU_SIZE
        check_success "Set lru_size"

        # Client Cache Control
        sudo lctl set_param llite.*.max_cached_mb=${LUSTRE_MAX_CACHED_MB}
        check_success "Set max_cached_mb"

        # RPC Controls
        sudo lctl set_param osc.*OST*.max_rpcs_in_flight=${LUSTRE_OST_MAX_RPC}
        check_success "Set OST max_rpcs_in_flight"

        sudo lctl set_param mdc.*.max_rpcs_in_flight=${LUSTRE_MDC_MAX_RPC}
        check_success "Set MDC max_rpcs_in_flight"

        sudo lctl set_param mdc.*.max_mod_rpcs_in_flight=${LUSTRE_MDC_MOD_RPC}
        check_success "Set MDC max_mod_rpcs_in_flight"

        # 7. Verify all tunings
        echo "********Verifying all tunings********"

        # Function to verify parameter value
        verify_param() {
            local param=$1
            local expected=$2
            local actual=$3

            if [ "$actual" == "$expected" ]; then
                echo "SUCCESS: $param is correctly set to $expected"
            else
                echo "WARNING: $param is set to $actual (expected $expected)"
            fi
        }

        echo "Verifying all parameters:"

        # LRU tunings
        actual_lru_max_age=$(lctl get_param -n ldlm.namespaces.*.lru_max_age | head -1)
        verify_param "lru_max_age" "600000" "$actual_lru_max_age"

        actual_lru_size=$(lctl get_param -n ldlm.namespaces.*.lru_size | head -1)
        verify_param "lru_size" "$LRU_SIZE" "$actual_lru_size"

        # Client Cache
        actual_max_cached_mb=$(lctl get_param -n llite.*.max_cached_mb | grep "max_cached_mb:" | awk '{print $2}')
        verify_param "max_cached_mb" "64" "$actual_max_cached_mb"

        # RPC Controls
        actual_ost_rpcs=$(lctl get_param -n osc.*OST*.max_rpcs_in_flight | head -1)
        verify_param "OST max_rpcs_in_flight" "32" "$actual_ost_rpcs"

        actual_mdc_rpcs=$(lctl get_param -n mdc.*.max_rpcs_in_flight | head -1)
        verify_param "MDC max_rpcs_in_flight" "64" "$actual_mdc_rpcs"

        actual_mdc_mod_rpcs=$(lctl get_param -n mdc.*.max_mod_rpcs_in_flight | head -1)
        verify_param "MDC max_mod_rpcs_in_flight" "50" "$actual_mdc_mod_rpcs"

        # Network and RPC configurations from modprobe.conf
        actual_ptlrpc=$(grep "ptlrpc ptlrpcd_per_cpt_max" /etc/modprobe.d/modprobe.conf | awk '{print $3}')
        verify_param "ptlrpcd_per_cpt_max" "ptlrpcd_per_cpt_max=64" "$actual_ptlrpc"

        actual_ksocklnd=$(grep "ksocklnd credits" /etc/modprobe.d/modprobe.conf | awk '{print $3}')
        verify_param "ksocklnd credits" "credits=2560" "$actual_ksocklnd"

        # 8. Setup persistence
        setup_persistence() {
            # Create functions file
            cat << EOF > $FUNCTIONS_SCRIPT
        #!/bin/bash

        apply_lustre_tunings() {
            local NUM_CPUS=\$(nproc)
            local LRU_SIZE=\$((100 * NUM_CPUS))

            echo "Applying Lustre performance tunings..."
            lctl set_param ldlm.namespaces.*.lru_max_age=$LUSTRE_LRU_MAX_AGE
            lctl set_param ldlm.namespaces.*.lru_size=\$LRU_SIZE
            lctl set_param llite.*.max_cached_mb=$LUSTRE_MAX_CACHED_MB
            lctl set_param osc.*OST*.max_rpcs_in_flight=$LUSTRE_OST_MAX_RPC
            lctl set_param mdc.*.max_rpcs_in_flight=$LUSTRE_MDC_MAX_RPC
            lctl set_param mdc.*.max_mod_rpcs_in_flight=$LUSTRE_MDC_MOD_RPC
        }
        EOF

            # Create tuning script
            cat << EOF > $TUNINGS_SCRIPT
        #!/bin/bash
        exec 1> >(logger -s -t \$(basename \$0)) 2>&1

        source $FUNCTIONS_SCRIPT

        # Function to check if Lustre is mounted
        is_lustre_mounted() {
            mount | grep -q "type lustre"
        }

        # Function to mount Lustre
        mount_lustre() {
            echo "Mounting Lustre filesystem..."
            mkdir -p $MOUNT_POINT
            mount -t lustre ${FSX_DNS}@tcp:/${MOUNT_NAME} $MOUNT_POINT
            return \$?
        }

        # Main execution
        # Try to mount if not already mounted
        if ! is_lustre_mounted; then
            echo "Lustre filesystem not mounted, attempting to mount..."
            mount_lustre
        fi

        # Wait for successful mount (up to 5 minutes)
        for i in {1..30}; do
            if is_lustre_mounted; then
                echo "Lustre filesystem mounted, applying tunings..."
                apply_lustre_tunings
                exit 0
            fi
            echo "Waiting for Lustre filesystem to be mounted... (attempt $i/30)"
            sleep 10
        done

        echo "Timeout waiting for Lustre filesystem mount"
        exit 1
        EOF

        # Create systemd service

        # Create systemd directory if it doesn't exist
        sudo mkdir -p /etc/systemd/system/

            # Create service file directly for Ubuntu
            cat << EOF > $SERVICE_FILE
        [Unit]
        Description=Apply Lustre Performance Tunings
        After=network.target remote-fs.target

        [Service]
        Type=oneshot
        ExecStart=/bin/bash -c 'source $FUNCTIONS_SCRIPT && $TUNINGS_SCRIPT'
        RemainAfterExit=yes

        [Install]
        WantedBy=multi-user.target
        EOF


            # Make scripts executable and enable service
            sudo chmod +x $FUNCTIONS_SCRIPT
            sudo chmod +x $TUNINGS_SCRIPT
            systemctl enable lustre-tunings.service
            systemctl start lustre-tunings.service
        }

        echo "********Setting up persistent tuning********"
        setup_persistence

        echo "FSx for Lustre configuration completed."
```

## (선택 사항) 3단계. EFA 설정 확인
<a name="verify-efa-setup"></a>

노드에 SSH로 연결합니다.

```
# Get instance ID from EKS console or {aws} CLI
ssh -i /path/to/your-key.pem ec2-user@<node-internal-ip>
```

EFA 구성을 확인합니다.

```
sudo lnetctl net show
```

설정 로그를 확인합니다.

```
sudo cat /var/log/cloud-init-output.log
```

다음은 `lnetctl net show`에 대한 예상 출력의 예입니다.

```
net:
    - net type: tcp
      ...
    - net type: efa
      local NI(s):
        - nid: xxx.xxx.xxx.xxx@efa
          status: up
```

## 배포 예제
<a name="example-deployments"></a>

### a. claim.yaml 생성
<a name="_a_create_claim_yaml"></a>

```
#claim.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: fsx-claim-efa
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: ""
  resources:
    requests:
      storage: 4800Gi
  volumeName: fsx-pv
```

클레임을 적용합니다.

```
kubectl apply -f claim.yaml
```

### b. pv.yaml 생성
<a name="_b_create_pv_yaml"></a>

`<replaceable-placeholders>`를 업데이트합니다.

```
#pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: fsx-pv
spec:
  capacity:
    storage: 4800Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  mountOptions:
    - flock
  persistentVolumeReclaimPolicy: Recycle
  csi:
    driver: fsx.csi.aws.com
    volumeHandle: fs-<1234567890abcdef0>
    volumeAttributes:
      dnsname: fs-<1234567890abcdef0>.fsx.us-east-1.amazonaws.com
      mountname: <abcdef01>
```

영구 볼륨을 적용합니다.

```
kubectl apply -f pv.yaml
```

### c. pod.yaml 생성
<a name="_c_create_pod_yaml"></a>

```
#pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: fsx-efa-app
spec:
  containers:
  - name: app
    image: amazonlinux:2
    command: ["/bin/sh"]
    args: ["-c", "while true; do dd if=/dev/urandom bs=100M count=20 > data/test_file; sleep 10; done"]
    resources:
      requests:
        vpc.amazonaws.com/efa: 1
      limits:
        vpc.amazonaws.com/efa: 1
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: fsx-claim-efa
```

포드를 적용합니다.

```
kubectl apply -f pod.yaml
```

## 추가 확인 명령
<a name="verification-commands"></a>

파일 시스템에 포드 탑재 및 쓰기를 확인합니다.

```
kubectl exec -ti fsx-efa-app -- df -h | grep data
# Expected output:
# <192.0.2.0>@tcp:/<abcdef01>  4.5T  1.2G  4.5T   1% /data

kubectl exec -ti fsx-efa-app -- ls /data
# Expected output:
# test_file
```

노드에 SSH로 연결하여 트래픽이 EFA를 통과하는지 확인합니다.

```
sudo lnetctl net show -v
```

예상 출력에는 트래픽 통계가 포함된 EFA 인터페이스가 표시됩니다.

## 관련 정보
<a name="_related_information"></a>
+  [FSx for Lustre CSI 드라이버 배포](fsx-csi-create.md) 
+  [노드에서 Amazon FSx for Lustre 성능 최적화(비 EFA)](fsx-csi-tuning-non-efa.md) 
+  [Amazon FSx for Lustre Performance](https://docs.aws.amazon.com/fsx/latest/LustreGuide/performance.html) 
+  [Elastic Fabric Adapter](https://docs.aws.amazon.com/ec2/latest/userguide/efa.html) 

# 노드에서 Amazon FSx for Lustre 성능 최적화(비 EFA)
<a name="fsx-csi-tuning-non-efa"></a>

시작 템플릿 사용자 데이터를 사용한 노드 초기화 중에 튜닝 파라미터를 적용하여 Amazon FSx for Lustre 성능을 최적화할 수 있습니다.

**참고**  
FSx for Lustre CSI 드라이버 생성 및 배포에 대한 자세한 내용은 [FSx for Lustre CSI 드라이버 배포](fsx-csi-create.md) 섹션을 참조하세요. EFA 지원 노드를 사용하여 성능을 최적화하려면 [노드에서 Amazon FSx for Lustre 성능 최적화(EFA)](fsx-csi-tuning-efa.md) 섹션을 참조하세요.

## 시작 템플릿 사용자 데이터를 사용하는 이유는 무엇인가요?
<a name="_why_use_launch_template_user_data"></a>
+ 노드 초기화 중에 튜닝을 자동으로 적용합니다.
+ 모든 노드에서 일관된 구성을 보장합니다.
+ 수동 노드 구성이 필요하지 않습니다.

## 예제 스크립트 개요
<a name="_example_script_overview"></a>

이 주제에 정의된 예제 스크립트는 다음 작업을 수행합니다.

### `# 1. Install Lustre client`
<a name="_1_install_lustre_client"></a>
+ Amazon Linux(AL) OS 버전을 자동으로 감지합니다.
+ 적절한 Lustre 클라이언트 패키지를 설치합니다.

### `# 2. Apply network and RPC tunings`
<a name="_2_apply_network_and_rpc_tunings"></a>
+ 병렬 RPC 처리를 위해 `ptlrpcd_per_cpt_max=64`를 설정합니다.
+ 네트워크 버퍼를 최적화하도록 `ksocklnd credits=2560`을 구성합니다.

### `# 3. Load Lustre modules`
<a name="_3_load_lustre_modules"></a>
+ 기존 Lustre 모듈을 안전하게 제거합니다(있는 경우).
+ 기존 파일 시스템의 탑재 해제를 처리합니다.
+ 새 Lustre 모듈을 로드합니다.

### `# 4. Lustre Network Initialization`
<a name="_4_lustre_network_initialization"></a>
+ Lustre 네트워킹 구성을 초기화합니다.
+ 필요한 네트워크 파라미터를 설정합니다.

### `# 5. Mount FSx filesystem`
<a name="_5_mount_fsx_filesystem"></a>
+ 이 섹션에서는 환경의 값을 조정해야 합니다.

### `# 6. Apply tunings`
<a name="_6_apply_tunings"></a>
+ LRU(리소스 잠금 단위) 튜닝:
  +  `lru_max_age=600000` 
  +  CPU 수를 기준으로 계산된 `lru_size`
+ 클라이언트 캐시 제어: `max_cached_mb=64` 
+ RPC 제어:
  + OST `max_rpcs_in_flight=32` 
  + MDC `max_rpcs_in_flight=64` 
  + MDC `max_mod_rpcs_in_flight=50` 

### `# 7. Verify tunings`
<a name="_7_verify_tunings"></a>
+ 적용된 튜닝을 모두 확인합니다.
+ 각 파라미터에 대해 성공 또는 경고를 보고합니다.

### `# 8. Setup persistence`
<a name="_8_setup_persistence"></a>
+ 이 섹션에서도 환경의 값을 조정해야 합니다.
+ OS 버전(AL2023)을 자동으로 감지하여 적용할 `Systemd` 서비스를 결정합니다.
+ 시스템을 시작합니다.
+  `Systemd`가 `lustre-tunings` 서비스를 시작합니다(`WantedBy=multi-user.target` 때문).
+ 서비스는 다음 작업을 수행하는 `apply_lustre_tunings.sh`를 실행합니다.
  + 파일 시스템이 탑재되었는지 확인합니다.
  + 탑재되지 않은 경우 파일 시스템을 탑재합니다.
  + 탑재가 성공할 때까지 기다립니다(최대 5분).
  + 탑재 성공 후 튜닝 파라미터를 적용합니다.
+ 설정은 재부팅할 때까지 활성 상태로 유지됩니다.
+ 스크립트 완료 후 서비스가 종료됩니다.
  + Systemd는 서비스를 ‘활성(종료됨)’으로 표시합니다.
+ 다음 재부팅 시 프로세스가 반복됩니다.

## 시작 템플릿 생성
<a name="_create_a_launch_template"></a>

1. https://console.aws.amazon.com/ec2/에서 Amazon EC2 콘솔을 엽니다.

1. **시작 템플릿**을 선택합니다.

1. **Create launch template**(시작 템플릿 생성)을 선택합니다.

1. **고급 세부 정보**에서 **사용자 데이터** 섹션을 찾습니다.

1. 아래 스크립트를 붙여넣고 필요한 항목을 업데이트합니다.
**중요**  
`# 5. Mount FSx filesystem` 섹션에서 그리고 `# 8. Setup persistence` 섹션 내 `apply_lustre_tunings.sh`의 `setup_persistence()` 함수에서 다음 값을 환경에 맞게 조정합니다.  

   ```
   FSX_DNS="<your-fsx-filesystem-dns>" # Needs to be adjusted.
   MOUNT_NAME="<your-mount-name>" # Needs to be adjusted.
   MOUNT_POINT="</your/mount/point>" # Needs to be adjusted.
   ```

   ```
   MIME-Version: 1.0
   Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="
   --==MYBOUNDARY==
   Content-Type: text/x-shellscript; charset="us-ascii"
   #!/bin/bash
   exec 1> >(logger -s -t $(basename $0)) 2>&1
   # Function definitions
   check_success() {
       if [ $? -eq 0 ]; then
           echo "SUCCESS: $1"
       else
           echo "FAILED: $1"
           return 1
       fi
   }
   apply_tunings() {
       local NUM_CPUS=$(nproc)
       local LRU_SIZE=$((100 * NUM_CPUS))
       local params=(
           "ldlm.namespaces.*.lru_max_age=600000"
           "ldlm.namespaces.*.lru_size=$LRU_SIZE"
           "llite.*.max_cached_mb=64"
           "osc.*OST*.max_rpcs_in_flight=32"
           "mdc.*.max_rpcs_in_flight=64"
           "mdc.*.max_mod_rpcs_in_flight=50"
       )
       for param in "${params[@]}"; do
           lctl set_param $param
           check_success "Set ${param%%=*}"
       done
   }
   verify_param() {
       local param=$1
       local expected=$2
       local actual=$3
   
       if [ "$actual" == "$expected" ]; then
           echo "SUCCESS: $param is correctly set to $expected"
       else
           echo "WARNING: $param is set to $actual (expected $expected)"
       fi
   }
   verify_tunings() {
       local NUM_CPUS=$(nproc)
       local LRU_SIZE=$((100 * NUM_CPUS))
       local params=(
           "ldlm.namespaces.*.lru_max_age:600000"
           "ldlm.namespaces.*.lru_size:$LRU_SIZE"
           "llite.*.max_cached_mb:64"
           "osc.*OST*.max_rpcs_in_flight:32"
           "mdc.*.max_rpcs_in_flight:64"
           "mdc.*.max_mod_rpcs_in_flight:50"
       )
       echo "Verifying all parameters:"
       for param in "${params[@]}"; do
           name="${param%%:*}"
           expected="${param#*:}"
           actual=$(lctl get_param -n $name | head -1)
           verify_param "${name##*.}" "$expected" "$actual"
       done
   }
   setup_persistence() {
       # Create functions file
       cat << 'EOF' > /usr/local/bin/lustre_functions.sh
   #!/bin/bash
   apply_lustre_tunings() {
       local NUM_CPUS=$(nproc)
       local LRU_SIZE=$((100 * NUM_CPUS))
   
       echo "Applying Lustre performance tunings..."
       lctl set_param ldlm.namespaces.*.lru_max_age=600000
       lctl set_param ldlm.namespaces.*.lru_size=$LRU_SIZE
       lctl set_param llite.*.max_cached_mb=64
       lctl set_param osc.*OST*.max_rpcs_in_flight=32
       lctl set_param mdc.*.max_rpcs_in_flight=64
       lctl set_param mdc.*.max_mod_rpcs_in_flight=50
   }
   EOF
       # Create tuning script
       cat << 'EOF' > /usr/local/bin/apply_lustre_tunings.sh
   #!/bin/bash
   exec 1> >(logger -s -t $(basename $0)) 2>&1
   # Source the functions
   source /usr/local/bin/lustre_functions.sh
   # FSx details
   FSX_DNS="<your-fsx-filesystem-dns>" # Needs to be adjusted.
   MOUNT_NAME="<your-mount-name>" # Needs to be adjusted.
   MOUNT_POINT="</your/mount/point>" # Needs to be adjusted.
   # Function to check if Lustre is mounted
   is_lustre_mounted() {
       mount | grep -q "type lustre"
   }
   # Function to mount Lustre
   mount_lustre() {
       echo "Mounting Lustre filesystem..."
       mkdir -p ${MOUNT_POINT}
       mount -t lustre ${FSX_DNS}@tcp:/${MOUNT_NAME} ${MOUNT_POINT}
       return $?
   }
   # Main execution
   # Try to mount if not already mounted
   if ! is_lustre_mounted; then
       echo "Lustre filesystem not mounted, attempting to mount..."
       mount_lustre
   fi
   # Wait for successful mount (up to 5 minutes)
   for i in {1..30}; do
       if is_lustre_mounted; then
           echo "Lustre filesystem mounted, applying tunings..."
           apply_lustre_tunings
           exit 0
       fi
       echo "Waiting for Lustre filesystem to be mounted... (attempt $i/30)"
       sleep 10
   done
   echo "Timeout waiting for Lustre filesystem mount"
   exit 1
   EOF
       # Create systemd service
       cat << 'EOF' > /etc/systemd/system/lustre-tunings.service
   [Unit]
   Description=Apply Lustre Performance Tunings
   After=network.target remote-fs.target
   StartLimitIntervalSec=0
   [Service]
   Type=oneshot
   ExecStart=/usr/local/bin/apply_lustre_tunings.sh
   RemainAfterExit=yes
   Restart=on-failure
   RestartSec=30
   [Install]
   WantedBy=multi-user.target
   EOF
       chmod +x /usr/local/bin/lustre_functions.sh
       chmod +x /usr/local/bin/apply_lustre_tunings.sh
       systemctl enable lustre-tunings.service
       systemctl start lustre-tunings.service
   }
   echo "Starting FSx for Lustre configuration..."
   # 1. Install Lustre client
   if grep -q 'VERSION="2"' /etc/os-release; then
       amazon-linux-extras install -y lustre
   elif grep -q 'VERSION="2023"' /etc/os-release; then
       dnf install -y lustre-client
   fi
   check_success "Install Lustre client"
   # 2. Apply network and RPC tunings
   export PATH=$PATH:/usr/sbin
   echo "Applying network and RPC tunings..."
   if ! grep -q "options ptlrpc ptlrpcd_per_cpt_max" /etc/modprobe.d/modprobe.conf; then
       echo "options ptlrpc ptlrpcd_per_cpt_max=64" | tee -a /etc/modprobe.d/modprobe.conf
       echo "options ksocklnd credits=2560" | tee -a /etc/modprobe.d/modprobe.conf
   fi
   # 3. Load Lustre modules
   modprobe lustre
   check_success "Load Lustre modules" || exit 1
   # 4. Lustre Network Initialization
   lctl network up
   check_success "Initialize Lustre networking" || exit 1
   # 5. Mount FSx filesystem
   FSX_DNS="<your-fsx-filesystem-dns>" # Needs to be adjusted.
   MOUNT_NAME="<your-mount-name>" # Needs to be adjusted.
   MOUNT_POINT="</your/mount/point>" # Needs to be adjusted.
   if [ ! -z "$FSX_DNS" ] && [ ! -z "$MOUNT_NAME" ]; then
       mkdir -p $MOUNT_POINT
       mount -t lustre ${FSX_DNS}@tcp:/${MOUNT_NAME} ${MOUNT_POINT}
       check_success "Mount FSx filesystem"
   fi
   # 6. Apply tunings
   apply_tunings
   # 7. Verify tunings
   verify_tunings
   # 8. Setup persistence
   setup_persistence
   echo "FSx for Lustre configuration completed."
   --==MYBOUNDARY==--
   ```

1. Amazon EKS 노드 그룹을 생성할 때 이 시작 템플릿을 선택합니다. 자세한 내용은 [클러스터에 대한 관리형 노드 그룹 생성](create-managed-node-group.md) 섹션을 참조하세요.

## 관련 정보
<a name="_related_information"></a>
+  [FSx for Lustre CSI 드라이버 배포](fsx-csi-create.md) 
+  [노드에서 Amazon FSx for Lustre 성능 최적화(EFA)](fsx-csi-tuning-efa.md) 
+  [Amazon FSx for Lustre Performance](https://docs.aws.amazon.com/fsx/latest/LustreGuide/performance.html) 

# FSx for NetApp ONTAP과 함께 고성능 앱 스토리지 사용
<a name="fsx-ontap"></a>

NetApp Trident에서는 Container Storage Interface(CSI) 호환 드라이버를 사용하여 동적 스토리지 오케스트레이션을 제공합니다. 이를 사용하면 Amazon FSx for NetApp ONTAP 파일 시스템에서 지원하는 영구 볼륨(PV)의 수명 주기를 Amazon EKS 클러스터에서 관리할 수 있습니다. Amazon FSx for NetApp ONTAP CSI 드라이버는 Amazon EKS Hybrid Nodes와 호환되지 않습니다. 시작하려면 NetApp Trident 설명서의 [Amazon FSx for NetApp ONTAP에서 Trident 사용](https://docs.netapp.com/us-en/trident/trident-use/trident-fsx.html)을 참조하세요.

Amazon FSx for NetApp ONTAP은 클라우드에서 완전관리형 ONTAP 파일 시스템을 시작하고 실행할 수 있는 스토리지 서비스입니다. ONTAP은 널리 채택된 데이터 액세스 및 데이터 관리 기능의 집합을 제공하는 NetApp의 파일 시스템 기술입니다. FSx for ONTAP은 완전 관리형 AWS 서비스의 민첩성, 확장성 및 단순성을 온프레미스 NetApp 파일 시스템의 기능, 성능 및 API에 제공합니다. 자세한 내용은 [FSx for ONTAP 사용 설명서](https://docs.aws.amazon.com/fsx/latest/ONTAPGuide/what-is-fsx-ontap.html)를 참조하세요.

**중요**  
Amazon EBS CSI 드라이버와 함께 Amazon FSx for NetApp ONTAP을 사용하여 EBS 볼륨을 프로비저닝하는 경우 `multipath.conf` 파일에서 EBS 디바이스를 사용하지 않도록 지정해야 합니다. 지원되는 방법은 [구성 파일 블랙리스트](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/dm_multipath/config_file_blacklist#config_file_blacklist)를 참조하세요. 다음 예를 참고하세요  

```
 defaults {
        user_friendly_names yes
        find_multipaths no
      }
      blacklist {
        device {
          vendor "NVME"
          product "Amazon Elastic Block Store"
        }
      }
```

# Amazon FSx for OpenZFS와 함께 데이터 스토리지 사용
<a name="fsx-openzfs-csi"></a>

Amazon FSx for OpenZFS는 온프레미스 ZFS 또는 기타 Linux 기반 파일 서버에서 AWS로 데이터를 손쉽게 이동할 수 있는 완전관리형 파일 스토리지 서비스입니다. 애플리케이션 코드나 데이터 관리 방법을 변경하지 않고도 이 작업을 수행할 수 있습니다. 또한 Amazon FSx for OpenZFS는 오픈 소스 OpenZFS 파일 시스템에 구축된 매우 안정적이고 확장 가능하며 효율적이고 기능이 풍부한 파일 스토리지를 제공합니다. 이러한 기능을 완전관리형 AWS 서비스의 민첩성, 확장성 및 단순성과 결합합니다. 자세한 내용은 [Amazon FSx for OpenZFS User Guide](https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/what-is-fsx.html)를 참조하세요.

FSx for OpenZFS 컨테이너 스토리지(CSI) 드라이버에서는 Amazon EKS 클러스터가 FSx for OpenZFS 볼륨의 수명 주기를 관리할 수 있도록 하는 CSI 인터페이스를 제공합니다. Amazon FSx for OpenZFS CSI 드라이버는 Amazon EKS Hybrid Nodes와 호환되지 않습니다. FSx for OpenZFS CSI 드라이버를 Amazon EKS 클러스터에 배포하려면 GitHub의 [aws-fsx-openzfs-csi-driver](https://github.com/kubernetes-sigs/aws-fsx-openzfs-csi-driver) 섹션을 참조하세요.

# Amazon File Cache를 사용한 지연 시간 최소화
<a name="file-cache-csi"></a>

Amazon 파일 캐시는 데이터가 저장된 위치에 관계없이 파일 데이터를 처리하는 데 사용되는 AWS의 완전 관리형 고속 캐시입니다. Amazon File Cache는 처음 액세스하면 캐시에 데이터를 자동으로 로드하고 사용하지 않을 때는 데이터를 릴리스합니다. 자세한 내용은 [Amazon File Cache 사용 설명서](https://docs.aws.amazon.com/fsx/latest/FileCacheGuide/what-is.html)를 참조하세요.

Amazon EBS Container Storage Interface(CSI) 드라이버는 클러스터가 Amazon EFS 파일 시스템의 수명 주기를 관리할 수 있게 해주는 CSI 인터페이스를 제공합니다. Amazon File Cache CSI 드라이버는 Amazon EKS Hybrid Nodes와 호환되지 않습니다. Amazon 파일 캐시 CSI 드라이버를 Amazon EKS 클러스터에 배포하려면 GitHub에서 [aws-file-cache-csi-driver](https://github.com/kubernetes-sigs/aws-file-cache-csi-driver)를 참조하세요.

# Mountpoint for Amazon S3 CSI 드라이버를 통해 Amazon S3 객체에 액세스
<a name="s3-csi"></a>

[Mountpoint for Amazon S3 컨테이너 스토리지 인터페이스(CSI) 드라이버](https://github.com/awslabs/mountpoint-s3-csi-driver)를 사용하면 Kubernetes 애플리케이션이 파일 시스템 인터페이스를 통해 Amazon S3 객체에 액세스하여Kubernetes 애플리케이션 코드를 변경하지 않고도 높은 총 처리량을 달성할 수 있습니다. [Mountpoint for Amazon S3](https://github.com/awslabs/mountpoint-s3)를 기반으로 구축된 CSI 드라이버는 Amazon EKS 및 자체 관리형 Kubernetes 클러스터의 컨테이너가 액세스할 수 있는 볼륨으로 Amazon S3 버킷을 제공합니다.

## 고려 사항
<a name="s3-csi-considerations"></a>
+ Mountpoint for Amazon S3 CSI 드라이버는 현재 Windows 기반 컨테이너 이미지와 호환되지 않습니다.
+ Mountpoint for Amazon S3 CSI 드라이버는 현재 Amazon EKS Hybrid Nodes와 호환되지 않습니다.
+ Mountpoint for Amazon S3 CSI 드라이버는 AWS Fargate를 지원하지 않습니다. 하지만 Amazon EC2에서 실행되는 컨테이너(Amazon EKS 또는 사용자 지정 Kubernetes 설치)는 지원됩니다.
+ Mountpoint for Amazon S3 CSI 드라이버는 정적 프로비저닝만 지원합니다. 동적 프로비저닝 또는 새 버킷의 생성은 지원되지 않습니다.
**참고**  
정적 프로비저닝이란 `PersistentVolume` 객체의 `volumeAttributes`에서 `bucketName`으로 지정된 기존 Amazon S3 버킷을 사용하는 것을 말합니다. 자세한 내용은 GitHub의 [Static Provisioning](https://github.com/awslabs/mountpoint-s3-csi-driver/blob/main/examples/kubernetes/static_provisioning/README.md)을 참조하세요.
+ Mountpoint for Amazon S3 CSI 드라이버가 탑재된 볼륨은 모든 POSIX 파일 시스템 기능을 지원하지는 않습니다. 파일 시스템 동작에 대한 자세한 내용은 GitHub의 [Mountpoint for Amazon S3 file system behavior](https://github.com/awslabs/mountpoint-s3/blob/main/doc/SEMANTICS.md)를 참조하세요.

드라이버 배포에 대한 자세한 내용은 [Mountpoint for Amazon S3 드라이버 배포](s3-csi-create.md) 섹션을 참조하세요. 드라이버 제거에 대한 자세한 내용은 [Mountpoint for Amazon S3 Amazon EKS 추가 기능 제거](removing-s3-csi-eks-add-on.md) 섹션을 참조하세요.

# Mountpoint for Amazon S3 드라이버 배포
<a name="s3-csi-create"></a>

[Mountpoint for Amazon S3 컨테이너 스토리지 인터페이스(CSI) 드라이버](https://github.com/awslabs/mountpoint-s3-csi-driver)를 사용하면 Kubernetes 애플리케이션이 파일 시스템 인터페이스를 통해 Amazon S3 객체에 액세스하여Kubernetes 애플리케이션 코드를 변경하지 않고도 높은 총 처리량을 달성할 수 있습니다.

이 절차에서는 [Mountpoint for Amazon S3 CSI Amazon EKS 드라이버](s3-csi.md)를 배포하는 방법을 보여줍니다. 계속하기 전에 [고려 사항](s3-csi.md#s3-csi-considerations)을 검토하세요.

## 사전 조건
<a name="s3-csi-prereqs"></a>
+ 클러스터에 대한 기존 AWS Identity and Access Management(IAM) OpenID Connect(OIDC) 제공자입니다. 이미 있는지 아니면 생성해야 하는지 확인하려면 [클러스터에 대한 IAM OIDC 공급자 생성](enable-iam-roles-for-service-accounts.md) 부분을 참조하세요.
+ 디바이스 또는 AWS CloudShell에 AWS CLI 버전 2.12.3 이후 버전이 설치 및 구성됩니다.
+ `kubectl` 명령줄 도구는 장치 또는 AWS CloudShell에 설치됩니다. 버전은 클러스터의 Kubernetes 버전과 동일하거나 최대 하나 이전 또는 이후의 마이너 버전일 수 있습니다. 예를 들어, 클러스터 버전이 `1.29`인 경우 `kubectl` 버전 `1.28`, `1.29` 또는 `1.30`를 함께 사용할 수 있습니다. `kubectl`을 설치하거나 업그레이드하려면 [`kubectl` 및 `eksctl` 설정](install-kubectl.md) 부분을 참조하세요.

## 1단계: IAM 정책 생성
<a name="s3-create-iam-policy"></a>

Mountpoint for Amazon S3 CSI 드라이버가 파일 시스템과 상호 작용하려면 Amazon S3 권한이 필요합니다. 이 섹션에서는 필요한 권한을 부여하는 IAM 정책을 생성하는 방법을 소개합니다.

다음 정책 예시는 Mountpoint에 대한 IAM 권한 권장 사항을 따릅니다. 또는 AWS 관리형 정책 [AmazonS3FullAccess](https://console.aws.amazon.com/iam/home?#/policies/arn:aws:iam::aws:policy/AmazonS3FullAccess$jsonEditor)를 사용할 수 있지만 이 관리형 정책은 Mountpoint에 필요한 것보다 더 많은 권한을 부여합니다.

Mountpoint에 대해 권장되는 권한에 대한 자세한 내용은 GitHub의 [Mountpoint IAM permissions](https://github.com/awslabs/mountpoint-s3/blob/main/doc/CONFIGURATION.md#iam-permissions)를 참조하세요.

1. IAM 콘솔(https://console.aws.amazon.com/iam/)을 엽니다.

1. 왼쪽 탐색 창에서 **정책**을 선택합니다.

1. **정책** 페이지에서 **정책 생성**을 선택합니다.

1. **정책 편집기**에서 **JSON**을 선택합니다.

1. **정책 편집기**에서 다음을 복사하고 붙여 넣습니다.
**중요**  
`amzn-s3-demo-bucket1`을 사용자의 Amazon S3 버킷 이름으로 대체합니다.

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
           {
               "Sid": "MountpointFullBucketAccess",
               "Effect": "Allow",
               "Action": [
                   "s3:ListBucket"
               ],
               "Resource": [
                   "arn:aws:s3:::amzn-s3-demo-bucket1"
               ]
           },
           {
               "Sid": "MountpointFullObjectAccess",
               "Effect": "Allow",
               "Action": [
                   "s3:GetObject",
                   "s3:PutObject",
                   "s3:AbortMultipartUpload",
                   "s3:DeleteObject"
               ],
               "Resource": [
                   "arn:aws:s3:::amzn-s3-demo-bucket1/*"
               ]
           }
      ]
   }
   ```

   Amazon S3 Express One Zone 스토리지 클래스에 도입된 디렉터리 버킷은 범용 버킷과 다른 인증 메커니즘을 사용합니다. `s3:*` 작업을 사용하는 대신 `s3express:CreateSession` 작업을 사용해야 합니다. 디렉터리 버킷에 대한 자세한 내용은 **Amazon S3 사용 설명서의 [디렉터리 버킷](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html)을 참조하세요.

   다음은 디렉터리 버킷에 사용할 최소 권한 정책의 예입니다.

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "s3express:CreateSession",
               "Resource": "arn:aws:s3express:us-west-2:111122223333:bucket/amzn-s3-demo-bucket1--usw2-az1--x-s3"
           }
       ]
   }
   ```

1. **다음**을 선택합니다.

1. **검토 및 생성** 페이지에서 정책의 이름을 지정합니다. 이 예시 연습에서는 `AmazonS3CSIDriverPolicy`라는 이름을 사용합니다.

1. **정책 생성**을 선택합니다.

## 2단계 - IAM 역할 생성
<a name="s3-create-iam-role"></a>

Mountpoint for Amazon S3 CSI 드라이버가 파일 시스템과 상호 작용하려면 Amazon S3 권한이 필요합니다. 이 섹션에서는 IAM 역할을 생성하여 이러한 권한을 위임하는 방법을 설명합니다. 이 역할을 생성하려면 다음 도구 중 하나를 사용할 수 있습니다.
+  [eksctl](#eksctl_s3_store_app_data) 
+  [AWS Management Console](#console_s3_store_app_data) 
+  [AWS CLI](#awscli_s3_store_app_data) 

**참고**  
IAM 정책 `AmazonS3CSIDriverPolicy`는 이전 섹션에서 생성되었습니다.

### eksctl
<a name="eksctl_s3_store_app_data"></a>

 **`eksctl`을 사용하여 Mountpoint for Amazon S3 CSI 드라이버 IAM 역할 생성** 

IAM 역할 및 Kubernetes 서비스 계정을 생성하려면 다음 명령을 실행합니다. 또한 이러한 명령은 `AmazonS3CSIDriverPolicy` IAM 정책을 역할에 연결하고, Kubernetes 서비스 계정(`s3-csi-controller-sa`)에 IAM 역할 Amazon 리소스 이름(ARN)을 주석으로 추가하고, Kubernetes 서비스 계정 이름을 IAM 역할에 대한 신뢰 정책에 추가합니다.

```
CLUSTER_NAME=my-cluster
REGION=region-code
ROLE_NAME=AmazonEKS_S3_CSI_DriverRole
POLICY_ARN=AmazonEKS_S3_CSI_DriverRole_ARN
eksctl create iamserviceaccount \
    --name s3-csi-driver-sa \
    --namespace kube-system \
    --cluster $CLUSTER_NAME \
    --attach-policy-arn $POLICY_ARN \
    --approve \
    --role-name $ROLE_NAME \
    --region $REGION \
    --role-only
```

### AWS Management Console
<a name="console_s3_store_app_data"></a>

1. IAM 콘솔(https://console.aws.amazon.com/iam/)을 엽니다.

1. 왼쪽 탐색 창에서 **역할**을 선택합니다.

1. **역할** 페이지에서 **역할 생성**을 선택합니다.

1. **신뢰할 수 있는 엔터티 선택** 페이지에서 다음을 수행합니다.

   1. **신뢰할 수 있는 엔터티 유형** 섹션에서 **웹 자격 증명**을 선택합니다.

   1. **아이덴티티 제공업체(Identity provider)**의 경우 클러스터에 대해 **OpenID Connect 공급자 URL(OpenID Connect provider URL)**을 선택합니다(Amazon EKS의 **개요**에 표시된 대로).

      URL이 표시되지 않으면 [필수 요건](#s3-csi-prereqs)을 검토하세요.

   1. **대상**에서 `sts.amazonaws.com`을 입력합니다.

   1. **다음**을 선택합니다.

1. **권한 추가** 페이지에서 다음을 수행합니다.

   1. **필터 정책** 상자에 AmazonS3CSIDriverPolicy를 입력합니다.
**참고**  
이 정책은 이전 섹션에서 생성되었습니다.

   1. 검색에서 반환된 `AmazonS3CSIDriverPolicy` 결과 왼쪽에 있는 확인란을 선택합니다.

   1. **다음**을 선택합니다.

1. **이름, 검토 및 생성** 페이지에서 다음을 수행합니다.

   1. **역할 이름**에 역할의 고유한 이름(예: AmazonEKS\$1S3\$1CSI\$1DriverRole)을 입력합니다.

   1. **태그 추가(선택사항)**에서 태그를 키-값 페어로 연결하여 메타데이터를 역할에 추가합니다. IAM에서 태그 사용에 대한 자세한 내용을 알아보려면 IAM 사용 설명서의 [IAM 리소스에 태깅](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html)을 참조하세요.

   1. **역할 생성**을 선택합니다.

1. 역할을 생성한 후 편집할 수 있도록 콘솔에서 이 역할을 선택하여 엽니다.

1. **신뢰 관계** 탭을 선택한 후 **신뢰 정책 편집**을 선택합니다.

1. 다음과 비슷한 줄을 찾습니다.

   ```
   "oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
   ```

   이전 줄의 끝에 쉼표를 추가한 다음 이전 줄 뒤에 다음 줄을 추가합니다. *region-code*를 클러스터가 있는 AWS 리전으로 바꿉니다. *EXAMPLED539D4633E53DE1B71EXAMPLE*을 클러스터의 OIDC 공급자 ID로 바꿉니다.

   ```
   "oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:kube-system:s3-csi-driver-sa"
   ```

1. `Condition` 연산자가 `"StringEquals"`로 설정되어 있는지 확인합니다.

1. **신뢰 정책 업데이트**를 선택하여 종료합니다.

### AWS CLI
<a name="awscli_s3_store_app_data"></a>

1. 클러스터의 OIDC 공급자 URL을 확인합니다. *my-cluster*를 해당 클러스터의 이름으로 바꿉니다. 명령의 출력이 `None`인 경우 [사전 요구 사항](#s3-csi-prereqs)을 검토합니다.

   ```
   aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text
   ```

   예제 출력은 다음과 같습니다.

   ```
   https://oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE
   ```

1. IAM 역할을 생성하여 Kubernetes 서비스 계정에 `AssumeRoleWithWebIdentity` 작업 권한을 부여합니다.

   1. 다음 콘텐츠를 `aws-s3-csi-driver-trust-policy.json`라는 파일에 복사합니다. *111122223333*을 계정 ID로 바꿉니다. *EXAMPLED539D4633E53DE1B71EXAMPLE* 및 *region-code*를 이전 단계에서 반환된 값으로 바꿉니다.

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
              "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
              "StringEquals": {
                "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:kube-system:s3-csi-driver-sa",
                "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
              }
            }
          }
        ]
      }
      ```

   1. 역할을 생성합니다. *AmazonEKS\$1S3\$1CSI\$1DriverRole*를 다른 이름으로 변경할 수 있지만, 그렇게 할 경우 이후 단계에서도 변경해야 합니다.

      ```
      aws iam create-role \
        --role-name AmazonEKS_S3_CSI_DriverRole \
        --assume-role-policy-document file://"aws-s3-csi-driver-trust-policy.json"
      ```

1. 다음 명령을 사용하여 이전에 생성한 IAM 정책을 역할에 연결합니다.

   ```
   aws iam attach-role-policy \
     --policy-arn arn:aws:iam::aws:policy/AmazonS3CSIDriverPolicy \
     --role-name AmazonEKS_S3_CSI_DriverRole
   ```
**참고**  
IAM 정책 `AmazonS3CSIDriverPolicy`는 이전 섹션에서 생성되었습니다.

1. 드라이버를 Amazon EKS 추가 기능으로 설치하는 경우에는 이 단계를 생략합니다. 자체 관리형 드라이버 설치의 경우 생성한 IAM 역할의 ARN으로 주석이 달린 Kubernetes 서비스 계정을 생성합니다.

   1. 다음 콘텐츠를 `mountpoint-s3-service-account.yaml`이라는 파일에 저장합니다. *111122223333*을 계정 ID로 바꿉니다.

      ```
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        labels:
          app.kubernetes.io/name: aws-mountpoint-s3-csi-driver
        name: mountpoint-s3-csi-controller-sa
        namespace: kube-system
        annotations:
          eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/AmazonEKS_S3_CSI_DriverRole
      ```

   1. 클러스터에 Kubernetes 서비스 계정을 생성합니다. Kubernetes 서비스 계정(`mountpoint-s3-csi-controller-sa`)에는 *AmazonEKS\$1S3\$1CSI\$1DriverRole*이라는 이름으로 생성한 IAM 역할이 주석으로 지정되어 있습니다.

      ```
      kubectl apply -f mountpoint-s3-service-account.yaml
      ```
**참고**  
해당 절차에서 플러그인이 배포되면 `s3-csi-driver-sa`라는 서비스 계정을 생성하고 해당 계정을 사용하도록 구성됩니다.

## 3단계: Mountpoint for Amazon S3 CSI 드라이버 설치
<a name="s3-install-driver"></a>

Amazon EKS 추가 기능을 통해 Mountpoint for Amazon S3 CSI 드라이버를 설치할 수 있습니다. 다음 도구를 사용하여 클러스터에 애드온을 추가할 수 있습니다.
+  [eksctl](#eksctl_s3_add_store_app_data) 
+  [AWS Management Console](#console_s3_add_store_app_data) 
+  [AWS CLI](#awscli_s3_add_store_app_data) 

또는 Mountpoint for Amazon S3 CSI 드라이버를 자체 관리형 설치로 설치할 수 있습니다. 자체 관리형 설치 방법에 대한 지침은 GitHub의 [Installation](https://github.com/awslabs/mountpoint-s3-csi-driver/blob/main/docs/install.md#deploy-driver)을 참조하세요.

`v1.8.0`부터 CSI 드라이버의 포드에 대해 허용하도록 테인트를 구성할 수 있습니다. 이렇게 하려면 `node.tolerations`를 사용하여 사용자 지정 테인트 세트를 지정하거나 `node.tolerateAllTaints`를 사용하여 모든 테인트를 허용하도록 지정하세요. 자세한 내용은 Kubernetes 설명서의 [테인트와 허용 오차](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)를 참조하세요.

### eksctl
<a name="eksctl_s3_add_store_app_data"></a>

 **`eksctl`을 사용하여 Amazon S3 CSI 추가 기능 추가** 

다음 명령을 실행합니다. *my-cluster*를 클러스터 이름으로, *111122223333*을 계정 ID로, *AmazonEKS\$1S3\$1CSI\$1DriverRole*을 [앞서 만든 IAM 역할의 이름](#s3-create-iam-role)으로 바꿉니다.

```
eksctl create addon --name aws-mountpoint-s3-csi-driver --cluster my-cluster \
  --service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_S3_CSI_DriverRole --force
```

기존 설정과 충돌하는 *–-force* 옵션과 Amazon EKS 추가 기능 설정을 제거할 경우, Amazon EKS 추가 기능의 업데이트 작업이 실패하고 충돌을 해결하는 데 도움이 되는 오류 메시지가 표시됩니다. 이 옵션을 사용하여 이러한 설정을 덮어쓰기 때문에 이 옵션을 지정하기 전에 Amazon EKS 추가 기능이 관리해야 하는 설정을 관리하지 않는지 확인합니다. 이 설정의 기타 옵션에 대한 자세한 내용은 `eksctl` 설명서의 [추가 기능](https://eksctl.io/usage/addons/)을 참조하세요. Amazon EKS Kubernetes 필드 관리에 대한 자세한 내용은 [Amazon EKS 추가 기능에 대해 사용자 지정할 수 있는 필드 확인](kubernetes-field-management.md) 섹션을 참조하세요.

구성 파일을 통해 `eksctl`을 사용자 지정할 수 있습니다. 자세한 내용은 `eksctl` 설명서의 [구성 값으로 작업하기](https://eksctl.io/usage/addons/#working-with-configuration-values)를 참조하세요. 다음 예제에서는 모든 테인트를 허용하는 방법을 보여줍니다.

```
# config.yaml
...

addons:
- name: aws-mountpoint-s3-csi-driver
  serviceAccountRoleARN: arn:aws:iam::111122223333:role/AmazonEKS_S3_CSI_DriverRole
  configurationValues: |-
    node:
      tolerateAllTaints: true
```

### AWS Management Console
<a name="console_s3_add_store_app_data"></a>

1. [Amazon EKS 콘솔](https://console.aws.amazon.com/eks/home#/clusters)을 엽니다.

1. 좌측 탐색 창에서 **클러스터**를 선택합니다.

1. Mountpoint for Amazon S3 CSI 추가 기능을 구성하려는 클러스터의 이름을 선택합니다.

1. **추가 기능** 탭을 선택합니다.

1. **추가 기능 더 가져오기**를 선택합니다.

1. **추가 기능 선택** 페이지에서 다음을 수행합니다.

   1. **Amazon EKS 추가 기능** 섹션에서 **Mountpoint for Amazon S3 CSI 드라이버** 확인란을 선택합니다.

   1. **다음**을 선택합니다.

1. **선택한 추가 기능 설정 구성** 페이지에서 다음을 수행합니다.

   1. 사용할 **버전**을 선택합니다.

   1. **IAM 역할 선택**에서 Mountpoint for Amazon S3 CSI 드라이버 IAM 정책을 연결한 IAM 역할의 이름을 선택합니다.

   1. (선택사항) **선택적 구성 설정**을 확장한 후 **충돌 해결 방법**을 업데이트하세요. **재정의**를 선택한 경우 기존 추가 기능에 대한 하나 이상의 설정을 Amazon EKS 추가 기능의 설정으로 덮어쓸 수 있습니다. 이 옵션을 사용 설정하지 않고 기존 설정과 충돌이 있는 경우 작업이 실패합니다. 결과 오류 메시지를 사용하여 충돌을 해결할 수 있습니다. 이 옵션을 선택하기 전에 Amazon EKS 추가 기능이 사용자가 자체 관리해야 하는 설정을 관리하지 않는지 확인하세요.

   1. (선택사항) **선택적 구성 설정**을 확장한 후 **구성 값** 필드에서 톨러레이션을 구성합니다.

   1. **다음**을 선택합니다.

1. **검토 및 추가** 페이지에서 **생성**을 선택합니다. 추가 기능 설치가 완료되면 설치한 추가 기능이 표시됩니다.

### AWS CLI
<a name="awscli_s3_add_store_app_data"></a>

 **AWS CLI를 사용하여 Mountpoint for Amazon S3 CSI 추가 기능 추가** 

다음 명령을 실행합니다. *my-cluster*를 클러스터 이름으로, *111122223333*을 계정 ID로, *AmazonEKS\$1S3\$1CSI\$1DriverRole*을 앞서 만든 역할의 이름으로 바꿉니다.

```
aws eks create-addon --cluster-name my-cluster --addon-name aws-mountpoint-s3-csi-driver \
  --service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_S3_CSI_DriverRole
```

`--configuration-values` 플래그와 함께 명령을 사용자 지정할 수 있습니다. 다음 대체 예제는 모든 테인트를 허용하는 방법을 보여줍니다.

```
aws eks create-addon --cluster-name my-cluster --addon-name aws-mountpoint-s3-csi-driver \
  --service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_S3_CSI_DriverRole \
  --configuration-values '{"node":{"tolerateAllTaints":true}}'
```

## 4단계: Mountpoint for Amazon S3 구성
<a name="s3-configure-mountpoint"></a>

대부분의 경우 버킷 이름만 사용하여 Mountpoint for Amazon S3를 구성할 수 있습니다. Mountpoint for Amazon S3 구성에 대한 지침은 GitHub의 [Configuring Mountpoint for Amazon S3](https://github.com/awslabs/mountpoint-s3/blob/main/doc/CONFIGURATION.md)를 참조하세요.

## 5단계: 샘플 애플리케이션 배포
<a name="s3-sample-app"></a>

기존 Amazon S3 버킷의 드라이버에 정적 프로비저닝을 배포할 수 있습니다. 자세한 내용은 GitHub의 [Static provisioning](https://github.com/awslabs/mountpoint-s3-csi-driver/blob/main/examples/kubernetes/static_provisioning/README.md)을 참조하세요.

# Mountpoint for Amazon S3 Amazon EKS 추가 기능 제거
<a name="removing-s3-csi-eks-add-on"></a>

[Mountpoint for Amazon S3 CSI 드라이버](s3-csi.md)를 제거하는 데는 두 가지 옵션이 있습니다.
+  **클러스터에 추가 기능 소프트웨어 보존** – 이 옵션은 모든 설정에 대한 Amazon EKS 관리를 제거합니다. 또한 업데이트를 시작한 후 Amazon EKS가 업데이트를 알리고 Amazon EKS 추가 기능을 자동으로 업데이트하는 기능을 제거합니다. 그러나 클러스터에 추가 기능 소프트웨어는 유지됩니다. 이 옵션을 사용하면 추가 기능을 Amazon EKS 추가 기능이 아닌 자체 관리형 설치 기능으로 만들 수 있습니다. 이 옵션을 사용하면 추가 기능에 대한 가동 중지 시간이 없습니다. 이 절차의 명령은 이 옵션을 사용합니다.
+  **클러스터에서 추가 기능 소프트웨어 완전히 제거(Remove the add-on software entirely from your cluster)** - 클러스터에 종속된 리소스가 없는 경우,에만 클러스터에서 Amazon EKS 추가 기능을 제거하는 것이 좋습니다. 이 옵션을 수행하려면 이 절차에서 사용하는 명령에서 `--preserve`를 삭제합니다.

추가 기능에 연결된 IAM 계정이 있는 경우 IAM 계정은 제거되지 않습니다.

다음 도구를 사용하여 Amazon S3 CSI 애드온을 제거할 수 있습니다:
+  [eksctl](#eksctl_s3_remove_store_app_data) 
+  [AWS Management Console](#console_s3_remove_store_app_data) 
+  [AWS CLI](#awscli_s3_remove_store_app_data) 

## eksctl
<a name="eksctl_s3_remove_store_app_data"></a>

 **`eksctl`을 사용하여 Amazon S3 CSI 추가 기능 제거** 

*my-cluster*를 클러스터 이름으로 바꾸고 다음 명령을 실행합니다.

```
eksctl delete addon --cluster my-cluster --name aws-mountpoint-s3-csi-driver --preserve
```

## AWS Management Console
<a name="console_s3_remove_store_app_data"></a>

1. [Amazon EKS 콘솔](https://console.aws.amazon.com/eks/home#/clusters)을 엽니다.

1. 좌측 탐색 창에서 **클러스터**를 선택합니다.

1. Amazon EBS CSI 추가 기능을 제거할 클러스터의 이름을 선택합니다.

1. **추가 기능** 탭을 선택합니다.

1. **Mountpoint for Amazon S3 CSI 드라이버**를 선택합니다.

1. **** 제거를 선택합니다.

1. **제거: aws-mountpoint-s3-csi-driver** 확인 대화 상자에서 다음을 수행합니다.

   1. 추가 기능에 대한 Amazon EKS의 설정 관리를 중지하려면 **클러스터에 보존**을 선택합니다. 클러스터에 추가 소프트웨어를 유지하려면 이렇게 합니다. 이는 추가 기능의 모든 설정을 스스로 관리할 수 있도록 하기 위한 것입니다.

   1. `aws-mountpoint-s3-csi-driver`을 입력합니다.

   1. **제거**를 선택합니다.

## AWS CLI
<a name="awscli_s3_remove_store_app_data"></a>

 **AWS CLI을 사용하여 Amazon S3 CSI 추가 기능 제거** 

*my-cluster*를 클러스터 이름으로 바꾸고 다음 명령을 실행합니다.

```
aws eks delete-addon --cluster-name my-cluster --addon-name aws-mountpoint-s3-csi-driver --preserve
```

# CSI 볼륨의 스냅샷 기능 활성화
<a name="csi-snapshot-controller"></a>

스냅샷 기능을 사용하면 데이터의 특정 시점 사본을 사용할 수 있습니다. Kubernetes에서 이 기능이 작동하려면 스냅샷을 지원하는 CSI 드라이버(예: Amazon EBS CSI 드라이버)와 CSI 스냅샷 컨트롤러가 모두 필요합니다. 스냅샷 컨트롤러는 Amazon EKS 관리형 추가 기능 또는 자체 관리형 설치로 사용할 수 있습니다.

CSI 스냅샷 컨트롤러 사용 시 고려할 사항이 몇 가지 있습니다.
+ 스냅샷 컨트롤러는 스냅샷 기능이 있는 CSI 드라이버와 함께 설치해야 합니다. Amazon EBS CSI 드라이버 설치 지침은 [Amazon EBS와 함께 Kubernetes 볼륨 스토리지 사용](ebs-csi.md)을 참조하세요.
+ Kubernetes는 프로비저너 `kubernetes.io/aws-ebs`에 `StorageClass`를 사용하는 Amazon EBS와 같이 CSI 마이그레이션을 통해 제공되는 볼륨의 스냅샷을 지원하지 않습니다. CSI 드라이버 프로비저너 `ebs.csi.aws.com`를 참조하는 `StorageClass`로 볼륨을 생성해야 합니다.
+ Amazon EKS Auto Mode에는 스냅샷 컨트롤러가 포함되지 않습니다. EKS Auto Mode의 스토리지 기능은 스냅샷 컨트롤러와 호환됩니다.

Amazon EKS 관리형 추가 기능을 통해 CSI 스냅샷 컨트롤러를 설치하는 것이 좋습니다. 이 추가 기능에는 Amazon EKS에서 스냅샷을 생성하고 관리하는 데 필요한 사용자 지정 리소스 정의(CRDs)가 포함되어 있습니다. Amazon EKS 추가 기능을 클러스터에 추가하려면 [Amazon EKS 추가 기능 생성](creating-an-add-on.md) 섹션을 참조하세요. Amazon EKS 추가 기능에 대한 자세한 내용은 [Amazon EKS 추가 기능](eks-add-ons.md) 섹션을 참조하세요.

또는 CSI 스냅샷 컨트롤러의 자체 관리형 설치를 원하는 경우 GitHub의 업스트림 Kubernetes `external-snapshotter`에서 [Usage](https://github.com/kubernetes-csi/external-snapshotter/blob/master/README.md#usage)를 참조하세요.