

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

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

# Elastic Fabric Adapter를 사용한 Amazon EKS에서 기계 학습 훈련 실행
<a name="node-efa"></a>

이 주제에서는 Amazon EKS 클러스터에 배포된 포드와 Elastic Fabric Adapter(EFA)를 통합하는 방법에 대해 설명합니다. Elastic Fabric Adapter(EFA)는 Amazon EC2 인스턴스용 네트워크 인터페이스로, AWS에서 대규모로 높은 수준의 노드 간 통신을 필요로 하는 애플리케이션을 실행할 수 있도록 지원합니다. 맞춤형으로 구축된 운영 체제 바이패스 하드웨어 인터페이스는 인스턴스 간 통신의 성능을 향상시켜 애플리케이션을 확장하는 데 매우 중요합니다. EFA를 사용하면 메시지 전달 인터페이스(MPI)를 사용하는 고성능 컴퓨팅(HPC) 애플리케이션과 NVIDIA Collective Communications Library(NCCL)를 사용하는 기계 학습(ML) 애플리케이션을 수천 개의 CPU 또는 GPU로 확장할 수 있습니다. 따라서 온프레미스 HPC 클러스터의 애플리케이션 성능을 AWS 클라우드의 온디맨드 탄력성과 유연성을 통해 실현할 수 있습니다. Amazon EKS 클러스터에서 실행되는 애플리케이션과 EFA를 통합하면 클러스터에 인스턴스를 추가하지 않고도 대규모 분산 훈련 워크로드를 완료하는 데 걸리는 시간을 줄일 수 있습니다. EFA에 대한 자세한 내용은 [Elastic Fabric Adapter(EFA)](https://aws.amazon.com/hpc/efa/) 섹션을 참조하세요.

## EFA를 사용한 인스턴스 유형
<a name="efa-instances"></a>

* AWS EFA Kubernetes 디바이스 플러그인*은 EFA가 있는 모든 Amazon EC2 인스턴스 유형을 지원합니다. EFA가 있는 모든 인스턴스 유형 목록을 보려면 **Amazon EC2 사용 설명서의 [지원되는 인스턴스 유형](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa.html#efa-instance-types)을 참조하세요. 그러나 ML 애플리케이션을 빠르게 실행하려면 인스턴스에 EFA 외에 nVidia GPU, [AWS Inferentia](https://aws.amazon.com/machine-learning/inferentia/) 칩 또는 [AWS Trainium](https://aws.amazon.com/machine-learning/trainium/) 칩과 같은 하드웨어 가속 칩이 있는 것이 좋습니다. 하드웨어 가속 칩과 EFA가 있는 인스턴스 유형 목록을 보려면 **Amazon EC2 사용 설명서의 [가속 컴퓨팅](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa.html#efa-instance-types)을 참조하세요.

인스턴스 유형을 비교하여 선택할 때는 해당 인스턴스 유형에 사용할 수 있는 EFA 네트워크 카드 수뿐만 아니라 가속기 카드 수, CPU 사용량, 메모리 크기도 고려하세요. 네트워크 카드당 최대 1개의 EFA를 할당할 수 있습니다. EFA는 네트워크 인터페이스 수 계산에 포함됩니다. EFA가 있는 각 인스턴스 유형에 사용할 수 있는 EFA 수를 확인하려면 **Amazon EC2 사용 설명서의 [네트워크 카드](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#network-cards) 목록을 참조하세요.

## EFA 및 EFA-only 인터페이스
<a name="efa-only-interfaces"></a>

*Elastic Fabric Adapter(EFA)*는 AWS Scalable Reliable Datagram(SRD) 프로토콜로 구동되는 Elastic Network Adapter(ENA)와 OS 바이패스 인터페이스의 기능을 결합하는 네트워크 인터페이스입니다. EFA 기능을 사용하면 애플리케이션이 지연 시간이 짧은 전송을 위해 하드웨어와 직접 통신할 수 있습니다. *EFA-only* 인터페이스를 사용하여 EFA 기능에만 액세스하도록 선택하여 동일한 가용 영역 내의 인터페이스로 통신을 제한할 수 있습니다.

EFA 전용 인터페이스를 가질 수 있는 노드를 생성하려면 사용자 지정 EC2 시작 템플릿을 사용하고 `InterfaceType`을 `efa-only`로 설정해야 합니다. 사용자 지정 시작 템플릿에서는 네트워크 카드 `0`를 EFA 전용 인터페이스로 설정할 수 없습니다. EC2 인스턴스의 기본 네트워크 카드 및 네트워크 인터페이스이기 때문입니다. EFA 전용 인터페이스의 경우 VPC CNI 버전 `1.18.5` 이상을 사용해야 합니다. Amazon Linux 2를 사용하는 경우 EfA 전용 인터페이스의 ami 버전은 `v20240928` 이상이어야 합니다.

다음 절차는 nVidia GPU 및 EFA 인터페이스가 있는 노드가 있는 `eksctl`로 EKS 클러스터를 생성하는 방법을 안내합니다. `eksctl`를 사용하여 EFA-only 인터페이스를 사용하는 노드 및 노드 그룹을 생성할 수 없습니다.

## 사전 조건
<a name="efa-prereqs"></a>
+ 기존 Amazon EKS 클러스터. 기존 클러스터가 없는 경우 [Amazon EKS 시작하기](getting-started.md)를 사용하여 클러스터를 생성합니다. 노드를 배포할 수 있는 충분한 IP 주소가 있는 프라이빗 서브넷이 하나 이상 있는 VPC에 클러스터를 배포해야 합니다. 프라이빗 서브넷에는 NAT 게이트웨이와 같은 외부 디바이스에서 제공하는 아웃바운드 인터넷 액세스가 있어야 합니다.

  `eksctl`을 사용하여 노드 그룹을 생성하려는 경우 `eksctl`이 클러스터를 생성할 수도 있습니다.
+ 장치에 설치 및 구성된 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) 부분을 참조하세요.
+ `p4d` 또는 `p5`와 같이 여러 Elastic Fabric Adapter를 지원하는 워커 노드를 시작하기 전에 Kubernetes용 Amazon VPC CNI 플러그인 버전 `1.7.10` 이상이 설치되어 있어야 합니다. Kubernetes용 Amazon VPC CNI 플러그인 버전 업데이트에 대한 자세한 내용은 [Amazon VPC CNI를 통해 포드에 IP 할당](managing-vpc-cni.md) 섹션을 참조하세요.
+ p6-b200 인스턴스의 경우 EFA 디바이스 플러그인 버전 v0.5.6 이상을 사용해야 합니다.

**중요**  
Kubernetes에 EFA를 도입하는 데 필요한 중요한 고려 사항은 Huge Page를 클러스터에서 리소스로 구성하고 관리하는 것입니다. 자세한 내용은 Kubernetes 문서의 [대용량 페이지 관리(Manage Huge Pages)](https://kubernetes.io/docs/tasks/manage-hugepages/scheduling-hugepages/)를 참조하세요. EFA 드라이버가 설치된 Amazon EC2 인스턴스는 5128 2MiB Huge Page를 미리 할당하며 이를 작업 사양에 따라 사용할 리소스로 요청할 수 있습니다.

## 노드 그룹 생성
<a name="efa-create-nodegroup"></a>

다음 절차를 따르면 EFA 인터페이스 및 GPUDirect RDMA를 사용하여 `p4d.24xlarge` 지원 노드 그룹으로 노드 그룹을 생성하고, EFA를 사용하여 다중 노드 NCCL 성능에 대한 예시 NVIDIA Collective Communications Library(NCCL) 테스트를 실행하는 데 도움이 됩니다. 이 예제는 EFA를 사용하는 Amazon EKS에 대한 분산 딥 러닝 훈련용 템플릿으로 사용할 수 있습니다.

1. 노드를 배포하려는 AWS 리전에서 사용할 수 있는 EFA를 지원하는 Amazon EC2 인스턴스 유형을 결정합니다. *region-code*를 노드 그룹을 배포할 AWS 리전으로 바꿉니다.

   ```
   aws ec2 describe-instance-types --region region-code \
       --filters Name=network-info.efa-supported,Values=true \
       --query "InstanceTypes[*].[InstanceType]" --output text
   ```

   노드를 배포할 때 배포하려는 인스턴스 유형은 클러스터가 속한 AWS 리전에서 사용할 수 있어야 합니다.

1. 배포하려는 인스턴스 유형이 사용 가능한 가용 영역을 결정합니다. 이 자습서에서는 `p5.48xlarge` 인스턴스 유형이 사용되며 이전 단계에서 지정한 AWS 리전에 대한 출력으로 반환되어야 합니다. 프로덕션 클러스터에 노드를 배포할 때 *p5.48xlarge*를 이전 단계에서 반환된 인스턴스 유형으로 바꿉니다.

   ```
   aws ec2 describe-instance-type-offerings --region region-code \
       --location-type availability-zone --filters Name=instance-type,Values=p4d.24xlarge,p5.48xlarge \
       --query 'InstanceTypeOfferings[*].Location' --output text
   ```

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

   ```
   us-west-2a    us-west-2c    us-west-2b
   ```

   이후 단계에서 사용하기 위해 반환된 가용 영역을 기록해 둡니다. 클러스터에 노드를 배포할 때 VPC에는 출력에 반환된 가용 영역 중 하나에 사용 가능한 IP 주소가 있는 서브넷이 있어야 합니다.

1. `eksctl`을 사용하여 노드 그룹을 생성합니다. 장치에 설치된 `eksctl` 명령줄 도구의 버전 `0.215.0` 이상 또는 AWS CloudShell이 필요합니다. `eksctl`을 설치 또는 업그레이드하려면 `eksctl` 설명서에서 [설치](https://eksctl.io/installation)를 참조하세요.

   1. 다음 콘텐츠를 *efa-cluster.yaml*라는 파일에 복사합니다. 예제 값을 사용자의 값으로 바꿉니다. `p5.48xlarge`을(를) 다른 인스턴스로 바꿀 수 있지만, 그렇게 할 경우 `availabilityZones`의 값이 1단계에서 인스턴스 유형에 대해 반환된 가용 영역이어야 합니다.

      ```
      apiVersion: eksctl.io/v1alpha5
      kind: ClusterConfig
      
      metadata:
        name: my-efa-cluster
        region: region-code
        version: "1.XX"
      
      iam:
        withOIDC: true
      
      availabilityZones: ["us-west-2a", "us-west-2c"]
      
      managedNodeGroups:
        - name: my-efa-ng
          instanceType: p5.48xlarge
          minSize: 1
          desiredCapacity: 2
          maxSize: 3
          availabilityZones: ["us-west-2a"]
          volumeSize: 300
          privateNetworking: true
          efaEnabled: true
      ```

   1. 기존 클러스터에 관리형 노드 그룹을 생성합니다.

      ```
      eksctl create nodegroup -f efa-cluster.yaml
      ```

      기존 클러스터가 없는 경우 다음 명령을 실행하여 클러스터와 노드 그룹을 생성할 수 있습니다.

      ```
      eksctl create cluster -f efa-cluster.yaml
      ```
**참고**  
이 예제에 사용된 인스턴스 유형에는 GPU가 있으므로 Amazon Linux 2를 사용할 때 `eksctl`은 각 인스턴스에 NVIDIA Kubernetes 디바이스 플러그인을 자동으로 설치합니다. NVIDIA 디바이스 플러그인이 Bottlerocket의 EKS NVIDIA 버전에 내장되어 있으므로 Bottlerocket의 경우 이 작업이 필요하지 않습니다. 노드 그룹 구성에서 `efaEnabled`가 `true`로 설정된 경우 `eksctl`은 노드에 EFA 디바이스 플러그인을 자동으로 배포합니다.

### EFA와 함께 Bottlerocket 사용
<a name="efa-bottlerocket"></a>

Bottlerocket AMI 버전 1.28.0 이상에는 EFA에 대한 공식 지원이 포함되어 있습니다. EFA 지원 노드에 Bottlerocket을 사용하려면 구성에 `amiFamily: Bottlerocket`을 지정합니다. 사용자 지정 AMI ID를 사용해야 하는 경우 `nodeGroups` 대신 표준 `managedNodeGroups`를 사용해야 합니다.

다음은 구성의 예입니다.

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

metadata:
  name: my-efa-bottlerocket-cluster
  region: region-code
  version: "1.XX"

iam:
  withOIDC: true

availabilityZones: ["us-west-2a", "us-west-2c"]

managedNodeGroups:
  - name: my-efa-bottlerocket-ng
    instanceType: p5.48xlarge
    minSize: 1
    desiredCapacity: 2
    maxSize: 3
    availabilityZones: ["us-west-2a"]
    volumeSize: 300
    privateNetworking: true
    efaEnabled: true
    amiFamily: Bottlerocket
    bottlerocket:
      enableAdminContainer: true
      settings:
        kernel:
          sysctl:
            "vm.nr_hugepages": "3000"  # Configures 3000 * 2Mi = 6000Mi hugepages
```

위의 `vm.nr_hugepages` sysctl 설정은 2Mi HugePages 수를 구성합니다. 이 예제에서 3000은 3000 \$1 2Mi = 6000Mi HugePages를 의미합니다.

### EFA 디바이스 플러그인 설치 확인
<a name="verify-efa-device-plugin"></a>

`efaEnabled: true`로 노드 그룹을 생성하면 `eksctl`이 자동으로 EFA Kubernetes 디바이스 플러그인을 배포합니다. 디바이스 플러그인이 설치되어 제대로 작동하는지 확인할 수 있습니다.

1. DaemonSet 상태를 확인합니다.

   ```
   kubectl get daemonsets -n kube-system
   ```

   샘플 출력:

   ```
   NAME                                  DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
   aws-efa-k8s-device-plugin-daemonset   2         2         2       2            2           <none>          6m16s
   ...
   ```

   여기에서는 2개의 노드에서 EFA 디바이스 플러그인 DaemonSet가 실행되고 있습니다. 둘 다 READY 및 AVAILABLE입니다.

1. 다음으로 DaemonSet에서 생성된 포드를 확인합니다.

   ```
   kubectl get pods -n kube-system -l name=aws-efa-k8s-device-plugin
   ```

   샘플 출력:

   ```
   NAME                                        READY   STATUS    RESTARTS   AGE
   aws-efa-k8s-device-plugin-daemonset-d68bs   1/1     Running   0          6m16s
   aws-efa-k8s-device-plugin-daemonset-w4l8t   1/1     Running   0          6m16s
   ```

   EFA 디바이스 플러그인 포드가 실행 중 상태이므로 플러그인이 성공적으로 배포되고 작동하고 있는 것입니다.

1. 리소스 등록을 확인합니다.

   노드를 설명하여 `vpc.amazonaws.com/efa` 리소스가 kubelet에 등록되었는지 확인할 수 있습니다.

   ```
   kubectl describe nodes
   ```

   EFA 리소스가 제대로 등록되면 노드의 용량 및 할당 가능한 리소스 아래에 해당 리소스가 나열됩니다. 예제:

   ```
   Capacity:
     ...
     vpc.amazonaws.com/efa:  4
   Allocatable:
     ...
     vpc.amazonaws.com/efa:  4
   ```

   이 출력은 노드가 EFA 리소스를 인식하여 이를 요청하는 포드에서 사용할 수 있음을 확인합니다.

## (선택사항) EFA의 성능 테스트
<a name="efa-application"></a>

EFA 설정을 테스트하는 것이 좋습니다. GitHub의 `aws-samples/awsome-distributed-training` 리포지토리에서 [NCCL Tests](https://github.com/aws-samples/awsome-distributed-training/tree/main/micro-benchmarks/nccl-tests)를 사용할 수 있습니다. [NCCL Tests](https://github.com/NVIDIA/nccl-tests)는 NVIDIA Collective Communication Library를 사용하여 네트워크 성능을 평가합니다. 다음 단계는 Amazon EKS에서 NCCL 테스트를 제출합니다.

1. Kubeflow MPI 연산자 배포

   NCCL 테스트를 위해 Kubeflow MPI 연산자를 적용할 수 있습니다. MPI 연산자를 사용하면 Kubernetes에서 Allreduce 스타일의 분산 훈련을 쉽게 실행할 수 있습니다. 자세한 내용은 GitHub에서 [MPI 연산자](https://github.com/kubeflow/mpi-operator)를 참조하세요.

1. GPUDirectRDMA/EFA 검증을 위한 다중 노드 NCCL 성능 테스트 실행

   EFA를 통한 GPUDirectRDMA를 사용하여 NCCL 성능을 검증하려면 표준 NCCL 성능 테스트를 실행합니다. 자세한 내용은 GitHub에서 공식 [NCCL-Tests](https://github.com/NVIDIA/nccl-tests.git) 리포지토리를 참조하세요.

   2개 노드 NCCL 성능 테스트를 실행하려면 다음 단계를 완료합니다. 예제 NCCL 테스트 작업에서 각 작업자는 8개의 GPU, 5210Mi의 `hugepages-2Mi`, 4개의 EFA, 8000Mi 메모리를 요청합니다. 이는 실질적으로 각 작업자가 `p5.48xlarge` 인스턴스의 리소스를 모두 사용한다는 것을 의미합니다.

   1. MPIJob 매니페스트 생성:

      다음을 `nccl-tests.yaml`이라는 파일에 복사합니다.

      ```
      apiVersion: kubeflow.org/v2beta1
      kind: MPIJob
      metadata:
        name: nccl-tests
      spec:
        runPolicy:
          cleanPodPolicy: Running
          backoffLimit: 20
        slotsPerWorker: 8
        mpiReplicaSpecs:
          Launcher:
            replicas: 1
            template:
               spec:
                restartPolicy: OnFailure
                containers:
                - image: public.ecr.aws/hpc-cloud/nccl-tests:latest
                  imagePullPolicy: IfNotPresent
                  name: test-nccl-launcher
                  env:
                   - name: PATH
                     value: $PATH:/opt/amazon/efa/bin:/usr/bin
                  command:
                  - /opt/amazon/openmpi/bin/mpirun
                  - --allow-run-as-root
                  - --tag-output
                  - -np
                  - "16"
                  - -N
                  - "8"
                  - --bind-to
                  - none
                  - -x
                  - PATH
                  - -x
                  - LD_LIBRARY_PATH
                  - -x
                  - NCCL_DEBUG=INFO
                  - -x
                  - NCCL_BUFFSIZE=8388608
                  - -x
                  - NCCL_P2P_NET_CHUNKSIZE=524288
                  - -x
                  - NCCL_TUNER_PLUGIN=/opt/amazon/ofi-nccl/lib/x86_64-linux-gnu/libnccl-ofi-tuner.so
                  - --mca
                  - pml
                  - ^cm,ucx
                  - --mca
                  - btl
                  - tcp,self
                  - --mca
                  - btl_tcp_if_exclude
                  - lo,docker0,veth_def_agent
                  - /opt/nccl-tests/build/all_reduce_perf
                  - -b
                  - "8"
                  - -e
                  - "16G"
                  - -f
                  - "2"
                  - -g
                  - "1"
                  - -c
                  - "1"
                  - -n
                  - "100"
          Worker:
            replicas: 2
            template:
              spec:
                nodeSelector:
                  node.kubernetes.io/instance-type: "p5.48xlarge"
                containers:
                - image: public.ecr.aws/hpc-cloud/nccl-tests:latest
                  imagePullPolicy: IfNotPresent
                  name: nccl-tests-worker
                  volumeMounts:
                  - name: shmem
                    mountPath: /dev/shm
                  resources:
                    limits:
                      nvidia.com/gpu: 8
                      hugepages-2Mi: 5120Mi
                      vpc.amazonaws.com/efa: 32
                      memory: 32000Mi
                    requests:
                      nvidia.com/gpu: 8
                      hugepages-2Mi: 5120Mi
                      vpc.amazonaws.com/efa: 32
                      memory: 32000Mi
                volumes:
                - name: shmem
                  hostPath:
                    path: /dev/shm
      ```

   1. NCCL-test MPIJob을 적용합니다:

      매니페스트를 적용하여 `MPIJob`을 제출합니다. 그러면 두 `p5.48xlarge` Amazon EC2 인스턴스가 생성됩니다.

      ```
      kubectl apply -f nccl-tests.yaml
      ```

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

      ```
      mpijob.kubeflow.org/nccl-tests created
      ```

   1. 작업이 포드를 시작했는지 확인

      실행 중인 포드를 봅니다.

      ```
      kubectl get pods
      ```

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

      ```
      NAME                             READY   STATUS     RESTARTS   AGE
      nccl-tests-launcher-nbql9    0/1     Init:0/1   0          2m49s
      nccl-tests-worker-0          1/1     Running    0          2m49s
      nccl-tests-worker-1          1/1     Running    0          2m49s
      ```

      MPI 연산자는 런처 포드와 작업자 포드 2개(각 노드에 하나씩)를 생성합니다.

   1. 로그를 사용하여 작업이 성공적으로 실행되고 있는지 확인

      `nccl-tests-launcher` 포드에 대한 로그를 확인합니다. *nbql9*를 출력된 값과 바꿉니다.

      ```
      kubectl logs -f nccl-tests-launcher-nbql9
      ```

테스트가 성공적으로 완료되면 Nvidia Collective Communication Library를 사용하는 애플리케이션을 배포할 수 있습니다.