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


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

本页面假定您了解 Google Cloud、Kubernetes、容器、YAML、containerd 运行时和 Google Cloud CLI。

概览

从 Standard 集群中的 GKE 1.28.3-gke.1067000 版以及 Autopilot 集群中的 GKE 1.30.1-gke.1329000 版开始,您可以配置具有辅助启动磁盘的节点池。您可以指示 GKE 预配节点并为其预加载数据(例如机器学习模型)或容器映像。对于工作负载,使用辅助磁盘中预加载的容器映像或数据具有以下优势:

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

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

辅助启动磁盘的工作原理

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

  • 辅助启动磁盘是由分布式块存储支持的永久性磁盘。如果磁盘映像已在可用区中使用,则来自同一磁盘映像的所有后续磁盘的创建时间会缩短。
  • 辅助启动磁盘类型与节点启动磁盘相同。
  • 辅助启动磁盘的大小由磁盘映像大小决定。

将辅助启动磁盘添加到节点池不会增加节点预配时间。GKE 会在节点预配过程中通过磁盘映像预配辅助启动磁盘。

为了支持预加载的容器映像,GKE 使用可从辅助启动磁盘读取容器映像的插件来扩展 containerd 运行时。容器映像会由基础层重复使用,我们建议您将大型基础层预加载到辅助启动磁盘中,而小型较高层可以从容器注册表中拉取。

准备工作

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

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。

要求

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

  1. 您的集群运行的是 GKE Standard 中的 GKE 1.28.3-gke.1067000 版或 GKE Autopilot 中的 1.30.1-gke.1329000 版。
  2. 修改磁盘映像时,请创建新的节点池。不支持更新现有节点上的磁盘映像。
  3. 配置映像流式传输以使用辅助启动磁盘功能。
  4. 将 Container-Optimized OS 与 containerd 节点映像搭配使用。Autopilot 节点默认使用此节点映像。
  5. 准备磁盘映像,其中包含构建时准备就绪的数据或预加载的容器映像。确保您的集群有权访问磁盘映像,以便在节点中加载。我们建议在 CI/CD 流水线中自动执行磁盘映像。

准备辅助启动磁盘

如需准备辅助启动磁盘,请选择映像标签页(用于预加载容器映像)或选择数据标签页(用于预加载数据),然后按照以下说明操作:

图片

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. 检查映像拉取延迟时间:

    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 Standard 集群和节点池,请按照以下说明操作,并根据您要在辅助启动磁盘上预加载容器映像还是预加载数据,选择“映像”或“数据”标签页:

图片

您可以使用 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.106700 或更高版本。
  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. 通过运行以下命令检查映像拉取延迟时间:

    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
      # Set `min_master_version` because secondary_boot_disks require GKE 1.28.3-gke.106700 or later.
      min_master_version = "1.28"
      # Setting `deletion_protection` to `true` would prevent
      # accidental deletion of this instance using Terraform.
      deletion_protection = false
    }
  2. nodeSelector 添加到 Pod 模板:

    nodeSelector:
        cloud.google.com/gke-nodepool: NODE_POOL_NAME
    
  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. 通过运行以下命令检查映像拉取延迟时间:

    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.106700 或更高版本。
  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 容器中。使用以下清单可定义 Pod 资源,并使用 hostPath 卷装载在容器中预加载数据磁盘:

    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
      # Set `min_master_version` because secondary_boot_disks require GKE 1.28.3-gke.106700 or later.
      min_master_version = "1.28"
      # Setting `deletion_protection` to `true` would prevent
      # accidental deletion of this instance using Terraform.
      deletion_protection = false
    }

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

  2. (可选)您可以使用 hostPath 卷装载将辅助磁盘映像装载到 Pod 容器中。使用以下清单可定义 Pod 资源,并使用 hostPath 卷装载在容器中预加载数据磁盘:

    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 会创建一个节点池,其中每个节点都具有一个包含预加载数据的辅助磁盘。此操作会挂接辅助启动磁盘并将其装载到节点上。

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

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

后续步骤