触发 Pod 快照

为了缩短 Google Kubernetes Engine (GKE) 工作负载的启动延迟时间,您可以为正在运行的 Pod 创建快照,并从中恢复新 Pod。本文档介绍了如何创建 Pod 快照政策,以及如何通过工作负载或手动触发快照。如需详细了解 Pod 快照的工作原理,请参阅 GKE Pod 快照简介。

平台管理员、运维人员和应用开发者可以使用本文档配置快照政策并触发快照。如需详细了解我们在 Cloud de Confiance by S3NS内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务。

准备工作

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

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如需使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
  • 完成前提条件,并在集群上启用 Pod 快照。如需详细了解如何准备集群和存储,请参阅准备 Pod 快照。

创建快照政策

如需为 Pod 启用快照,请创建一个 PodSnapshotPolicy 自定义资源,并使用与 Pod 标签匹配的选择器:

  1. 将以下清单保存为 example-pod-snapshot-policy.yaml。此示例创建了一个适用于具有 app: my-app 标签的 Pod 的政策。该政策使用您在为 Pod 快照做准备中创建的 example-pod-snapshot-storage-config PodSnapshotStorageConfig 自定义资源来定义快照存储位置:

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotPolicy
    metadata:
      name: example-pod-snapshot-policy
      namespace: NAMESPACE
    spec:
      storageConfigName: example-pod-snapshot-storage-config
      selector:
        matchLabels:
          app: my-app
      triggerConfig:
        type: TRIGGER_TYPE
        postCheckpoint: resume
    

    替换以下内容:

    • NAMESPACE:Pod 的命名空间。使用您在为 Pod 快照做准备中向其授予 Cloud Storage 访问权限的同一命名空间。
    • TRIGGER_TYPE:触发器类型。 支持的值包括:workload(适用于基于工作负载的触发器)或 manual(适用于按需快照)。

    在此示例中,postCheckpoint: resume 设置会在 GKE 创建快照后使 Pod 保持运行状态。

    如需查看可配置字段的完整列表,请参阅 PodSnapshotPolicy 规范。

  2. 应用清单:

    kubectl apply -f example-pod-snapshot-policy.yaml
    

配置其他 Pod 快照政策设置

除了必需的选择器、存储配置和触发器之外,PodSnapshotPolicy 自定义资源还支持可选设置。这些额外设置可控制每个快照捕获的内容、GKE 保留快照的时长以及 GKE 如何对快照进行分组以进行恢复:

  • 快照范围:如需指定要在快照中捕获 Pod 状态的哪些部分,请配置 spec.snapshotScope 字段。支持的值包括 whole-pod(默认)和 rootfs-only。whole-pod 范围会捕获整个 Pod,包括应用状态、内存和文件系统。rootfs-only 范围仅捕获容器根文件系统。rootfs-only 范围需要 GKE 1.35.3-gke.1031000 或更高版本。

  • 自动清理:如需自动清理旧的 PodSnapshot 自定义资源,请使用 spec.retentionConfig 字段配置保留政策。您可以使用 lastAccessTimeout 字段指定时长,例如 7d。此时间段过后,GKE 会删除快照。

  • 快照分组:如需隔离在类似环境但不同上下文中拍摄的快照,请在 spec.snapshotGroupingRules 字段中指定分组标签。例如,在多租户场景中,如果所有用户的基础 Pod 都相同,您可以按用户或群组隔离快照。在恢复期间,GKE 仅从同一标签组中选择快照。如需详细了解此分组如何影响恢复期间的兼容性匹配,请参阅分组规则匹配。

您可以单独配置快照范围、保留和分组设置。以下示例展示了 PodSnapshotPolicy 自定义资源中的所有三项设置:

# Multiple lines are omitted here
spec:
  snapshotScope: rootfs-only
  retentionConfig:
    lastAccessTimeout: 7d
  snapshotGroupingRules:
    groupByLabelValue:
      labels: ["tenant", "environment"]
      groupRetentionPolicy:
        maxSnapshotCountPerGroup: 5

如需查看可配置字段的完整列表,请参阅 PodSnapshotPolicy 规范。

优化快照大小

快照越大,保存和恢复所需的时间就越长。在触发快照之前,请删除 GKE 从快照恢复 Pod 后应用不需要的任何临时文件或应用状态,以缩减快照大小。

使用默认的 whole-pod 快照范围时,GKE Sandbox 会捕获所有容器的完整状态,包括:

  • 应用状态,例如内存和寄存器
  • 对根文件系统和 tmpfs 装载(包括 emptyDir 卷)的更改
  • 内核状态,例如打开的文件描述符、线程和套接字

对于大语言模型 (LLM) 等工作负载,优化快照大小尤为重要。LLM 服务器通常会将模型权重下载到本地存储空间(rootfs 或 tmpfs),然后再将其加载到 GPU 中。当您创建快照时,GKE Sandbox 会同时保存 GPU 状态和模型权重文件。在这种情况下,如果模型大小为 100 GB,则生成的快照大小约为 200 GB(100 GB 的模型文件,加上 100 GB 的 GPU 状态)。应用将模型权重加载到 GPU 后,通常不需要文件系统中的文件即可运行。通过在触发快照之前删除这些模型文件,您可以将快照大小缩减一半,并以显著降低的延迟时间恢复应用。

触发快照

选择以下方法之一来触发快照:

  • 工作负载触发器:如果您可以修改应用,使其在准备好创建快照时发出信号(例如在初始化完成后),请使用此方法。此方法最适合缩短横向伸缩工作负载的启动延迟时间。工作负载触发器在工作负载周期内仅运行一次。

  • 手动触发器:如果您无法修改应用来发出就绪信号,或者您希望按需创建特定 Pod 的快照,请使用此方法。您可以根据需要创建任意数量的手动触发器。

从工作负载触发快照

如需从应用代码中触发快照,请将应用配置为在准备好创建快照时发送信号。如需发出就绪信号,请将值 1 写入 /proc/gvisor/checkpoint 文件,例如,通过运行 echo 1 > /proc/gvisor/checkpoint 命令。写入操作会异步启动快照过程并立即返回。从同一文件描述符读取数据会阻塞读取过程,直到快照或恢复操作完成且工作负载准备好恢复。

在从工作负载触发快照之前,请确保快照政策选择了 Pod。该政策中 triggerConfig.type 字段的值必须设置为 workload。

确切用法因应用而异,但以下示例展示了 Python 应用的快照触发器。如需从此示例工作负载触发快照,请按照以下步骤操作:

  1. 将以下清单保存为 my-app.yaml。在此示例中,app: my-app 标签与示例快照政策中的选择器匹配,并且 runtimeClassName: gvisor 设置在 GKE Sandbox 中运行 Pod:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-app
      namespace: NAMESPACE
      labels:
        app: my-app
    spec:
      serviceAccountName: SERVICEACCOUNT_NAME
      runtimeClassName: gvisor
      containers:
      - name: my-container
        image: python:3.10-slim
        command: ["python3", "-c"]
        args:
          - |
            import time
            def trigger_snapshot():
              try:
                with open("/proc/gvisor/checkpoint", "r+") as f:
                  f.write("1")
                  res = f.read().rstrip()
                  print(f"GKE Pod Snapshot: {res}")
              except FileNotFoundError:
                print("GKE Pod Snapshot file does not exist -- "
                      "Pod Snapshots is disabled")
                return
            i = 0
            while True:
              print(f"Count: {i}", flush=True)
              if (i == 20): # Simulate readiness at the 20th count
                trigger_snapshot()
              i += 1
              time.sleep(1)
        resources:
          limits:
            cpu: "500m"
            memory: "512Mi"
          requests:
            cpu: "250m"
            memory: "256Mi"
    

    替换以下内容:

    • NAMESPACE:Pod 的命名空间。
    • SERVICEACCOUNT_NAME:您在准备 Pod 快照中向其授予 Cloud Storage 访问权限的 ServiceAccount 对象的名称。
  2. 部署应用:

    kubectl apply -f my-app.yaml
    

    应用启动并发出就绪信号后,GKE Sandbox 会创建快照。如需确认快照是否成功,请参阅验证快照。

手动触发快照

在手动触发快照之前,请确保目标 Pod 正在运行,并且快照政策选择了该 Pod。该政策中 triggerConfig.type 字段的值必须设置为 manual。

如需为特定 Pod 手动触发按需快照,请按照以下步骤创建 PodSnapshotManualTrigger 自定义资源:

  1. 将以下清单保存为 example-manual-trigger.yaml。此示例会为名为 my-pod 的 Pod 触发快照:

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotManualTrigger
    metadata:
      name: example-manual-trigger
      namespace: NAMESPACE
    spec:
      targetPod: my-pod
    

    将 NAMESPACE 替换为 Pod 的命名空间。

  2. 应用清单:

    kubectl apply -f example-manual-trigger.yaml
    
  3. 如需确认快照已成功触发,请检查 PodSnapshotManualTrigger 自定义资源的 status 部分:

    kubectl get podsnapshotmanualtriggers.podsnapshot.gke.io \
        example-manual-trigger \
        --namespace NAMESPACE -o yaml
    

    将 NAMESPACE 替换为 Pod 的命名空间。

    如果触发器成功,则 status.conditions 字段会显示检查点已完成,status.snapshotCreated 字段会显示所创建的 PodSnapshot 自定义资源的名称。

验证快照

如需确认 GKE 已创建快照,请查看事件记录中是否有 GKEPodSnapshotting 事件:

kubectl get events \
    -o custom-columns=NAME:involvedObject.name,CREATIONTIME:.metadata.creationTimestamp,REASON:.reason,MESSAGE:.message \
    --namespace NAMESPACE \
    --field-selector involvedObject.name=POD_NAME,reason=GKEPodSnapshotting

替换以下内容:

  • NAMESPACE:Pod 的命名空间。
  • POD_NAME:您的 pod 的名称。

输出类似于以下内容:

NAME                                    CREATIONTIME           REASON               MESSAGE
default/5b449f9c7c-bd7pc                2025-11-05T16:25:11Z   GKEPodSnapshotting   Successfully checkpointed the pod to PodSnapshot

MESSAGE 列显示 Successfully checkpointed the pod to PodSnapshot,这确认了 GKE 已将 Pod 状态保存到 PodSnapshot 自定义资源。如需查看和管理 PodSnapshot 自定义资源,请参阅管理快照。

后续步骤