Google Kubernetes Engine (GKE) Pod 快照通过恢复正在运行的 Pod 的快照来帮助缩短工作负载启动延迟时间。Pod 快照会保存整个 Pod 状态,包括内存和对根文件系统的更改。创建新副本时,系统会恢复快照,而不是从全新状态初始化 Pod。然后,Pod 会从截取快照的点恢复执行。
本文档介绍了如何为工作负载启用和配置 GKE Pod 快照。
如需详细了解 Pod 快照的工作原理,请参阅 Pod 快照简介。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 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 中运行。
如需在集群上启用该功能,请完成以下任一步骤:
如需在新集群上启用 Pod 快照,请运行以下命令:
gcloud beta container clusters create CLUSTER_NAME \ --enable-pod-snapshots \ --cluster-version=CLUSTER_VERSION \ --workload-pool=PROJECT_ID.svc.id.goog \ --workload-metadata=GKE_METADATA替换以下内容:
CLUSTER_NAME:您的集群的名称。CLUSTER_VERSION:新集群的版本,必须为 1.34.1-gke.3084001 或更高版本。PROJECT_ID:您的项目 ID。
如需在现有集群上启用 Pod 快照,请完成以下步骤:
将集群更新到 1.34.1-gke.3084001 版或更高版本:
gcloud container clusters upgrade CLUSTER_NAME \ --node-pool=NODEPOOL_NAME \ --cluster-version=CLUSTER_VERSION替换以下内容:
CLUSTER_NAME:您的集群的名称。NODEPOOL_VERSION:节点池的名称。CLUSTER_VERSION:要将新集群更新到的版本,必须为 1.34.1-gke.3084001 或更高版本。
在集群上启用 Pod 快照:
gcloud container clusters update CLUSTER_NAME \ --workload-pool=PROJECT_ID .svc.id.goog" \ --enable-pod-snapshots将
PROJECT_ID替换为您的项目 ID。
在 Standard 集群上启用 GKE Sandbox:
gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --node-version=NODE_VERSION \ --machine-type=MACHINE_TYPE \ --image-type=cos_containerd \ --sandbox type=gvisor执行以下变量替换操作:
NODE_POOL_NAME:新节点池的名称。NODE_VERSION:用于节点池的版本。MACHINE_TYPE:用于节点的机器类型。
如需详细了解如何使用 gVisor,请参阅使用 GKE Sandbox 隔离工作负载。
商店快照
Pod 快照存储在 Cloud Storage 存储分区中,其中包含内存和(可选)GPU 状态。Pod 快照需要 Workload Identity Federation for GKE 来启用并使用 Pod 的服务账号向 Cloud Storage 进行身份验证。
Pod 快照要求存储分区具有以下配置:
- 分层命名空间:必须启用,才能实现更高的每秒读写查询次数。分层命名空间还要求启用统一存储分区级访问权限。
- 软删除:由于 Pod 快照使用并行复合上传,因此您应停用软删除等数据保护功能。如果保持启用状态,删除临时对象可能会大幅增加您的存储空间费用。
- 位置:Cloud Storage 存储分区位置必须与 GKE 集群位置相同,因为如果跨不同区域传输快照,性能可能会受到影响。
创建 Cloud Storage 存储桶
如需创建必需的存储分区和权限,请完成以下步骤:
创建 Cloud Storage 存储分区。 以下命令会创建一个具有所需配置的存储分区:
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 使用的 Kubernetes 服务账号 (KSA) 授予 IAM 权限。
获取凭据,以便您可以使用
kubectl命令与集群通信:gcloud container clusters get-credentials "CLUSTER_NAME"对于每个 Pod,请完成以下步骤:
为每个 Pod 创建 KSA:
kubectl create serviceaccount "KSA_NAME" \ --namespace "NAMESPACE"替换以下内容:
KSA_NAME:您的 KSA 的名称。NAMESPACE:Pod 的命名空间。
向 KSA 授予访问相应存储分区的权限:
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/KSA_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/KSA_NAME" \ --role="roles/storage.objectUser"替换以下内容:
PROJECT_NUMBER:您的项目编号。PROJECT_ID:您的项目 ID。
(可选)为 Cloud Storage 存储分区创建受管理的文件夹
创建文件夹可让您隔离来自互不信任的 Pod 的快照权限,这在多租户使用情形中非常有用。如需设置受管理的文件夹,请完成以下步骤:
创建仅包含 Pod 快照所需权限的自定义 IAM 角色:
gcloud iam roles create podSnapshotGcsReadWriter \ --project="PROJECT_ID" \ --permissions="storage.objects.get,storage.objects.create,storage.objects.delete,storage.folders.create"向目标命名空间中的所有 KSA 授予
roles/storage.bucketViewer角色。此角色允许 KSA 读取存储分区元数据,但不授予对存储分区中对象的读取或写入权限。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"替换以下内容:
PROJECT_NUMBER:您的项目编号。PROJECT_ID:您的项目 ID。
对于需要存储 Pod 快照的每个 KSA,请完成以下步骤:
为 KSA 创建托管文件夹:
gcloud storage managed-folders create "gs://BUCKET_NAME/FOLDER_PATH/"将
FOLDER_PATH替换为受管理文件夹的路径,例如my-app-snapshots。向 KSA 授予受管文件夹的自定义
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/KSA_NAME" \ --role="projects/PROJECT_ID/roles/podSnapshotGcsReadWriter"将
KSA_NAME替换为 KSA 的名称。
为快照配置存储空间
如需指定快照文件的存储位置,请创建 PodSnapshotStorageConfig 资源。
以下示例将 GKE 配置为将 Pod 快照存储在 Cloud Storage 存储分区 BUCKET_NAME 内的
FOLDER_PATH/路径中。将以下清单保存为example-pod-snapshot-storage-config:apiVersion: podsnapshot.gke.io/v1alpha1 kind: PodSnapshotStorageConfig metadata: name: example-pod-snapshot-storage-config namespace: NAMESPACE spec: snapshotStorageConfig: gcs: bucket: "BUCKET_NAME" path: "FOLDER_PATH"替换以下内容:
NAMESPACE:Pod 的命名空间。 默认情况下,此属性为default。BUCKET_NAME:Cloud Storage 存储桶的名称。FOLDER_PATH:Cloud Storage 受管文件夹的路径。
应用清单:
kubectl apply -f example-pod-snapshot-storage-config.yaml
创建快照政策
如需为 Pod 启用快照,请创建一个 PodSnapshotPolicy 资源,其中包含与 Pod 标签匹配的选择器。
以下示例创建了一项政策,该政策适用于具有
app: my-app标签的 Pod,并使用example-pod-snapshot-storage-config存储配置。将以下清单保存为example-pod-snapshot-policy.yaml:apiVersion: podsnapshot.gke.io/v1alpha1 kind: PodSnapshotPolicy metadata: name: example-pod-snapshot-policy namespace: NAMESPACE spec: storageConfigName: example-pod-snapshot-storage-config selector: matchLabels: app: my-app triggerConfig: type: workload postCheckpoint: resume应用清单:
kubectl apply -f example-pod-snapshot-policy.yaml --namespace NAMESPACE
优化快照大小
当触发 Pod 快照时,gVisor 会捕获所有容器的完整状态,包括:
- 应用状态,例如内存和寄存器
- 对根文件系统和
tmpfs(包括emptyDir卷)的更改 - 内核状态,例如打开的文件描述符、线程和套接字
快照的大小由以下因素决定。较大的快照需要更长时间才能保存和恢复。为了优化性能,在触发快照之前,您应该清理在从快照恢复 Pod 后不需要的任何应用状态或文件。
优化快照大小对于大语言模型 (LLM) 等工作负载尤为重要。LLM 服务器通常会将模型权重下载到本地存储空间(rootfs 或 tmpfs),然后再将其加载到 GPU 中。拍摄快照时,系统会保存 GPU 状态和模型权重文件。在这种情况下,如果模型为 100 GB,则生成的快照约为 200 GB(100 GB 的模型文件,加上 100 GB 的 GPU 状态)。将模型权重加载到 GPU 后,应用通常不需要文件系统上的文件即可运行。通过在触发快照之前删除这些模型文件,您可以将快照大小减少一半,并以显著更低的延迟恢复应用。
从工作负载触发快照
如需从应用代码内触发快照,请将应用配置为在准备好拍摄快照时发送信号。如需发出就绪信号,请将 1 写入 /proc/gvisor/checkpoint 文件,例如 echo 1 > /proc/gvisor/checkpoint.。写入操作会异步启动快照进程,并立即返回。从同一文件描述符读取数据会阻塞读取进程,直到快照和恢复都完成且工作负载准备好恢复为止。
具体用法因应用而异,但以下示例展示了 Python 应用的快照触发器。如需从此示例工作负载触发快照,请完成以下步骤:
将以下清单保存为
my-app.yaml:apiVersion: v1 kind: Pod metadata: name: my-app namespace: NAMESPACE labels: app: my-app spec: serviceAccountName: KSA_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 except OSError as e: return e i = 0 while True: print(f"Count: {i}", flush=True) if (i == 20): #simulate the application being ready to snapshot at 20th count trigger_snapshot() i += 1 time.sleep(1) resources: limits: cpu: "500m" memory: "512Mi" requests: cpu: "250m" memory: "256Mi"部署应用:
kubectl apply -f my-app.yaml如需验证是否已拍摄快照,请检查
GKEPodSnapshotting事件的事件历史记录:kubectl get events -o \ custom-columns=NAME:involvedObject.name,CREATIONTIME:.metadata.creationTimestamp,REASON:.reason,MESSAGE:.message \ --namespace NAMESPACE \ --field-selector involvedObject.name=my-app,reason=GKEPodSnapshotting输出将类似以下内容:
NAME CREATIONTIME REASON MESSAGE default/5b449f9c7c-bd7pc 2025-11-05T16:25:11Z GKEPodSnapshotting Successfully checkpointed the pod to PodSnapshot
管理快照
创建 Pod 快照时,系统会创建一个 PodSnapshot CRD 资源来存储该时间点的 Pod 状态。
如需查看命名空间中的所有 PodSnapshot 资源,请运行以下命令:
kubectl get podsnapshots.gke.io --namespace NAMESPACE
输出将类似以下内容:
NAME STATUS POLICY AGE
de334898-1e7a-4cdb-9f2e-7cc2181c29e4 AllSnapshotsAvailable example-policy 47h
通过快照恢复工作负载
如需从最新快照恢复工作负载,您可以在拍摄快照后删除现有 Pod,然后重新部署 Pod。或者,您也可以部署具有相同规范的新 Pod。GKE 会自动从匹配的快照恢复 Pod。
以下步骤展示了如何通过删除并重新部署 Pod,从匹配的快照中恢复 Pod:
删除 Pod:
kubectl delete -f POD_NAME.yaml将
POD_NAME替换为您的 Pod 名称,例如my-app。重新应用 Pod:
kubectl apply -f POD_NAME.yaml查看日志以确认快照恢复:
kubectl logs my-app --namespace NAMESPACE输出取决于您配置应用的方式。在示例应用中,当发生恢复操作时,日志会显示
GKE Pod Snapshot: restore。
停用快照
移除 PodSnapshotPolicy CRD 会阻止对 Pod 进行快照和恢复。正在运行的 Pod 不受资源删除的影响。不过,如果您在保存或恢复 Pod 时删除政策,Pod 可能会进入失败状态。
如需针对受政策管理的新 Pod 停用快照和恢复功能,请运行以下命令来删除 PodSnapshotPolicy:
kubectl delete podsnapshotpolicies.podsnapshot.gke.io SNAPSHOT_POLICY --namespace=NAMESPACE
将 SNAPSHOT_POLICY 替换为您要删除的 PodSnapshotPolicy 的名称,例如 example-pod-snapshot-policy。
您还可以删除特定的 PodSnapshot 资源,以便不再从该特定快照恢复 Pod。删除 PodSnapshot 资源也会移除存储在 Cloud Storage 中的文件。
如需防止特定快照用于未来的恢复,请运行以下命令来删除 PodSnapshot 对象:
kubectl delete podsnapshots.podsnapshot.gke.io POD_SNAPSHOT_NAME --namespace=NAMESPACE
将 POD_SNAPSHOT_NAME 替换为要删除的快照的名称,例如 example-podsnapshot。
后续步骤
- 详细了解 Pod 快照概念。
- 请参阅 Pod 快照自定义资源定义 (CRD):