

 **協助改進此頁面** 

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

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

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

# 將 AWS Inferentia 執行個體與 Amazon EKS 搭配使用以進行Machine Learning
<a name="inferentia-support"></a>

本主題描述了如何建立 Amazon EKS 叢集，其中具有執行 [Amazon EC2 Inf1](https://aws.amazon.com/ec2/instance-types/inf1/) 執行個體的節點，以及 (選用) 如何部署範例應用程式。Amazon EC2 Inf1 執行個體採用 [AWS Inferentia](https://aws.amazon.com/machine-learning/inferentia/) 晶片，由 自訂， AWS 可在雲端提供高效能和最低成本的推論。機器學習模型使用 [AWS Neuron](https://aws.amazon.com/machine-learning/neuron/) 部署到容器，這是一個專門的軟體開發套件 (SDK)，由編譯器、執行時間和分析工具組成，可最佳化 Inferentia 晶片的機器學習推論效能。 AWS Neuron 支援熱門的機器學習架構，例如 TensorFlow、PyTorch 和 MXNet。

**注意**  
Neuron 裝置邏輯 ID 必須是連續的。如果請求多個 Neuron 裝置的 Pod 已排程在某個 `inf1.6xlarge` 或 `inf1.24xlarge` 執行個體類型 (具有多個 Neuron 裝置) 上，則如果 Kubernetes 排程器選取非連續的裝置 ID，該 Pod 將無法啟動。如需詳細資訊，請參閱 GitHub 上的[裝置邏輯 ID 必須是連續的](https://github.com/aws/aws-neuron-sdk/issues/110)。

## 先決條件
<a name="inferentia-prerequisites"></a>
+ 將 `eksctl` 安裝在您的電腦上。如果您尚未安裝，請參閱 `eksctl` 文件中的[安裝](https://eksctl.io/installation)一節。
+ 將 `kubectl` 安裝在您的電腦上。如需詳細資訊，請參閱[設定 `kubectl` 和 `eksctl`](install-kubectl.md)。
+ (選用) 將 `python3` 安裝在您的電腦上。如果您尚未安裝，請參閱 [Python 下載](https://www.python.org/downloads/)以取得安裝指示。

## 建立 叢集
<a name="create-cluster-inferentia"></a>

1. 建立具有 Inf1 Amazon EC2 執行個體之節點的叢集。您可以使用任何 [Inf1 執行個體類型](https://aws.amazon.com/ec2/instance-types/inf1/)取代 *inf1.2xlarge*。`eksctl` 公用程式偵測到您正在啟動具有 `Inf1` 執行個體類型的節點群組，並將使用 Amazon EKS 最佳化加速 Amazon Linux AMI 之一來啟動您的節點。
**注意**  
您無法搭配 TensorFlow Serving 使用[服務帳戶的 IAM 角色](iam-roles-for-service-accounts.md)。

   ```
   eksctl create cluster \
       --name inferentia \
       --region region-code \
       --nodegroup-name ng-inf1 \
       --node-type inf1.2xlarge \
       --nodes 2 \
       --nodes-min 1 \
       --nodes-max 4 \
       --ssh-access \
       --ssh-public-key your-key \
       --with-oidc
   ```
**注意**  
請注意下列輸出行的值。它將用於稍後的 (選用) 步驟。

   ```
   [9]  adding identity "arn:aws: iam::111122223333:role/eksctl-inferentia-nodegroup-ng-in-NodeInstanceRole-FI7HIYS3BS09" to auth ConfigMap
   ```

   使用`Inf1`執行個體啟動節點群組時， `eksctl`會自動安裝 AWS Neuron Kubernetes 裝置外掛程式。這個外掛程式會將 Neuron 裝置做為系統資源公告給 Kubernetes 排程器，如此就能由容器請求。除了預設 Amazon EKS 節點 IAM 政策之外，還會新增 Amazon S3 唯讀存取政策，以便稍後步驟介紹的範例應用程式可以從 Amazon S3 載入訓練過的模型。

1. 請確保所有的 Pod 都已正確啟動。

   ```
   kubectl get pods -n kube-system
   ```

   縮寫輸出：

   ```
   NAME                                   READY   STATUS    RESTARTS   AGE
   [...]
   neuron-device-plugin-daemonset-6djhp   1/1     Running   0          5m
   neuron-device-plugin-daemonset-hwjsj   1/1     Running   0          5m
   ```

## (選用) 部署 TensorFlow Serving 應用程式映像
<a name="deploy-tensorflow-serving-application"></a>

經過訓練的模型必須編譯至 Inferentia 目標，才能部署到 Inferentia 執行個體上。若要繼續，您需要儲存在 Amazon S3 中的 [Neuron 最佳化 TensorFlow](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-frameworks/tensorflow-neuron/index.html) 模型。如果您尚未擁有 SavedModel，請依照[建立 Neuron 相容的 ResNet50 模型](https://docs.aws.amazon.com/dlami/latest/devguide/tutorial-inferentia-tf-neuron.html)教學，並將產生的 SavedModel 上傳到 S3。ResNet-50 是一種熱門的機器學習模型，用於圖像識別任務。如需編譯 Neuron 模型的詳細資訊，請參閱 AWS [深度學習 AMI 開發人員指南中的 AWS Inferentia Chip with DLAMI](https://docs.aws.amazon.com/dlami/latest/devguide/tutorial-inferentia.html)。 AMIs 

範例部署資訊清單會管理 AWS 深度學習容器為 TensorFlow 提供的預先建置推論服務容器。容器內部是 AWS Neuron 執行期和 TensorFlow Serving 應用程式。針對 Neuron 最佳化的預建置 Deep Learning Containers 的完整清單會在 GitHub 上進行維護，位於[可用圖像](https://github.com/aws/deep-learning-containers/blob/master/available_images.md#neuron-inference-containers)下。啟動時，DLC 會從 Amazon S3 中擷取您的模型、使用儲存的模型啟動 Neuron TensorFlow Serving，並等待預測請求。

分配給服務應用程式的 Nesuron 裝置數量可以進行調整，方法是變更部署 yaml 中的 `aws.amazon.com/neuron` 資源。請注意，TensorFlow Serving 和 Neuron 執行時間之間的通訊透過 GRPC 進行，這需要將 `IPC_LOCK` 功能傳遞給容器。

1. 將 `AmazonS3ReadOnlyAccess` IAM 政策新增至在[建立叢集](#create-cluster-inferentia)的步驟 1 中建立的節點執行個體角色。這是必要步驟，以便範例應用程式可以從 Amazon S3 載入訓練過的模型。

   ```
   aws iam attach-role-policy \
       --policy-arn arn:aws: iam::aws:policy/AmazonS3ReadOnlyAccess \
       --role-name eksctl-inferentia-nodegroup-ng-in-NodeInstanceRole-FI7HIYS3BS09
   ```

1. 使用下列內容建立名為 `rn50_deployment.yaml` 的檔案。更新區域碼和模型路徑以符合您想要的設定。當用戶端向 TensorFlow 伺服器發出請求時，模型名稱用於識別目的。此範例使用模型名稱來比對範例 ResNet50 用戶端指令碼，該指令碼將在稍後步驟中用於傳送預測請求。

   ```
   aws ecr list-images --repository-name neuron-rtd --registry-id 790709498068 --region us-west-2
   ```

   ```
   kind: Deployment
   apiVersion: apps/v1
   metadata:
     name: eks-neuron-test
     labels:
       app: eks-neuron-test
       role: master
   spec:
     replicas: 2
     selector:
       matchLabels:
         app: eks-neuron-test
         role: master
     template:
       metadata:
         labels:
           app: eks-neuron-test
           role: master
       spec:
         containers:
           - name: eks-neuron-test
             image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/tensorflow-inference-neuron:1.15.4-neuron-py37-ubuntu18.04
             command:
               - /usr/local/bin/entrypoint.sh
             args:
               - --port=8500
               - --rest_api_port=9000
               - --model_name=resnet50_neuron
               - --model_base_path=s3://${your-bucket-of-models}/resnet50_neuron/
             ports:
               - containerPort: 8500
               - containerPort: 9000
             imagePullPolicy: IfNotPresent
             env:
               - name: AWS_REGION
                 value: "us-east-1"
               - name: S3_USE_HTTPS
                 value: "1"
               - name: S3_VERIFY_SSL
                 value: "0"
               - name: S3_ENDPOINT
                 value: s3.us-east-1.amazonaws.com
               - name: AWS_LOG_LEVEL
                 value: "3"
             resources:
               limits:
                 cpu: 4
                 memory: 4Gi
                 aws.amazon.com/neuron: 1
               requests:
                 cpu: "1"
                 memory: 1Gi
             securityContext:
               capabilities:
                 add:
                   - IPC_LOCK
   ```

1. 部署模型。

   ```
   kubectl apply -f rn50_deployment.yaml
   ```

1. 使用下列內容建立名為 `rn50_service.yaml` 的檔案。HTTP 和 gRPC 連接埠會開啟以接受預測請求。

   ```
   kind: Service
   apiVersion: v1
   metadata:
     name: eks-neuron-test
     labels:
       app: eks-neuron-test
   spec:
     type: ClusterIP
     ports:
       - name: http-tf-serving
         port: 8500
         targetPort: 8500
       - name: grpc-tf-serving
         port: 9000
         targetPort: 9000
     selector:
       app: eks-neuron-test
       role: master
   ```

1. 為您的 TensorFlow 模型服務應用程式建立 Kubernetes 服務。

   ```
   kubectl apply -f rn50_service.yaml
   ```

## (選用) 針對您的 TensorFlow Serving 服務進行預測
<a name="make-predictions-against-tensorflow-service"></a>

1. 若要在本機測試，請將 gRPC 連接埠轉送至 `eks-neuron-test` 服務。

   ```
   kubectl port-forward service/eks-neuron-test 8500:8500 &
   ```

1. 建立一個叫做 `tensorflow-model-server-infer.py` 的 Python 指令碼，具有以下內容。此指令碼會透過 gRPC 執行推論，這是一種服務架構。

   ```
   import numpy as np
      import grpc
      import tensorflow as tf
      from tensorflow.keras.preprocessing import image
      from tensorflow.keras.applications.resnet50 import preprocess_input
      from tensorflow_serving.apis import predict_pb2
      from tensorflow_serving.apis import prediction_service_pb2_grpc
      from tensorflow.keras.applications.resnet50 import decode_predictions
   
      if __name__ == '__main__':
          channel = grpc.insecure_channel('localhost:8500')
          stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
          img_file = tf.keras.utils.get_file(
              "./kitten_small.jpg",
              "https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg")
          img = image.load_img(img_file, target_size=(224, 224))
          img_array = preprocess_input(image.img_to_array(img)[None, ...])
          request = predict_pb2.PredictRequest()
          request.model_spec.name = 'resnet50_inf1'
          request.inputs['input'].CopyFrom(
              tf.make_tensor_proto(img_array, shape=img_array.shape))
          result = stub.Predict(request)
          prediction = tf.make_ndarray(result.outputs['output'])
          print(decode_predictions(prediction))
   ```

1. 執行指令碼，將預測提交至您的服務。

   ```
   python3 tensorflow-model-server-infer.py
   ```

   範例輸出如下。

   ```
   [[(u'n02123045', u'tabby', 0.68817204), (u'n02127052', u'lynx', 0.12701613), (u'n02123159', u'tiger_cat', 0.08736559), (u'n02124075', u'Egyptian_cat', 0.063844085), (u'n02128757', u'snow_leopard', 0.009240591)]]
   ```