使用辅助启动磁盘预加载数据或容器映像

本页面介绍了如何通过在 Google Kubernetes Engine (GKE) 中使用辅助启动磁盘在新节点上预加载数据或容器映像,从而缩短工作负载启动延迟时间。这样一来,工作负载便可以实现快速冷启动,并提高预配资源的总体利用率。

在阅读本页面内容之前,请确保您熟悉 Google Cloud、Kubernetes、容器、YAML、containerd 运行时和 Google Cloud CLI。

概览

您可以使用最新 GKE 版本中提供的辅助启动磁盘配置节点池。您可以指示 GKE 预配节点并为其预加载数据(例如机器学习 [ML] 模型)或容器映像。对于工作负载,使用辅助磁盘中预加载的容器映像或数据具有以下优势:

  • 缩短了拉取大型容器映像或下载数据时的延迟时间
  • 更快的自动扩缩
  • 更快地从中断(例如维护事件和系统错误)中恢复

以下部分介绍了如何在 GKE Autopilot 和 Standard 集群中配置辅助启动磁盘。

辅助启动磁盘的工作原理

通过使用辅助启动磁盘上预加载的容器映像或数据,您的工作负载可以更快地启动。辅助启动磁盘具有以下特性:

  • 辅助启动磁盘是指由分布式块存储提供支持的永久性磁盘。
  • 永久性磁盘是从您预先创建的磁盘映像实例化的。
  • 出于可伸缩性方面的考虑,每个节点都会获得一个从磁盘映像创建的自己的永久性磁盘实例。这些永久性磁盘实例会在删除节点时一并删除。
  • 如果磁盘映像已在可用区中使用,则从同一磁盘映像创建的所有后续磁盘的创建时间会缩短。
  • 辅助启动磁盘类型与节点启动磁盘相同。
  • 辅助启动磁盘的大小由磁盘映像大小决定。

向节点池添加辅助启动磁盘通常不会增加节点预配时间。GKE 会并行于节点预配流程,从磁盘映像预配辅助启动磁盘。

最佳实践:

为了支持预加载的容器映像,GKE 使用可从辅助启动磁盘读取容器映像的插件来扩展 containerd 运行时。容器映像会由基础层重复使用。

将大型基础层预加载到辅助启动磁盘中,而小型较高层可以从容器注册表中拉取。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如需使用 Google Cloud CLI 执行此任务, 请安装并 初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新 版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。

要求

使用辅助启动磁盘时需满足以下要求:

  1. 使用受支持的节点映像类型和 GKE 版本:
    • Container-Optimized OS with containerd (COS_CONTAINERD):
      • GKE Standard 和 Autopilot:版本 1.30.1-gke.1329000 或更高版本。
    • Ubuntu with containerd (UBUNTU_CONTAINERD):
      • GKE Standard 和 Autopilot:版本 1.35.0-gke.1403000 或更高版本。
  2. 修改磁盘映像时,您必须创建新的节点池。不支持更新现有节点上的磁盘映像。
  3. 配置 映像流式传输 以使用辅助启动磁盘功能。
  4. 在构建时或使用预加载的容器映像时,准备好数据的磁盘映像。确保您的集群有权访问磁盘映像,以便在节点中加载。

    最佳实践:

    在 CI/CD 流水线中自动化处理磁盘映像。

限制

您无法更新现有节点的辅助启动磁盘。如需附加新的磁盘映像,请创建新的节点池。

价格

创建具有辅助启动磁盘的节点池时,GKE 会将永久性磁盘挂接到节点池中的每个节点。永久性磁盘的费用是根据 Compute Engine 磁盘价格计算的。

准备辅助启动磁盘映像

如需准备辅助启动磁盘映像,请选择映像标签页以预加载容器映像,或选择数据标签页以预加载数据,然后完成以下说明:

图片

GKE 提供了一种名为 gke-disk-image-builder 的工具,用于创建虚拟机 (VM) 并拉取磁盘上的容器映像,然后通过该磁盘创建磁盘映像。

如需创建具有多个预加载的容器映像的磁盘映像,请完成以下步骤:

  1. 创建一个 Cloud Storage 存储桶来存储 gke-disk-image-builder 的执行日志。
  2. 使用 gke-disk-image-builder 创建磁盘映像。
go run ./cli \
    --project-name=PROJECT_ID \
    --image-name=DISK_IMAGE_NAME \
    --zone=LOCATION \
    --gcs-path=gs://LOG_BUCKET_NAME \
    --disk-size-gb=10 \
    --container-image=docker.io/library/python:latest \
    --container-image=docker.io/library/nginx:latest

替换以下内容:

  • PROJECT_ID:您的 Google Cloud 项目的名称。
  • DISK_IMAGE_NAME:磁盘映像的名称。例如 nginx-python-image。
  • LOCATION:集群位置。
  • LOG_BUCKET_NAME:用于存储执行日志的 Cloud Storage 存储桶的名称。例如 gke-secondary-disk-image-logs/。

使用 gke-disk-image-builder 创建磁盘映像时,Google Cloud 会创建多个资源以完成此过程(例如虚拟机实例、临时磁盘和永久性磁盘)。执行完成后,映像构建器会清理您创建的所有资源(磁盘映像除外)。

数据

通过完成以下步骤创建自定义磁盘映像作为数据源:

  1. 创建具有空白磁盘的虚拟机。
  2. 使用 SSH 连接到虚拟机。
    1. 装载空白磁盘。
    2. 将数据下载到空白磁盘上。
  3. 通过该磁盘创建自定义映像。

配置辅助启动磁盘

您可以在 GKE Autopilot 或 Standard 集群中配置辅助启动磁盘。

最佳做法:

使用 Autopilot 集群可获得全托管式 Kubernetes 体验。如需选择最适合您的工作负载的 GKE 操作模式,请参阅选择 GKE 操作模式。

使用 GKE Autopilot

在本部分中,您将创建磁盘映像许可名单以允许现有 GKE Autopilot 集群中的磁盘映像。然后,修改 Pod 节点选择器以使用辅助启动磁盘。

允许您的项目中的磁盘映像

在本部分中,您将创建一个 GCPResourceAllowlist,以允许 GKE 使用来自Google Cloud 项目中的磁盘映像的辅助启动磁盘创建节点。

  1. 将以下清单保存为 allowlist-disk.yaml:

    apiVersion: "node.gke.io/v1"
    kind: GCPResourceAllowlist
    metadata:
      name: gke-secondary-boot-disk-allowlist
    spec:
      allowedResourcePatterns:
      - "projects/PROJECT_ID/global/images/.*"
    

    将 PROJECT_ID 替换为用于托管磁盘映像的项目 ID。

  2. 应用清单:

    kubectl apply -f allowlist-disk.yaml
    

    GKE 会使用来自项目中所有磁盘映像的辅助启动磁盘创建节点。

更新 Pod 节点选择器以使用辅助启动磁盘

在本部分中,您将修改 Pod 规范,以便 GKE 创建具有辅助启动磁盘的节点。

  1. 将 nodeSelector 添加到 Pod 模板:

    nodeSelector:
        cloud.google.com.node-restriction.kubernetes.io/gke-secondary-boot-disk-DISK_IMAGE_NAME: CONTAINER_IMAGE_CACHE.PROJECT_ID
    

    替换以下内容:

    • DISK_IMAGE_NAME:磁盘映像的名称。
    • PROJECT_ID:用于托管磁盘映像的项目 ID。
  2. 使用 kubectl apply 命令通过 Pod 模板应用 Kubernetes 规范。

  3. 确认正在使用辅助启动磁盘缓存:

    kubectl get events --all-namespaces
    

    输出类似于以下内容:

    75s         Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm   Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  4. 确认正在使用辅助启动磁盘缓存的更可靠方式:

    使用以下日志名称查询您感兴趣的节点中的日志:

    logName="projects/PROJECT_ID/logs/gcfs-snapshotter"
    

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

    类似于 Image gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary boot disk caching by 100.0%... 的日志表示已使用辅助启动磁盘缓存。

  5. 检查映像拉取延迟时间:

    kubectl describe pod POD_NAME
    

    将 POD_NAME 替换为 Pod 的名称。

    输出类似于以下内容:

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

无论映像大小如何,缓存的容器映像的预期映像拉取延迟时间都应显著缩短。

使用 GKE Standard

如需创建 GKE 标准集群和节点池,请完成以下说明,并根据您是要在辅助启动磁盘上预加载容器映像还是数据,选择“Images”标签页或“Data”标签页:

图片

如需配置辅助启动磁盘,请使用 Google Cloud CLI 或 Terraform:

gcloud

  1. 创建启用了映像流式传输的 GKE Standard 集群:

    gcloud container clusters create CLUSTER_NAME \
        --location=LOCATION \
        --cluster-version=VERSION \
        --enable-image-streaming
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群位置。
    • VERSION:要使用的 GKE 版本。GKE 版本必须为 1.28.3-gke.1067000 或更高版本。
  2. 在同一项目中创建具有辅助启动磁盘的节点池:

    gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location LOCATION \
    --enable-image-streaming \
    --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE
    

    替换以下内容:

    • NODE_POOL_NAME:节点池的名称。
    • CLUSTER_NAME:现有集群的名称。
    • LOCATION:集群的计算可用区(以英文逗号分隔)。
    • DISK_IMAGE_NAME:磁盘映像的名称。

    如需通过不同项目中的磁盘映像创建具有辅助启动磁盘的节点池,请完成使用不同项目中的辅助启动磁盘中的步骤。

  3. 将 nodeSelector 添加到 Pod 模板:

    nodeSelector:
        cloud.google.com/gke-nodepool: NODE_POOL_NAME
    
  4. 确认正在使用辅助启动磁盘缓存:

    kubectl get events --all-namespaces
    

    输出类似于以下内容:

    75s       Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  5. 确认正在使用辅助启动磁盘缓存的更可靠方式:

    使用以下日志名称查询您感兴趣的节点中的日志:

    logName="projects/PROJECT_ID/logs/gcfs-snapshotter"
    

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

    类似于 Image gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary boot disk caching by 100.0%... 的日志表示已使用辅助启动磁盘缓存。

  6. 运行以下命令,检查映像拉取延迟时间:

    kubectl describe pod POD_NAME
    

    将 POD_NAME 替换为 Pod 的名称。

    输出类似于以下内容:

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

无论映像大小如何,缓存的容器映像的预期映像拉取延迟时间都不应超过几秒钟。

Terraform

  1. 如需使用 Terraform 创建具有默认节点池的集群,请参阅以下示例:

    resource "google_container_cluster" "default" {
      name               = "default"
      location           = "us-central1-a"
      initial_node_count = 1
    
      # secondary_boot_disks require GKE 1.28.3-gke.106700 or later, which should
      # be true for all release channels apart from EXTENDED.
      # If required, Use `release_channel = "EXTENDED"` and set `min_master_version`.
    }
  2. 在同一项目中创建具有辅助启动磁盘的节点池:

    resource "google_container_node_pool" "secondary-boot-disk-container" {
      name               = "secondary-boot-disk-container"
      location           = "us-central1-a"
      cluster            = google_container_cluster.default.name
      initial_node_count = 1
    
      node_config {
        machine_type = "e2-medium"
        image_type   = "COS_CONTAINERD"
        gcfs_config {
          enabled = true
        }
        secondary_boot_disks {
          disk_image = ""
          mode       = "CONTAINER_IMAGE_CACHE"
        }
      }
    }

    如需详细了解如何使用 Terraform,请参阅针对 GKE 的 Terraform 支持。

  3. 将 nodeSelector 添加到 Pod 模板:

    nodeSelector:
        cloud.google.com/gke-nodepool: NODE_POOL_NAME
    
  4. 确认正在使用辅助启动磁盘缓存:

    kubectl get events --all-namespaces
    

    输出类似于以下内容:

    75s       Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  5. 运行以下命令,检查映像拉取延迟时间:

    kubectl describe pod POD_NAME
    

    将 POD_NAME 替换为 Pod 的名称。

    输出类似于以下内容:

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

无论映像大小如何,缓存的容器映像的预期映像拉取延迟时间都不应超过几秒钟。

如需详细了解如何使用 Terraform,请参阅针对 GKE 的 Terraform 支持。

数据

您可以使用 Google Cloud CLI 或 Terraform 配置辅助启动磁盘并预加载数据:

gcloud

  1. 创建启用了映像流式传输的 GKE Standard 集群:

    gcloud container clusters create CLUSTER_NAME \
        --location=LOCATION \
        --cluster-version=VERSION \
        --enable-image-streaming
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群位置。
    • VERSION:要使用的 GKE 版本。GKE 版本必须为 1.28.3-gke.1067000 或更高版本。
  2. 使用 --secondary-boot-disk 标志创建具有辅助启动磁盘的节点池:

    gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location LOCATION \
    --enable-image-streaming \
    --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME
    

    替换以下内容:

    • NODE_POOL_NAME:节点池的名称。
    • CLUSTER_NAME:现有集群的名称。
    • LOCATION:集群的计算可用区(以英文逗号分隔)。
    • DISK_IMAGE_NAME:磁盘映像的名称。

    如需通过不同项目中的磁盘映像创建具有辅助启动磁盘的节点池,请完成使用不同项目中的辅助启动磁盘中的步骤。

    GKE 会创建一个节点池,其中每个节点都具有一个包含预加载数据的辅助磁盘。GKE 会挂接辅助启动磁盘并将其装载到节点上。

  3. 如需访问数据,请使用 hostPath 卷装载将辅助启动磁盘映像装载到 Pod 容器中。将 /usr/local/data_path_sbd 设置为您希望数据驻留在容器中的路径:

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-name
    spec:
      containers:
      ...
        volumeMounts:
        - mountPath: /usr/local/data_path_sbd
          name: data-path-sbd
      ...
      volumes:
      - name: data-path-sbd
        hostPath:
          path: /mnt/disks/gke-secondary-disks/gke-DISK_IMAGE_NAME-disk
    

    将 DISK_IMAGE_NAME 替换为磁盘映像的名称。

Terraform

  1. 如需使用 Terraform 创建具有默认节点池的集群,请参阅以下示例:

    resource "google_container_cluster" "default" {
      name               = "default"
      location           = "us-central1-a"
      initial_node_count = 1
    
      # secondary_boot_disks require GKE 1.28.3-gke.106700 or later, which should
      # be true for all release channels apart from EXTENDED.
      # If required, Use `release_channel = "EXTENDED"` and set `min_master_version`.
    }
  2. 在同一项目中创建具有辅助启动磁盘的节点池:

    resource "google_container_node_pool" "secondary-boot-disk-data" {
      name               = "secondary-boot-disk-data"
      location           = "us-central1-a"
      cluster            = google_container_cluster.default.name
      initial_node_count = 1
    
      node_config {
        machine_type = "e2-medium"
        image_type   = "COS_CONTAINERD"
        gcfs_config {
          enabled = true
        }
        secondary_boot_disks {
          disk_image = ""
        }
      }
    }

    如需详细了解如何使用 Terraform,请参阅 针对 GKE 的 Terraform 支持。

  3. 如需访问数据,请使用 hostPath 卷装载将辅助启动磁盘映像装载到 Pod 容器中。将 /usr/local/data_path_sbd 设置为您希望数据驻留在容器中的路径:

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-name
    spec:
      containers:
      ...
        volumeMounts:
        - mountPath: /usr/local/data_path_sbd
          name: data-path-sbd
      ...
      volumes:
      - name: data-path-sbd
        hostPath:
          path: /mnt/disks/gke-secondary-disks/gke-DISK_IMAGE_NAME-disk
    

    将 DISK_IMAGE_NAME 替换为磁盘映像的名称。

辅助启动磁盘的集群自动扩缩功能

如需创建节点池并在辅助启动磁盘上配置集群自动扩缩,请使用 Google Cloud CLI:

  gcloud container node-pools create NODE_POOL_NAME \
      --cluster=CLUSTER_NAME \
      --location LOCATION \
      --enable-image-streaming \
      --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE \
      --enable-autoscaling \
      --num-nodes NUM_NODES \
      --min-nodes MIN_NODES \
      --max-nodes MAX_NODES

替换以下内容:

  • NODE_POOL_NAME:节点池的名称。
  • CLUSTER_NAME:现有集群的名称。
  • LOCATION:集群的计算可用区(以英文逗号分隔)。
  • DISK_IMAGE_NAME:磁盘映像的名称。
  • MIN_NODES:为每个可用区中指定节点池自动扩缩的节点数下限。如需在 GKE 1.24 及更高版本中指定整个节点池的节点数下限,请使用 --total-min-nodes。标志 --total-min-nodes 和 --total-max-nodes 与标志 --min-nodes 和 --max-nodes 互斥。
  • MAX_NODES:为每个可用区中指定节点池自动扩缩的节点数上限。如需在 GKE 1.24 及更高版本中指定整个节点池的节点数上限,请使用 --total-max-nodes。标志 --total-min-nodes 和 --total-max-nodes 与标志 --min-nodes 和 --max-nodes 互斥。

辅助启动磁盘的节点自动预配功能

在 GKE 1.30.1-gke.1329000 及更高版本中,您可以配置节点自动预配以自动创建和删除节点池,从而满足工作负载的资源需求。

  1. 为辅助启动磁盘创建磁盘映像许可名单自定义资源以进行 GKE 节点自动预配,如下所示:

    apiVersion: "node.gke.io/v1"
    kind: GCPResourceAllowlist
    metadata:
      name: gke-secondary-boot-disk-allowlist
    spec:
      allowedResourcePatterns:
      - "projects/<PROJECT_ID>/global/images/.*"
    

    将 PROJECT_ID 替换为用于托管磁盘映像的项目 ID。

  2. 如需在集群中部署许可名单自定义资源,请运行以下命令:

    kubectl apply -f ALLOWLIST_FILE
    

    将 ALLOWLIST_FILE 替换为清单文件名。

  3. 更新 Pod 节点选择器以使用辅助启动磁盘:

    nodeSelector:
        cloud.google.com.node-restriction.kubernetes.io/gke-secondary-boot-disk-DISK_IMAGE_NAME:CONTAINER_IMAGE_CACHE.PROJECT_ID
    

    替换以下内容:

    • DISK_IMAGE_NAME:磁盘映像的名称。
    • PROJECT_ID:用于托管磁盘映像的项目 ID。

使用不同项目中的辅助启动磁盘

创建具有辅助启动磁盘的节点池时,您可以使用 --secondary-boot-disk 标志指示 GKE 使用不同项目中的磁盘映像。

  1. 使用 --secondary-boot-disk 标志,根据其他项目中的磁盘映像创建具有辅助启动磁盘的节点池。例如:

    gcloud beta container node-pools create NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location LOCATION \
        --enable-image-streaming \
        --secondary-boot-disk=disk-image=projects/IMAGE_PROJECT_ID/global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE
    
    

    替换以下内容:

    • DISK_IMAGE_NAME:磁盘映像的名称。
    • IMAGE_PROJECT_ID:磁盘映像所属的项目的名称。

    GKE 会创建一个节点池,其中每个节点都具有一个包含预加载数据的辅助磁盘。GKE 会挂接辅助启动磁盘并将其装载到节点上。

  2. 通过为集群服务账号添加“Compute Image User”角色,授予对属于不同项目的磁盘映像的访问权限:

    • 默认计算服务账号:CLUSTER_PROJECT_NUMBER@cloudservices。
    • GKE 服务账号:service-CLUSTER_PROJECT_NUMBER@container-engine-robot。
    gcloud projects add-iam-policy-binding IMAGE_PROJECT_ID \
        --member serviceAccount:CLUSTER_PROJECT_NUMBER@cloudservices. \
        --role roles/compute.imageUser
    
    gcloud projects add-iam-policy-binding IMAGE_PROJECT_ID \
        --member serviceAccount:service-CLUSTER_PROJECT_NUMBER@container-engine-robot. \
        --role roles/compute.imageUser
    

后续步骤