

 **協助改進此頁面** 

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

若要為本使用者指南貢獻內容，請點選每個頁面右側面板中的**在 GitHub 上編輯此頁面**連結。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 Elastic Fabric Adapter 在 Amazon EKS 上執行機器學習訓練
<a name="node-efa"></a>

本主題會說明如何將 Elastic Fabric Adapter (EFA) 與部署在 Amazon EKS 叢集中的 Pod 整合。Elastic Fabric Adapter (EFA) 是 Amazon EC2 執行個體的網路介面，可讓您在 AWS上大規模執行需要高層級節點間通訊的應用程式。其自訂的作業系統略過硬體介面可增強執行個體間通訊的效能，這對於擴展這些應用程式至關重要。藉由 EFA，使用訊息傳遞介面 (MPI) 的高效能運算 (HPC) 應用程式和使用 NVIDIA 集體通訊程式庫 (NCCL) 的機器學習 (ML) 應用程式可擴展到數千個 CPU 或 GPU。因此，您可以使用 AWS 雲端的隨需彈性和彈性，獲得現場部署 HPC 叢集的應用程式效能。將 EFA 與 Amazon EKS 叢集上執行的應用程式整合，可減少完成大規模分散式訓練工作負載的時間，而無需在叢集中新增其他執行個體。如需 EFA 的詳細資訊，請參閱 [Elastic Fabric Adapter](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 數量和記憶體數量。對於每張網路卡您最多可以指派一個 EFA。EFA 視為網路介面。若要查看具有 EFA 的每個執行個體類型可使用多少 EFA，請參閱《*Amazon EC2 使用者指南*》中的[網路卡](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#network-cards)清單。

## EFA 和僅限 EFA 介面
<a name="efa-only-interfaces"></a>

*Elastic Fabric Adapter (EFA)* 是一種網路介面，結合了彈性網路轉接器 (ENA) 和 OS-bypass 介面的功能，採用 AWS 可擴展可靠資料包 (SRD) 通訊協定。EFA 功能可讓應用程式直接與硬體通訊，以實現低延遲傳輸。您可以選擇只使用*僅限 EFA* 介面存取 EFA 功能，以限制與相同可用區域內介面的通訊。

若要建立具有僅限 EFA 介面的節點，您必須使用自訂 EC2 啟動範本，並將 `InterfaceType` 設定為 `efa-only`。在自訂啟動範本中，您無法將網路卡 `0` 設定為僅限 EFA 介面，因為這是 EC2 執行個體的主要網路卡和網路介面。對於僅限 EFA 介面，您必須使用 VPC CNI 版本 `1.18.5` 或更新版本。如果您使用的是 Amazon Linux 2，則僅限 EfA 介面的 ami 版本必須是 `v20240928` 或更新版本。

下列程序會引導您使用 `eksctl` 建立 EKS 叢集，而該叢集具有 nVidia GPU 和 EFA 介面的節點。您無法使用 `eksctl` 來建立使用僅限 EFA 介面的節點和節點群組。

## 先決條件
<a name="efa-prereqs"></a>
+ 現有 Amazon EKS 叢集。若您尚未擁有現有叢集，請使用 [開始使用 Amazon EKS](getting-started.md) 建立一個。您的叢集必須部署在具有至少一個私有子網路的 VPC 中，其中具有足夠的可用 IP 地址，以便部署節點。私有子網路必須具有外部裝置 (例如 NAT 閘道) 所提供的傳出網際網路存取權。

  如果計劃使用 `eksctl` 來建立您的節點群組，`eksctl` 也會為您建立叢集。
+ 在您的裝置或 AWS CloudShell 上安裝和設定的 AWS 命令列界面 (AWS CLI) 版本 `1.27.160` `2.12.3`或更新版本。若要檢查您目前的版本，請使用 `aws --version | cut -d / -f2 | cut -d ' ' -f1`。適用於 macOS 的 `yum`、 `apt-get`或 Homebrew 等套件管理員通常是最新版本 CLI AWS 後面的幾個版本。若要安裝最新版本，請參閱《 * AWS 命令列界面使用者指南*》中的使用 aws 設定[安裝](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) 和 快速組態。 [https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)安裝在 AWS CloudShell 中的 AWS CLI 版本也可能是最新版本後面的幾個版本。若要更新它，請參閱《CloudShell [AWS 使用者指南》中的將 CLI 安裝到您的主目錄](https://docs.aws.amazon.com/cloudshell/latest/userguide/vm-specs.html#install-cli-software)。 * AWS CloudShell *
+ `kubectl` 命令列工具安裝在您的裝置或 AWS CloudShell 上。版本可以與您的叢集 Kubernetes 版本相同，或是為最多比該版本更舊一版或更新一版的次要版本。例如，如果您的叢集版本為 `1.29`，則可以搭配使用 `kubectl` `1.28`、`1.29` 或 `1.30` 版。若要安裝或升級 `kubectl`，請參閱 [設定 `kubectl` 和 `eksctl`](install-kubectl.md)。
+ 在啟動支援多個 Elastic Fabric Adapter 的工作節點 (例如 `p4d` 或 `p5`) 之前，您必須先安裝版本 `1.7.10` 或更新版本的 Kubernetes 專用 Amazon VPC CNI 外掛程式。如需有關更新 Kubernetes 專用 Amazon VPC CNI 外掛程式版本的詳細資訊，請參閱 [使用 Amazon VPC CNI 將 IP 指派給 Pod](managing-vpc-cni.md)。
+ 若為 p6-b200 執行個體，您必須使用 EFA 裝置外掛程式版本 v0.5.6 或更新版本。

**重要**  
搭配 Kubernetes 採用 EFA 所需的一項重要考量，就是將大型頁面作為叢集中的資源進行設定和管理。如需詳細資訊，請參閱 Kubernetes 文件中的[管理大型頁面](https://kubernetes.io/docs/tasks/manage-hugepages/scheduling-hugepages/)。已安裝 EFA 驅動程式的 Amazon EC2 執行個體會預先分配 5128 2MiB 大型頁面，您可以請求作為資源在任務規格中耗用。

## 建立節點群組
<a name="efa-create-nodegroup"></a>

下列程序可協助您建立具有 EFA 介面和 GPUDirect RDMA 之 `p4d.24xlarge` 支援的節點群組，並針對使用 EFA 的多節點 NCCL 效能執行範例 NVIDIA 集體通訊程式庫 (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. 判斷您想要部署的執行個體類型所在的哪一個 Availability Zone (可用區域) 為可用。在本教學課程中，會使用`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
   ```

   請注意傳回的 Availability Zone (可用區域) 以供稍後步驟使用。將節點部署到叢集時，您的 VPC 必須在輸出中傳回的其中一個 Availability Zone (可用區域) 中具有可用 IP 位址的子網路。

1. 使用 `eksctl` 建立節點群組。您需要在裝置`0.215.0`或 AWS CloudShell 上安裝版本 或更新版本的`eksctl`命令列工具。如需有關安裝或更新 `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，`eksctl` 會在使用 Amazon Linux 2. 時，為您自動在每個執行個體上安裝 NVIDIA Kubernetes 裝置外掛程式。Bottlerocket 不需要執行此操作，因為 NVIDIA 裝置外掛程式內建於 Bottlerocket 的 EKS NVIDIA 變體中。在節點群組組態中將 `efaEnabled` 設定為 `true` 時，`eksctl` 也會自動在節點上部署 EFA 裝置外掛程式。

### 搭配 EFA 使用 Bottlerocket
<a name="efa-bottlerocket"></a>

Bottlerocket AMI 版本 1.28.0 及更新版本包含對 EFA 的官方支援。若要將 Bottlerocket 用於已啟用 EFA 的節點，請在您的組態中指定 `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 巨型分頁的數量。在此範例中，3000 表示 3000 \$1 2Mi = 6000Mi 的巨型分頁。

### 驗證 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
   ...
   ```

   在此，EFA 裝置外掛程式 DaemonSet 會在兩個節點上執行。兩者狀態皆為就緒及可用。

1. 接著，驗證 DaemonSet 建立的 Pod：

   ```
   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 裝置外掛程式 Pod 處於「執行中」狀態，確認外掛程式已成功部署並可運作。

1. 驗證資源註冊：

   您可以描述節點，進而確認 `vpc.amazonaws.com/efa` 資源已向 kubelet 註冊：

   ```
   kubectl describe nodes
   ```

   如果 EFA 資源已正確註冊，您即會看到該資源列於節點的容量和可配置資源下。例如：

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

   此輸出會確認節點可辨識 EFA 資源，使其可供請求它的 Pod 使用。

## (選用) 測試 EFA 的效能
<a name="efa-application"></a>

建議您測試 EFA 設定。您可以在 GitHub 上的 `aws-samples/awsome-distributed-training` 儲存庫中使用 [NCCL 測試](https://github.com/aws-samples/awsome-distributed-training/tree/main/micro-benchmarks/nccl-tests)。[NCCL 測試](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. 執行多節點 NCCL 效能測試，以驗證 GPUDirectRDMA/EFA：

   要透過 EFA 使用 GPUDirectRDMA 驗證 NCCL 效能，請執行標準 NCCL 效能測試。如需詳細資訊，請參閱 GitHub 上的官方 [NCCL 測試](https://github.com/NVIDIA/nccl-tests.git)儲存庫。

   請完成以下步驟，以執行雙節點 NCCL 效能測試。在 NCCL 測試任務範例中，每個工作者請求八個 GPU、`hugepages-2Mi` 的 5210Mi、四個 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 測試 MPIJob：

      套用資訊清單，以提交 `MPIJob`。這將建立兩個 `p5.48xlarge` Amazon EC2 執行個體。

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

      範例輸出如下。

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

   1. 確認任務已啟動 Pod：

      檢視您的執行中 Pod。

      ```
      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 運算子會建立啟動器 Pod 和 2 個工作者 Pod (每個節點上有一個)。

   1. 使用日誌確認任務已成功執行：

      檢視 `nccl-tests-launcher` Pod 的日誌。使用輸出的值取代 *nbql9*。

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

如果測試成功完成，則您可以部署使用 Nvidia Collective Communication Library 的應用程式。