搭配 Amazon EKS 使用 AWS Inferentia 執行個體,以進行機器學習 - Amazon EKS

協助改進此頁面

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

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

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

搭配 Amazon EKS 使用 AWS Inferentia 執行個體,以進行機器學習

本主題描述了如何建立 Amazon EKS 叢集,其中具有執行 Amazon EC2 Inf1 執行個體的節點,以及 (選用) 如何部署範例應用程式。Amazon EC2 Inf1 執行個體由 AWS Inferentia 晶片提供支援,這些晶片由 AWS 自訂建置,可在雲端中提供高效能和最低成本推論。機器學習模型使用 AWS Neuron 部署至容器,這是一款軟體開發套件 (SDK),由編譯器、執行時間和分析工具組成,能夠最佳化 Inferentia 晶片的機器學習推理效能。AWSNeuron 支援流行的機器學習框架,如 TensorFlow、PyTorch 和 MxNet。

注意

Neuron 裝置邏輯 ID 必須是連續的。如果請求多個 Neuron 裝置的 Pod 已排程在某個 inf1.6xlargeinf1.24xlarge 執行個體類型 (具有多個 Neuron 裝置) 上,則如果 Kubernetes 排程器選取非連續的裝置 ID,該 Pod 將無法啟動。如需詳細資訊,請參閱 GitHub 上的裝置邏輯 ID 必須是連續的

先決條件

  • eksctl 安裝在您的電腦上。如果您尚未安裝,請參閱 eksctl 文件中的安裝一節。

  • kubectl 安裝在您的電腦上。如需詳細資訊,請參閱 設定 kubectl 和 eksctl

  • (選用) 將 python3 安裝在您的電腦上。如果您尚未安裝,請參閱 Python 下載以取得安裝指示。

建立叢集

  1. 建立具有 Inf1 Amazon EC2 執行個體之節點的叢集。您可以使用任何 Inf1 執行個體類型取代 inf1.2xlargeeksctl 公用程式偵測到您正在啟動具有 Inf1 執行個體類型的節點群組,並將使用 Amazon EKS 最佳化加速 Amazon Linux AMI 之一來啟動您的節點。

    注意

    您無法搭配 TensorFlow Serving 使用服務帳戶的 IAM 角色

    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 載入訓練過的模型。

  2. 請確保所有的 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 應用程式映像

經過訓練的模型必須編譯至 Inferentia 目標,才能部署到 Inferentia 執行個體上。若要繼續,您需要儲存在 Amazon S3 中的 Neuron 最佳化 TensorFlow 模型。如果您尚未擁有 SavedModel,請依照建立 Neuron 相容的 ResNet50 模型教學,並將產生的 SavedModel 上傳到 S3。ResNet-50 是一種熱門的機器學習模型,用於圖像識別任務。如需編譯 Nuron 模型的詳細資訊,請參閱《AWS 深度學習 AMI 開發人員指南》中的具有 DLAMI 的 AWS Inferentia 晶片

範例部署清單檔案管理由 AWS Deep Learning Containers 提供的適用於 TensorFlow 的預建置推斷服務容器。容器內部是 AWS Neuron 執行時間和 TensorFlow Serving 應用程式。針對 Neuron 最佳化的預建置 Deep Learning Containers 的完整清單會在 GitHub 上進行維護,位於可用圖像下。啟動時,DLC 會從 Amazon S3 中擷取您的模型、使用儲存的模型啟動 Neuron TensorFlow Serving,並等待預測請求。

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

  1. AmazonS3ReadOnlyAccess IAM 政策新增至在建立叢集的步驟 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
  2. 使用下列內容建立名為 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
  3. 部署模型。

    kubectl apply -f rn50_deployment.yaml
  4. 使用下列內容建立名為 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
  5. 為您的 TensorFlow 模型服務應用程式建立 Kubernetes 服務。

    kubectl apply -f rn50_service.yaml

(選用) 針對您的 TensorFlow Serving 服務進行預測

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

    kubectl port-forward service/eks-neuron-test 8500:8500 &
  2. 建立一個叫做 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))
  3. 執行指令碼,將預測提交至您的服務。

    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)]]