在 GKE Standard 模式下使用 GPU 训练模型


本快速入门介绍了如何在 Google Kubernetes Engine (GKE) 中部署采用 GPU 的训练模型,并将预测结果存储在 Cloud Storage 中。本文档适用于已有标准模式集群并希望首次运行 GPU 工作负载的 GKE 管理员。

您也可以通过较少的设置步骤,在 Autopilot 模式集群上运行这些工作负载。

须知事项

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

    转到“项目选择器”

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

  4. 启用 Kubernetes Engine and Cloud Storage API。

    启用 API

  5. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

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

  7. 启用 Kubernetes Engine and Cloud Storage API。

    启用 API

  8. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。

克隆示例代码库

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

git clone https://github.com/GoogleCloudPlatform/ai-on-gke/ ai-on-gke
cd ai-on-gke/tutorials-and-examples/gpu-examples/training-single-gpu

创建 Standard 模式集群和 GPU 节点池

使用 Cloud Shell 执行以下操作:

  1. 创建使用适用于 GKE 的工作负载身份联合的 Standard 集群,并安装 Cloud Storage FUSE 驱动程序

    gcloud container clusters create gke-gpu-cluster \
        --addons GcsFuseCsiDriver \
        --location=us-central1 \
        --num-nodes=1 \
        --workload-pool=PROJECT_ID.svc.id.goog
    

    PROJECT_ID 替换为您的 Google Cloud 项目 ID。

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

  2. 创建 GPU 节点池:

    gcloud container node-pools create gke-gpu-pool-1 \
        --accelerator=type=nvidia-tesla-t4,count=1,gpu-driver-version=default \
        --machine-type=n1-standard-16 --num-nodes=1 \
        --location=us-central1 \
        --cluster=gke-gpu-cluster
    

创建 Cloud Storage 存储桶

  1. 在 Google Cloud 控制台中,转到创建存储桶页面:

    转到“创建存储桶”

  2. 为存储桶命名字段中,输入以下名称:

    PROJECT_ID-gke-gpu-bucket
    
  3. 点击继续

  4. 对于位置类型,选择区域

  5. 区域列表中,选择 us-central1 (Iowa) 并点击继续

  6. 为您的数据选择存储类别部分中,点击继续

  7. 选择如何控制对象的访问权限部分中,对于访问权限控制,选择统一

  8. 点击创建

  9. 系统将禁止公开访问对话框,请确保禁止公开访问此存储桶复选框处于选中状态,然后点击确认

配置集群以使用适用于 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
    

验证 Pod 是否可以访问 Cloud Storage 存储桶

  1. 在 Cloud Shell 中,创建以下环境变量:

    export K8S_SA_NAME=gpu-k8s-sa
    export BUCKET_NAME=PROJECT_ID-gke-gpu-bucket
    

    PROJECT_ID 替换为您的 Google Cloud 项目 ID。

  2. 创建具有 TensorFlow 容器的 Pod:

    envsubst < src/gke-config/standard-tensorflow-bash.yaml | kubectl --namespace=gke-ai-namespace apply -f -
    

    此命令会将您创建的环境变量替换为清单中相应的引用。您还可以在文本编辑器中打开清单,并将 $K8S_SA_NAME$BUCKET_NAME 替换为相应的值。

  3. 在存储桶中创建示例文件:

    touch sample-file
    gsutil cp sample-file gs://PROJECT_ID-gke-gpu-bucket
    
  4. 等待 Pod 准备就绪:

    kubectl wait --for=condition=Ready pod/test-tensorflow-pod -n=gke-ai-namespace --timeout=180s
    

    Pod 准备就绪后,输出如下:

    pod/test-tensorflow-pod condition met
    
  5. 在 Tensorflow 容器中打开 Shell:

    kubectl -n gke-ai-namespace exec --stdin --tty test-tensorflow-pod --container tensorflow -- /bin/bash
    
  6. 尝试读取您创建的示例文件:

    ls /data
    

    输出会显示该示例文件。

  7. 查看日志以确定挂接到 Pod 的 GPU:

    python -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))"
    

    输出显示挂接到 Pod 的 GPU,类似于以下内容:

    ...
    PhysicalDevice(name='/physical_device:GPU:0',device_type='GPU')
    
  8. 退出该容器:

    exit
    
  9. 删除示例 Pod:

    kubectl delete -f src/gke-config/standard-tensorflow-bash.yaml \
        --namespace=gke-ai-namespace
    

使用 MNIST 数据集进行训练和预测

在本部分中,您将在 MNIST 示例数据集上运行训练工作负载。

  1. 将示例数据复制到 Cloud Storage 存储桶:

    gsutil -m cp -R src/tensorflow-mnist-example gs://PROJECT_ID-gke-gpu-bucket/
    
  2. 创建以下环境变量:

    export K8S_SA_NAME=gpu-k8s-sa
    export BUCKET_NAME=PROJECT_ID-gke-gpu-bucket
    
  3. 查看训练作业:

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: mnist-training-job
    spec:
      template:
        metadata:
          name: mnist
          annotations:
            gke-gcsfuse/volumes: "true"
        spec:
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-tesla-t4
          tolerations:
          - key: "nvidia.com/gpu"
            operator: "Exists"
            effect: "NoSchedule"
          containers:
          - name: tensorflow
            image: tensorflow/tensorflow:latest-gpu
            command: ["/bin/bash", "-c", "--"]
            args: ["cd /data/tensorflow-mnist-example; pip install -r requirements.txt; python tensorflow_mnist_train_distributed.py"]
            resources:
              limits:
                nvidia.com/gpu: 1
                cpu: 1
                memory: 3Gi
            volumeMounts:
            - name: gcs-fuse-csi-vol
              mountPath: /data
              readOnly: false
          serviceAccountName: $K8S_SA_NAME
          volumes:
          - name: gcs-fuse-csi-vol
            csi:
              driver: gcsfuse.csi.storage.gke.io
              readOnly: false
              volumeAttributes:
                bucketName: $BUCKET_NAME
                mountOptions: "implicit-dirs"
          restartPolicy: "Never"
  4. 部署训练作业:

    envsubst < src/gke-config/standard-tf-mnist-train.yaml | kubectl -n gke-ai-namespace apply -f -
    

    此命令会将您创建的环境变量替换为清单中相应的引用。您还可以在文本编辑器中打开清单,并将 $K8S_SA_NAME$BUCKET_NAME 替换为相应的值。

  5. 等待作业处于 Completed 状态:

    kubectl wait -n gke-ai-namespace --for=condition=Complete job/mnist-training-job --timeout=180s
    

    输出类似于以下内容:

    job.batch/mnist-training-job condition met
    
  6. 检查 Tensorflow 容器中的日志:

    kubectl logs -f jobs/mnist-training-job -c tensorflow -n gke-ai-namespace
    

    输出显示发生了以下事件:

    • 安装必需的 Python 软件包
    • 下载 MNIST 数据集
    • 使用 GPU 训练模型
    • 保存模型
    • 评估模型
    ...
    Epoch 12/12
    927/938 [============================>.] - ETA: 0s - loss: 0.0188 - accuracy: 0.9954
    Learning rate for epoch 12 is 9.999999747378752e-06
    938/938 [==============================] - 5s 6ms/step - loss: 0.0187 - accuracy: 0.9954 - lr: 1.0000e-05
    157/157 [==============================] - 1s 4ms/step - loss: 0.0424 - accuracy: 0.9861
    Eval loss: 0.04236088693141937, Eval accuracy: 0.9861000180244446
    Training finished. Model saved
    
  7. 删除训练工作负载:

    kubectl -n gke-ai-namespace delete -f src/gke-config/standard-tf-mnist-train.yaml
    

部署推理工作负载

在本部分中,您将部署一个推理工作负载,该工作负载将示例数据集作为输入并返回预测。

  1. 将用于预测的图片复制到存储桶:

    gsutil -m cp -R data/mnist_predict gs://PROJECT_ID-gke-gpu-bucket/
    
  2. 查看推理工作负载:

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: mnist-batch-prediction-job
    spec:
      template:
        metadata:
          name: mnist
          annotations:
            gke-gcsfuse/volumes: "true"
        spec:
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-tesla-t4
          tolerations:
          - key: "nvidia.com/gpu"
            operator: "Exists"
            effect: "NoSchedule"
          containers:
          - name: tensorflow
            image: tensorflow/tensorflow:latest-gpu
            command: ["/bin/bash", "-c", "--"]
            args: ["cd /data/tensorflow-mnist-example; pip install -r requirements.txt; python tensorflow_mnist_batch_predict.py"]
            resources:
              limits:
                nvidia.com/gpu: 1
                cpu: 1
                memory: 3Gi
            volumeMounts:
            - name: gcs-fuse-csi-vol
              mountPath: /data
              readOnly: false
          serviceAccountName: $K8S_SA_NAME
          volumes:
          - name: gcs-fuse-csi-vol
            csi:
              driver: gcsfuse.csi.storage.gke.io
              readOnly: false
              volumeAttributes:
                bucketName: $BUCKET_NAME
                mountOptions: "implicit-dirs"
          restartPolicy: "Never"
  3. 部署推理工作负载:

    envsubst < src/gke-config/standard-tf-mnist-batch-predict.yaml | kubectl -n gke-ai-namespace apply -f -
    

    此命令会将您创建的环境变量替换为清单中相应的引用。您还可以在文本编辑器中打开清单,并将 $K8S_SA_NAME$BUCKET_NAME 替换为相应的值。

  4. 等待作业处于 Completed 状态:

    kubectl wait -n gke-ai-namespace --for=condition=Complete job/mnist-batch-prediction-job --timeout=180s
    

    输出类似于以下内容:

    job.batch/mnist-batch-prediction-job condition met
    
  5. 检查 Tensorflow 容器中的日志:

    kubectl logs -f jobs/mnist-batch-prediction-job -c tensorflow -n gke-ai-namespace
    

    输出为每个图片的预测以及预测中模型的置信度,类似于以下内容:

    Found 10 files belonging to 1 classes.
    1/1 [==============================] - 2s 2s/step
    The image /data/mnist_predict/0.png is the number 0 with a 100.00 percent confidence.
    The image /data/mnist_predict/1.png is the number 1 with a 99.99 percent confidence.
    The image /data/mnist_predict/2.png is the number 2 with a 100.00 percent confidence.
    The image /data/mnist_predict/3.png is the number 3 with a 99.95 percent confidence.
    The image /data/mnist_predict/4.png is the number 4 with a 100.00 percent confidence.
    The image /data/mnist_predict/5.png is the number 5 with a 100.00 percent confidence.
    The image /data/mnist_predict/6.png is the number 6 with a 99.97 percent confidence.
    The image /data/mnist_predict/7.png is the number 7 with a 100.00 percent confidence.
    The image /data/mnist_predict/8.png is the number 8 with a 100.00 percent confidence.
    The image /data/mnist_predict/9.png is the number 9 with a 99.65 percent confidence.
    

清理

为避免系统因您在本指南中创建的资源而向您的 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/standard-tf-mnist-batch-predict.yaml
    kubectl delete namespace gke-ai-namespace
    
  2. 删除 Cloud Storage 存储桶:

    1. 转至存储桶页面:

      进入“存储桶”

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

    3. 点击 删除

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

  3. 删除 Google Cloud 服务账号:

    1. 转到服务账号页面:

      转到“服务账号”

    2. 选择您的项目。

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

    4. 点击 删除

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

删除 GKE 集群和 Google Cloud 资源

  1. 删除 GKE 集群:

    1. 转到集群页面:

      转到“集群”

    2. 选择 gke-gpu-cluster 对应的复选框。

    3. 点击 删除

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

  2. 删除 Cloud Storage 存储桶:

    1. 转至存储桶页面:

      进入“存储桶”

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

    3. 点击 删除

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

  3. 删除 Google Cloud 服务账号:

    1. 转到服务账号页面:

      转到“服务账号”

    2. 选择您的项目。

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

    4. 点击 删除

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

删除项目

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

    转到“管理资源”

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

后续步骤