在 GKE 中使用单个 GPU 提供模型


本教程介绍了如何在 Google Kubernetes Engine (GKE) 模式下使用 GPU 提供简单模型。本教程会创建一个使用单个 L4 Tensor Core GPU 的 GKE 集群,并准备 GKE 基础设施以进行在线推理。本教程使用两种最常用的框架进行在线传送:

目标

本教程适用于希望在 GKE 集群中托管预训练的机器学习 (ML) 模型的基础架构工程师、MLOps 工程师、DevOps 工程师或集群管理员。

本教程介绍以下步骤:

  1. 创建 GKE Autopilot 或 Standard 集群。
  2. 配置 Cloud Storage 存储桶,即预训练模型。
  3. 部署您选择的在线推理框架。
  4. 向已部署的服务发出测试请求。

费用

本教程使用 Google Cloud 的以下收费组件:

  • GKE
  • Cloud Storage
  • L4 GPU 加速器
  • 出站流量

您可使用价格计算器根据您的预计使用情况来估算费用。

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备工作

设置项目

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 中的项目选择器页面上,点击创建项目以开始创建新的 Google Cloud 项目。

    转到“项目选择器”

  3. 确保您的 Google Cloud 项目已启用结算功能

  4. 启用 GKE API。

    启用 API

  5. 在 Google Cloud Console 中的项目选择器页面上,点击创建项目以开始创建新的 Google Cloud 项目。

    转到“项目选择器”

  6. 确保您的 Google Cloud 项目已启用结算功能

  7. 启用 GKE API。

    启用 API

设置 Google Cloud CLI 的默认值

  1. 在 Google Cloud 控制台中,启动 Cloud Shell 实例:
    打开 Cloud Shell

  2. 下载此示例应用的源代码:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/ai-ml/gke-online-serving-single-gpu
    
  3. 设置默认环境变量:

    gcloud config set project PROJECT_ID
    gcloud config set compute/region COMPUTE_REGION
    

    替换以下值:

    • PROJECT_ID:您的 Google Cloud 项目 ID
    • COMPUTE_REGION:支持要使用的加速器类型的 Compute Engine 区域,例如适用于 L4 GPU 的 us-central1
  4. 在 Cloud Shell 中,创建以下环境变量:

    export PROJECT_ID=$(gcloud config get project)
    export REGION=$(gcloud config get compute/region)
    export K8S_SA_NAME=gpu-k8s-sa
    export GSBUCKET=$PROJECT_ID-gke-bucket
    export MODEL_NAME=mnist
    export CLUSTER_NAME=online-serving-cluster
    

创建 GKE 集群

您可以在 GKE Autopilot 或 Standard 集群中的单个 GPU 上提供模型。我们建议您使用 Autopilot 集群获得全托管式 Kubernetes 体验。借助 GKE Autopilot,资源会根据模型请求自动扩缩。

如需选择最适合您的工作负载的 GKE 操作模式,请参阅选择 GKE 操作模式

Autopilot

运行以下命令创建 GKE Autopilot 集群:

  gcloud container clusters create-auto ${CLUSTER_NAME} \
      --region=${REGION} \
      --project=${PROJECT_ID} \
      --release-channel=rapid

GKE 会根据所部署的工作负载的请求,创建具有所需 CPU 和 GPU 节点的 Autopilot 集群。

标准

  1. 运行以下命令创建 GKE Standard 集群:

      gcloud container clusters create ${CLUSTER_NAME} \
        --project=${PROJECT_ID}  \
        --region=${REGION}  \
        --workload-pool=${PROJECT_ID}.svc.id.goog \
        --addons GcsFuseCsiDriver \
        --release-channel=rapid \
        --num-nodes=1
    

    集群创建可能需要几分钟的时间。

  2. 运行以下命令创建节点池:

      gcloud container node-pools create gpupool \
        --accelerator type=nvidia-l4,count=1,gpu-driver-version=latest \
        --project=${PROJECT_ID} \
        --location=${REGION} \
        --node-locations=${REGION}-a \
        --cluster=${CLUSTER_NAME} \
        --machine-type=g2-standard-8 \
        --num-nodes=1
    

    GKE 会创建一个节点池,其中每个节点都有一个 L4 GPU。

创建 Cloud Storage 存储桶

创建 Cloud Storage 存储桶以存储将要提供的预训练模型。

在 Cloud Shell 中,运行以下命令:

gcloud storage buckets create gs://$GSBUCKET

配置集群以使用适用于 GKE 的工作负载身份联合访问存储桶

如需允许集群访问 Cloud Storage 存储桶,请执行以下操作:

  1. 创建 Google Cloud 服务账号。
  2. 在集群中创建 Kubernetes ServiceAccount。
  3. 将 Kubernetes ServiceAccount 绑定到 Google Cloud 服务账号。

创建 Google Cloud 服务账号

  1. 在 Google Cloud 控制台中,转到创建服务账号页面:

    转到“创建服务账号”

  2. 服务账号 ID 字段中,输入 gke-ai-sa

  3. 点击创建并继续

  4. 角色列表中,选择 Cloud Storage > Storage Insights Collector Service 角色。

  5. 点击添加其他角色

  6. 选择角色列表中,选择 Cloud Storage > Storage Object Admin 角色。

  7. 点击继续,然后点击完成

在集群中创建 Kubernetes ServiceAccount

在 Cloud Shell 中,执行以下操作:

  1. 创建 Kubernetes 命名空间:

    kubectl create namespace gke-ai-namespace
    
  2. 在该命名空间中创建 Kubernetes ServiceAccount:

    kubectl create serviceaccount gpu-k8s-sa --namespace=gke-ai-namespace
    

将 Kubernetes ServiceAccount 绑定到 Google Cloud 服务账号

在 Cloud Shell 中,运行以下命令:

  1. 向 Google Cloud 服务账号添加 IAM 绑定:

    gcloud iam service-accounts add-iam-policy-binding gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-ai-namespace/gpu-k8s-sa]"
    

    --member 标志提供 Google Cloud 中 Kubernetes ServiceAccount 的完整身份。

  2. 为 Kubernetes ServiceAccount 添加注解:

    kubectl annotate serviceaccount gpu-k8s-sa \
        --namespace gke-ai-namespace \
        iam.gke.io/gcp-service-account=gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com
    

部署在线推理服务器

每个在线推理框架都希望以特定格式查找预训练的机器学习模型。以下部分介绍如何根据要使用的框架部署推理服务器:

海卫一

  1. 在 Cloud Shell 中,将预训练的机器学习模型复制到 Cloud Storage 存储桶:

    gsutil cp -r src/triton-model-repository gs://$GSBUCKET
    
  2. 在 Kubernetes 上部署该框架:

    envsubst < src/gke-config/deployment-triton.yaml | kubectl --namespace=gke-ai-namespace apply -f -
    
  3. 验证 GKE 是否已部署框架:

    kubectl get deployments --namespace=gke-ai-namespace
    

    框架准备就绪后,输出将类似于以下内容:

    NAME                 READY   UP-TO-DATE   AVAILABLE   AGE
    triton-deployment    1/1     1            1           5m29s
    
  4. 部署 Service 以访问部署

    kubectl apply --namespace=gke-ai-namespace -f src/gke-config/service-triton.yaml
    
  5. 检查是否已分配外部 IP 地址:

    kubectl get services --namespace=gke-ai-namespace
    

    输出类似于以下内容:

    NAME            TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                        AGE
    kubernetes      ClusterIP      34.118.224.1     <none>          443/TCP                                        60m
    triton-server   LoadBalancer   34.118.227.176   35.239.54.228   8000:30866/TCP,8001:31035/TCP,8002:30516/TCP   5m14s
    

    记下 EXTERNAL-IP 列中 triton-server 的 IP 地址。

  6. 检查服务和部署是否正常运行:

    curl -v EXTERNAL_IP:8000/v2/health/ready
    

    输出类似于以下内容:

    ...
    < HTTP/1.1 200 OK
    < Content-Length: 0
    < Content-Type: text/plain
    ...
    

TF 传送

  1. 在 Cloud Shell 中,将预训练的机器学习模型复制到 Cloud Storage 存储桶:

    gsutil cp -r src/tfserve-model-repository gs://$GSBUCKET
    
  2. 在 Kubernetes 上部署该框架:

    envsubst < src/gke-config/deployment-tfserve.yaml | kubectl --namespace=gke-ai-namespace apply -f -
    
  3. 验证 GKE 是否已部署框架:

    kubectl get deployments --namespace=gke-ai-namespace
    

    框架准备就绪后,输出将类似于以下内容:

    NAME                 READY   UP-TO-DATE   AVAILABLE   AGE
    tfserve-deployment   1/1     1            1           5m29s
    
  4. 部署 Service 以访问部署

    kubectl apply --namespace=gke-ai-namespace -f src/gke-config/service-tfserve.yaml
    
  5. 检查是否已分配外部 IP 地址:

    kubectl get services --namespace=gke-ai-namespace
    

    输出类似于以下内容:

    NAME            TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                        AGE
    kubernetes      ClusterIP      34.118.224.1     <none>          443/TCP                                        60m
    tfserve-server  LoadBalancer   34.118.227.176   35.239.54.228   8500:30003/TCP,8000:32194/TCP                  5m14s
    

    记下 EXTERNAL-IP 列中 tfserve-server 的 IP 地址。

  6. 检查服务和部署是否正常运行:

    curl -v EXTERNAL_IP:8000/v1/models/mnist
    

    EXTERNAL_IP 替换为您的外部 IP 地址。

    输出类似于以下内容:

    ...
    < HTTP/1.1 200 OK
    < Content-Type: application/json
    < Date: Thu, 12 Oct 2023 19:01:19 GMT
    < Content-Length: 154
    <
    {
      "model_version_status": [
            {
            "version": "1",
            "state": "AVAILABLE",
            "status": {
              "error_code": "OK",
              "error_message": ""
            }
          }
        ]
    }
    

应用模型

海卫一

  1. 在 Cloud Shell 中创建 Python 虚拟环境。

    python -m venv ./mnist_client
    source ./mnist_client/bin/activate
    
  2. 安装必需的 Python 软件包。

    pip install -r src/client/triton-requirements.txt
    
  3. 通过加载图片来测试 Triton 推断服务器:

    cd src/client
    python triton_mnist_client.py -i EXTERNAL_IP -m mnist -p ./images/TEST_IMAGE.png
    

    替换以下内容:

    • EXTERNAL_IP:您的外部 IP 地址。
    • TEST_IMAGE:与要测试的映像对应的文件的名称。您可以使用存储在 src/client/images 中的映像。

    输出内容如下所示(具体取决于您使用的映像):

    Calling Triton HTTP Service      ->      Prediction result: 7
    

TF 传送

  1. 在 Cloud Shell 中创建 Python 虚拟环境。

    python -m venv ./mnist_client
    source ./mnist_client/bin/activate
    
  2. 安装必需的 Python 软件包。

    pip install -r src/client/tfserve-requirements.txt
    
  3. 使用几张图片测试 TensorFlow Serving。

    cd src/client
    python tfserve_mnist_client.py -i EXTERNAL_IP -m mnist -p ./images/TEST_IMAGE.png
    

替换以下内容:

  • EXTERNAL_IP:您的外部 IP 地址。
  • TEST_IMAGE:一个介于 09 之间的值。您可以使用存储在 src/client/images 中的映像。

根据您使用的图片,您将获得类似如下所示的输出:

  Calling TensorFlow Serve HTTP Service    ->      Prediction result: 5

清理

为避免系统因您在本指南中创建的资源而向您的 Google Cloud 账号收取费用,请执行以下操作之一:

  • 保留 GKE 集群:删除集群中的 Kubernetes 资源以及 Google Cloud 资源
  • 保留 Google Cloud 项目:删除 GKE 集群和 Google Cloud 资源
  • 删除项目

删除集群中的 Kubernetes 资源以及 Google Cloud 资源

  1. 删除 Kubernetes 命名空间和您部署的工作负载:

海卫一

kubectl -n gke-ai-namespace delete -f src/gke-config/service-triton.yaml
kubectl -n gke-ai-namespace delete -f src/gke-config/deployment-triton.yaml
kubectl delete namespace gke-ai-namespace

TF 传送

kubectl -n gke-ai-namespace delete -f src/gke-config/service-tfserve.yaml
kubectl -n gke-ai-namespace delete -f src/gke-config/deployment-tfserve.yaml
kubectl delete namespace gke-ai-namespace
  1. 删除 Cloud Storage 存储桶:

    1. 转至存储桶页面:

      进入“存储桶”

    2. 选择 PROJECT_ID-gke-bucket 对应的复选框。

    3. 点击 删除

    4. 要确认删除,请输入 DELETE,然后点击删除

  2. 删除 Google Cloud 服务账号:

    1. 转到服务账号页面:

      转到“服务账号”

    2. 选择您的项目。

    3. 选择 gke-gpu-sa@PROJECT_ID.iam.gserviceaccount.com 对应的复选框。

    4. 点击 删除

    5. 如需确认删除,请点击删除

删除 GKE 集群和 Google Cloud 资源

  1. 删除 GKE 集群:

    1. 转到集群页面:

      转到“集群”

    2. 选择 online-serving-cluster 对应的复选框。

    3. 点击 删除

    4. 要确认删除,请输入 online-serving-cluster,然后点击删除

  2. 删除 Cloud Storage 存储桶:

    1. 转至存储桶页面:

      进入“存储桶”

    2. 选择 PROJECT_ID-gke-bucket 对应的复选框。

    3. 点击 删除

    4. 要确认删除,请输入 DELETE,然后点击删除

  3. 删除 Google Cloud 服务账号:

    1. 转到服务账号页面:

      转到“服务账号”

    2. 选择您的项目。

    3. 选择 gke-gpu-sa@PROJECT_ID.iam.gserviceaccount.com 对应的复选框。

    4. 点击 删除

    5. 如需确认删除,请点击删除

删除项目

  1. 在 Google Cloud 控制台中,进入管理资源页面。

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

后续步骤