准备使用 Pod 快照

借助 Google Kubernetes Engine (GKE) Pod 快照,您可以保存和恢复正在运行的 Pod 状态,从而缩短工作负载启动延迟时间。在捕获工作负载的快照之前,您必须准备好集群和存储环境。

通过本文档,您可以了解如何在集群上启用和配置 Pod 快照,以及如何设置 Cloud Storage 来存储快照。如需详细了解 Pod 快照的工作原理,请参阅 GKE Pod 快照简介。

平台管理员、运维人员和应用开发者可以使用本文档来配置集群、创建存储桶以及为 Pod 快照设置访问权限。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务。

准备工作

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

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

启用 Pod 快照

您可以在新集群或现有集群上启用 Pod 快照。Pod 快照需要 GKE Sandbox 和 Workload Identity Federation for GKE。Autopilot 集群默认启用这两项功能。对于 Standard 集群,您必须在集群上启用 Workload Identity Federation for GKE,并配置节点池以在 GKE Sandbox 中运行。

如需在集群上启用 Pod 快照,请按照您要使用的 GKE 操作模式的步骤操作:

Autopilot

  • 如需在新集群上启用 Pod 快照,请运行以下命令:

      gcloud container clusters create-auto CLUSTER_NAME \
          --enable-pod-snapshots \
          --location=CONTROL_PLANE_LOCATION \
          --cluster-version=CLUSTER_VERSION
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • CONTROL_PLANE_LOCATION:集群控制平面的位置。
    • CLUSTER_VERSION:新集群的版本,必须为 1.35.3-gke.1234000 或更高版本。
  • 如需在现有集群上启用 Pod 快照,请按照以下步骤操作:

    1. 将集群升级到 1.35.3-gke.1234000 版或更高版本:

        gcloud container clusters upgrade CLUSTER_NAME \
            --cluster-version=CLUSTER_VERSION \
            --location=CONTROL_PLANE_LOCATION
      

      替换以下内容:

      • CLUSTER_NAME:您的集群的名称。
      • CLUSTER_VERSION:要将集群升级到的版本,必须为 1.35.3-gke.1234000 或更高版本。
      • CONTROL_PLANE_LOCATION:集群控制平面的位置。
    2. 在集群上启用 Pod 快照:

        gcloud container clusters update CLUSTER_NAME \
            --enable-pod-snapshots \
            --location=CONTROL_PLANE_LOCATION
      

      替换以下内容:

      • CLUSTER_NAME:您的集群的名称。
      • CONTROL_PLANE_LOCATION:集群控制平面的位置。

具有默认 whole-pod 范围的 Pod 快照不支持 E2 机器类型,而文件系统快照 (rootfs-only) 支持。在 Autopilot 集群中,GKE 默认可能会在 E2 节点上调度 Pod。如果您使用 whole-pod 范围,请使用 ComputeClass 自定义资源,以帮助确保您的工作负载在兼容的硬件上运行。

如需创建和使用 ComputeClass 自定义资源,请按照以下步骤操作:

  1. 将以下清单保存为 non-e2-class.yaml:

      apiVersion: cloud.google.com/v1
      kind: ComputeClass
      metadata:
        name: non-e2-class
      spec:
        priorities:
        - machineFamily: n2
        - machineFamily: c3
        activeMigration:
          optimizeRulePriority: false
        whenUnsatisfiable: DoNotScaleUp
    
  2. 应用清单:

      kubectl apply -f non-e2-class.yaml
    
  3. 在 Pod 规范中,使用 cloud.google.com/compute-class 节点选择器引用 ComputeClass 自定义资源:

      spec:
        nodeSelector:
          cloud.google.com/compute-class: non-e2-class
        # Multiple lines are omitted here
    

标准

  • 如需在新集群上启用 Pod 快照,请运行以下命令:

      gcloud container clusters create CLUSTER_NAME \
          --enable-pod-snapshots \
          --cluster-version=CLUSTER_VERSION \
          --workload-pool=PROJECT_ID.svc.id.goog \
          --workload-metadata=GKE_METADATA \
          --location=CONTROL_PLANE_LOCATION
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • CLUSTER_VERSION:新集群的版本,必须为 1.35.3-gke.1234000 或更高版本。
    • PROJECT_ID:您的项目 ID。
    • CONTROL_PLANE_LOCATION:集群控制平面的位置。
  • 如需在现有集群上启用 Pod 快照,请按照以下步骤操作:

    1. 将集群升级到 1.35.3-gke.1234000 版或更高版本:

        gcloud container clusters upgrade CLUSTER_NAME \
            --node-pool=NODE_POOL_NAME \
            --cluster-version=CLUSTER_VERSION \
            --location=CONTROL_PLANE_LOCATION
      

      替换以下内容:

      • CLUSTER_NAME:您的集群的名称。
      • NODE_POOL_NAME:节点池的名称。
      • CLUSTER_VERSION:要将集群升级到的版本,必须为 1.35.3-gke.1234000 或更高版本。
      • CONTROL_PLANE_LOCATION:集群控制平面的位置。
    2. 在集群上启用 Pod 快照:

        gcloud beta container clusters update CLUSTER_NAME \
            --enable-pod-snapshots \
            --location=CONTROL_PLANE_LOCATION
      

      替换以下内容:

      • CLUSTER_NAME:您的集群的名称。
      • CONTROL_PLANE_LOCATION:集群控制平面的位置。

如需在 Standard 集群上的 GKE Sandbox 中运行 Pod,您必须创建或更新启用了 GKE Sandbox 的节点池。如需更新节点池,请使用 --sandbox type=gvisor 标志。如需创建已启用 GKE Sandbox 的节点池,请运行以下命令:

gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --node-version=NODE_VERSION \
    --machine-type=MACHINE_TYPE \
    --location=CONTROL_PLANE_LOCATION \
    --image-type=cos_containerd \
    --sandbox type=gvisor

替换以下内容:

  • NODE_POOL_NAME:新节点池的名称。
  • CLUSTER_NAME:您的集群的名称。
  • NODE_VERSION:用于节点池的版本。
  • MACHINE_TYPE:用于节点的机器类型。
  • CONTROL_PLANE_LOCATION:集群控制平面的位置。

如需详细了解 GKE Sandbox,请参阅利用 GKE Sandbox 强化工作负载隔离。

存储快照

GKE 会将 Pod 快照存储在 Cloud Storage 存储桶中。每个快照都包含应用内存以及 Pod 的 GPU 状态(可选)。如需向 Cloud Storage 进行身份验证,Pod 快照会使用 Pod 的 ServiceAccount 对象,这需要Workload Identity Federation for GKE。

Pod 快照需要以下存储桶配置:

  • 分层命名空间:您必须启用分层命名空间,才能支持更高的每秒读写查询次数。分层命名空间还要求您启用统一存储桶级访问权限。
  • 软删除:由于 Pod 快照使用并行复合上传,因此请停用软删除等数据保护功能。如果您让这些功能保持启用状态,则临时对象的软删除可能会大幅增加您的存储费用。
  • 位置:Cloud Storage 存储桶位置必须与 GKE 集群位于同一位置,因为跨不同区域传输快照可能会影响性能。

如需创建具有所需配置的存储桶,请运行以下命令:

gcloud storage buckets create gs://BUCKET_NAME \
    --uniform-bucket-level-access \
    --enable-hierarchical-namespace \
    --soft-delete-duration=0d \
    --location=LOCATION

替换以下内容:

  • BUCKET_NAME:存储桶的名称。
  • LOCATION:存储桶的位置。

如需查看存储桶创建的选项的完整列表,请参阅 buckets create 命令文档中的标志。

授予工作负载对 Cloud Storage 存储桶的访问权限

默认情况下,GKE 无权访问 Cloud Storage。如需读取和写入 Pod 快照,您必须向工作负载 Pod 使用的 Kubernetes ServiceAccount 对象授予包含相应权限的 IAM 角色,或使用短期令牌启用多租户。

向特定 Kubernetes ServiceAccount 对象授予角色

如需向特定 Kubernetes ServiceAccount 对象授予角色,请按照以下步骤操作:

  1. 如需使用 kubectl 命令与集群通信,请获取集群的凭据:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • CONTROL_PLANE_LOCATION:集群控制平面的位置。
  2. 对于每个 Pod,请按以下步骤操作:

    1. 创建 ServiceAccount 对象:

      kubectl create serviceaccount SERVICEACCOUNT_NAME \
          --namespace=NAMESPACE
      

      替换以下内容:

      • SERVICEACCOUNT_NAME:ServiceAccount 对象的名称。
      • NAMESPACE:Pod 的命名空间。
    2. 向 ServiceAccount 对象授予访问存储桶的权限。根据您的安全要求,选择以下选项之一:

      • 标准权限:授予完整的读取、写入和删除权限。
      • 单次写入权限:防止覆盖或删除已完成的快照文件,但授予删除并行复合上传的临时对象的权限。

      如需授予权限,请运行所选选项对应的命令:

      标准权限

      gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="roles/storage.bucketViewer"
      
      gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="roles/storage.objectUser"
      

      一次性写入权限

      gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="roles/storage.bucketViewer"
      
      gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="roles/storage.objectCreator"
      
      gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="roles/storage.objectViewer"
      
      gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="roles/storage.objectUser" \
          --condition='expression=resource.type == "storage.googleapis.com/Object" && (resource.name.extract("/pages.img_{part}") != "" || resource.name.extract("/fs_checkpoint_pages.img_{part}") != ""),title=allow_pcu_temp_part_cleanup,description=Allow deleting temporary parallel composite upload part objects only'
      

      替换以下内容:

      • BUCKET_NAME:存储桶的名称。
      • PROJECT_NUMBER:您的项目编号。
      • PROJECT_ID:您的项目 ID。
      • NAMESPACE:Pod 的命名空间。
      • SERVICEACCOUNT_NAME:ServiceAccount 对象的名称。

使用短期 token 启用多租户

除了向单个 ServiceAccount 对象授予权限之外,您还可以使用短期有效的范围受限令牌启用多租户。此方法有助于避免与手动 IAM 绑定相关的传播延迟。您无需向每个 ServiceAccount 对象授予权限,而是向 GKE 节点服务账号一次性授予快照存储桶的 Storage Admin 角色 (roles/storage.admin)。然后,节点服务账号会根据需要为特定路径创建短期有效的令牌。

如需通过 Pod 快照启用令牌,需要使用 GKE 1.35.3-gke.1737000 版或更高版本。

如需启用多租户,请按以下步骤操作:

  1. 如需向节点服务账号授予使用存储桶的权限,请运行以下命令:

    gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
        --member="serviceAccount:service-PROJECT_NUMBER@gcp-sa-gkenode.iam.gserviceaccount.com" \
        --role="roles/storage.admin"
    

    替换以下内容:

    • BUCKET_NAME:存储桶的名称。
    • PROJECT_NUMBER:您的项目编号。
  2. 为快照配置存储空间时,请将 tokenSource 字段的值设置为 federatedP4SA。

向 Pod 快照控制器授予对 Cloud Storage 存储桶的访问权限

如需允许 Pod 快照控制器删除 Cloud Storage 存储桶中的快照,您必须向项目中的 GKE 服务代理授予 Storage Object User 角色 (roles/storage.objectUser)。如需授予该角色,请运行以下命令:

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com" \
    --role="roles/storage.objectUser" \
    --condition="expression=resource.name.startsWith(\"projects/_/buckets/BUCKET_NAME\"),title=restrict_to_bucket,description=Restricts access to one bucket only"

替换以下内容:

  • PROJECT_ID:您的项目 ID。
  • PROJECT_NUMBER:您的项目编号。
  • BUCKET_NAME:存储桶的名称。

可选:为 Cloud Storage 存储桶创建托管式文件夹

如需隔离来自互不信任的 Pod 的快照权限(这在多租户用例中非常有用),请创建托管文件夹。如需设置托管文件夹,请按以下步骤操作:

  1. 创建一个自定义 IAM 角色,其中仅包含 Pod 快照所需的权限。运行所选选项对应的命令:

    标准权限

    gcloud iam roles create podSnapshotGcsReadWriter \
        --project=PROJECT_ID \
        --permissions="storage.objects.get,storage.objects.list,storage.objects.create,storage.objects.delete,storage.folders.create"
    

    一次性写入权限

    gcloud iam roles create podSnapshotGcsReadWriter \
        --project=PROJECT_ID \
        --permissions="storage.objects.get,storage.objects.list,storage.objects.create,storage.folders.create"
    

    将 PROJECT_ID 替换为您的项目 ID。

  2. 向目标命名空间中的所有 ServiceAccount 对象授予 Storage Bucket Viewer 角色 (roles/storage.bucketViewer)。此角色允许 ServiceAccount 对象读取存储桶元数据,但不授予它们读取或写入存储桶中对象的权限。

    gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/namespace/NAMESPACE" \
        --role="roles/storage.bucketViewer"
    

    替换以下内容:

    • BUCKET_NAME:存储桶的名称。
    • PROJECT_NUMBER:您的项目编号。
    • PROJECT_ID:您的项目 ID。
    • NAMESPACE:Pod 的命名空间。
  3. 对于需要存储 Pod 快照的每个 ServiceAccount 对象,请按照以下步骤操作:

    1. 为 ServiceAccount 对象创建托管文件夹:

      gcloud storage managed-folders create gs://BUCKET_NAME/FOLDER_PATH/
      

      替换以下内容:

      • BUCKET_NAME:存储桶的名称。
      • FOLDER_PATH:代管式文件夹的路径(例如 my-app-snapshots)。
    2. 向 ServiceAccount 对象授予对代管文件夹的自定义 podSnapshotGcsReadWriter 角色。如需授予权限,请运行所选选项对应的命令:

      标准权限

      gcloud storage managed-folders add-iam-policy-binding gs://BUCKET_NAME/FOLDER_PATH/ \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="projects/PROJECT_ID/roles/podSnapshotGcsReadWriter"
      

      一次性写入权限

      gcloud storage managed-folders add-iam-policy-binding gs://BUCKET_NAME/FOLDER_PATH/ \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="projects/PROJECT_ID/roles/podSnapshotGcsReadWriter"
      
      gcloud storage managed-folders add-iam-policy-binding gs://BUCKET_NAME/FOLDER_PATH/ \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT_NAME" \
          --role="roles/storage.objectUser" \
          --condition='expression=resource.type == "storage.googleapis.com/Object" && (resource.name.extract("/pages.img_{part}") != "" || resource.name.extract("/fs_checkpoint_pages.img_{part}") != ""),title=allow_pcu_temp_part_cleanup,description=Allow deleting temporary parallel composite upload part objects only'
      

      替换以下内容:

      • BUCKET_NAME:存储桶的名称。
      • FOLDER_PATH:代管式文件夹的路径(例如 my-app-snapshots)。
      • PROJECT_NUMBER:您的项目编号。
      • PROJECT_ID:您的项目 ID。
      • NAMESPACE:Pod 的命名空间。
      • SERVICEACCOUNT_NAME:ServiceAccount 对象的名称。

为快照配置存储空间

如需指定 Pod 快照的存储位置,请创建 PodSnapshotStorageConfig 自定义资源:

  1. 将以下清单保存为 example-pod-snapshot-storage-config.yaml。此示例将 GKE 配置为将 Pod 快照存储在 Cloud Storage 存储桶 BUCKET_NAME 内的 FOLDER_PATH/ 路径中:

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotStorageConfig
    metadata:
      name: example-pod-snapshot-storage-config
    spec:
      snapshotStorageConfig:
        gcs:
          bucket: "BUCKET_NAME"
          path: "FOLDER_PATH"
          tokenSource: "TOKEN_SOURCE"
    

    替换以下内容:

    • BUCKET_NAME:Cloud Storage 存储桶的名称。
    • FOLDER_PATH:Cloud Storage 托管文件夹的路径。
    • TOKEN_SOURCE:用于访问的身份提供方。使用 podKSA(默认)或 federatedP4SA 实现多租户。

  2. 应用清单:

    kubectl apply -f example-pod-snapshot-storage-config.yaml
    

后续步骤

了解如何触发 Pod 快照。