Snapshot 部署
项目仍在早期(README 写明 under construction ),不能当生产系统用。本文只覆盖:在已有 GPU Kubernetes 集群上装 Snapshot 控制面和节点 agent,并做一次 capture / restore 通路检查。
官方 chart 说明:charts/snapshot/README.md。组件职责:snapshot0-snapshot介绍。GPU 侧依赖:snapshot4-cuda-checkpoint分析、snapshot5-cuda-checkpoint依赖。restore Pod 合同:docs/restore-pod-contract.md。
1. 会装上什么
一次 Helm release 装这些东西(默认 release 名 snapshot):
| 组件 | 形态 | 作用 |
|---|---|---|
| operator | Deployment | 调和 SnapshotJob / PodSnapshot / PodSnapshotContent,建工单、镜像状态、清孤儿目录 |
| agent | 特权 DaemonSet(hostPID / hostIPC / hostNetwork) |
在 GPU 节点上真正 dump / restore;调 CRIU 和 cuda-checkpoint-helper |
snapshot-pvc |
RWX PVC(可改成已有 PVC) | 所有 agent 挂同一块盘存 artifact。workload Pod 不挂这块盘 |
| CRD | PodSnapshot、PodSnapshotContent、SnapshotJob |
用户 API |
| RBAC / seccomp | ClusterRole 等;CRIU 用的 block-iouring profile |
agent 碰节点、堵 io_uring |
装 一份 即可覆盖全集群。agent 看所有 namespace 里的工单和 restore 注解。
调用方只跟 kube-apiserver 打交道:capture 写 CR,restore 给 Pod 打 nvidia.com/restore-from。不要给 agent 另开 HTTP/gRPC。
2. 前置条件
| 项 | 要求 |
|---|---|
| 节点架构 | x86_64 / amd64 。agent 镜像和上游 cuda-checkpoint 目前没有别的架构 |
| GPU 节点 | 节点上有 NVIDIA GPU;chart 默认 nodeSelector: nvidia.com/gpu.present=true,并容忍 nvidia.com/gpu taint |
| 驱动 | 580.xx+ (cuCheckpoint*)。多卡 --launch-job 需要 610+ |
| 运行时 | containerd (默认)或 CRI-O (runtime.type=crio) |
| 权限 | 集群允许特权 DaemonSet + hostPID/IPC/Network |
| 存储 | 能供给 ReadWriteMany 的 StorageClass。多节点 agent 同时挂同一 PVC |
| 工具 | kubectl、helm;自己编镜像还要 Docker buildx |
| 内核 | restore 用的 ns-bind-mount 需要 Linux ≥ 5.12 (mount_setattr) |
OpenShift:额外设 openshift.enabled=true,runtime.type=crio。
PVC accessMode 不能原地改 。已有 RWO 盘不能直接当 snapshot PVC。需要 RWX 新盘,必要时把旧数据拷过去,再 storage.pvc.create=false + storage.pvc.name={新PVC}。
3. 镜像
chart 默认:
text
ghcr.io/ai-dynamo/snapshot/operator:{chart appVersion}
ghcr.io/ai-dynamo/snapshot/agent:{chart appVersion}
当前 charts/snapshot/Chart.yaml 的 appVersion 是 0.1.0。拉不到就改 tag,或本仓库自己编:
bash
make docker-build-operator TAGS=dev
make docker-build-agent TAGS=dev
推到集群能拉的仓库后,Helm 覆盖:
bash
--set image.operator.repository={仓库}/operator \
--set image.operator.tag=dev \
--set image.agent.repository={仓库}/agent \
--set image.agent.tag=dev
agent 镜像里已经带了:从源码编的 CRIU、cuda-checkpoint-helper、官方 cuda-checkpoint、restore 用的 /snapshot-binaries bundle。节点上还要有 真的 libcuda.so(驱动 / NVIDIA Container Toolkit 注入),stubs 不能冻 GPU。
4. 安装
仓库根目录:
bash
export NAMESPACE=snapshot
helm upgrade --install snapshot ./charts/snapshot \
--namespace "${NAMESPACE}" \
--create-namespace \
--set storage.pvc.create=true
没有默认 StorageClass 时加上:
bash
--set storage.pvc.storageClass={RWX 的 class}
已有 RWX PVC:
bash
helm upgrade --install snapshot ./charts/snapshot \
--namespace "${NAMESPACE}" \
--create-namespace \
--set storage.pvc.create=false \
--set storage.pvc.name=my-snapshot-pvc
CRI-O / OpenShift:
bash
helm upgrade --install snapshot ./charts/snapshot \
--namespace "${NAMESPACE}" --create-namespace \
--set storage.pvc.create=true \
--set runtime.type=crio \
--set openshift.enabled=true
常用值(完整列表见 charts/snapshot/values.yaml):
| 值 | 含义 | 默认 |
|---|---|---|
storage.pvc.create |
是否建 snapshot-pvc |
true |
storage.pvc.name |
PVC 名 | snapshot-pvc |
storage.pvc.size |
容量 | 1Ti |
storage.pvc.basePath |
agent 里挂载路径 | /checkpoints |
runtime.type |
containerd / crio |
containerd |
seccomp.deploy |
部署 CRIU seccomp(字段名是 deploy,不是 enabled) |
true |
crdUpgrade.enabled |
operator init 容器 server-side apply CRD | true |
rbac.create |
建 RBAC | true |
helm upgrade 不会 更新 CRD。默认靠 operator 的 crd-installer init 容器补。关掉 crdUpgrade.enabled 后要自己:
bash
kubectl apply --server-side --force-conflicts -f ./charts/snapshot/crds/
5. 验收
bash
kubectl get pvc snapshot-pvc -n "${NAMESPACE}"
kubectl rollout status deployment/snapshot-operator -n "${NAMESPACE}"
kubectl rollout status daemonset/snapshot-agent -n "${NAMESPACE}"
kubectl get pods -n "${NAMESPACE}" -l app.kubernetes.io/name=snapshot -o wide
kubectl logs deployment/snapshot-operator -n "${NAMESPACE}" -c crd-installer
期望:
- PVC
Bound - operator Ready
- 每台目标 GPU 节点上有一个 agent Running(不是只有一台)
crd-installer日志里能看到三个 CRDApplied/unchanged
agent 起不来时先看:节点有没有 nvidia.com/gpu.present=true、特权/SCC、CRI socket 路径、镜像能否拉取、PVC 是否 RWX。
6. 装完之后怎么用
6.1 两条 API 路径
Capture 必须 operator + 本机 agent:
text
调用方创建 PodSnapshot 或 SnapshotJob
→ operator 写成 cluster 级 PodSnapshotContent(钉死 nodeName)
→ 源 Pod 所在节点的 agent dump
→ artifact 写到共享 PVC
Restore 不经过 operator。 新 Pod 带注解,调度到哪台节点,那台节点的 agent 执行 restore。那台机器上也要有 agent,并且能读同一 PVC。
yaml
metadata:
annotations:
nvidia.com/restore-from: snapshot-name
# 可选:一份快照灌进多个容器
# nvidia.com/restore-container-map: main=engine-0,main=engine-1
restore Pod 还要满足合同:提供控制卷、CRIU seccomp 配置和等待 agent 灌入状态的惰性入口。Go 侧可用 api/podcontract 的 Build。placeholder 的临时目录必须可写,供 agent bind-mount 工具包。
6.2 SnapshotJob(一次「起 Pod 再拍」)
适合:用 pod 模板把 worker 拉起来,等 Ready,再打成 PodSnapshot。镜像、GPU 请求、DRA、shm 都是调用方自己的。完成条件是 dump 成功 并且 helper 容器干净退出,不是 CRIU 一结束就算完。
6.3 snapshotctl(调试用)
不是主用户路径。chart 已经装好、agent 在跑之后:
bash
# 需要 operator:会建 PodSnapshot
snapshotctl checkpoint \
--manifest ./worker-pod.yaml \
--snapshot worker-snapshot \
--container main \
--namespace "${NAMESPACE}"
# 不需要 operator:只给新 Pod 打注解并创建
snapshotctl restore \
--manifest ./worker-pod.yaml \
--namespace "${NAMESPACE}" \
--snapshot worker-snapshot
manifest 必须是 Pod ,不是 Deployment/Job。checkpoint 必须 --container 指定唯一目标容器(当前 API 一次只拍一个容器)。
多卡:snapshotctl --cuda-checkpoint-wrap 会把容器命令包成 cuda-checkpoint --launch-job ...。打开后,源镜像和 placeholder 里 cuda-checkpoint 绝对路径必须一致。单卡可以不包。
6.4 看结果
bash
kubectl get podsnapshots,podsnapshotcontents,snapshotjobs -A
kubectl describe podsnapshot {name} -n {ns}
kubectl logs daemonset/snapshot-agent -n "${NAMESPACE}"
PodSnapshot Ready=True 才能拿去 restore。restore 看 Pod 条件 nvidia.com/Restored:全成功 / 部分成功 / 失败。部分成功和失败都是终态,重试要新建 restore Pod。
7. 和工作负载相关的硬约束
- 源 Pod 所在节点必须有 agent;dump 不能换到别的节点做。
- restore 落点由 kube-scheduler 决定(GPU、亲和性、驱动兼容),不绑死原机。
- 源/目标 GPU 张数必须一致;型号和驱动要兼容。
- 冻 GPU 走
cuda-checkpoint-helper,不走 CRIUcuda_plugin。 helper 的 lock/checkpoint 失败则整次 capture 失败。 - placeholder / 源镜像 glibc 要和 agent 基座对得上(当前 agent 基座是 Ubuntu 24.04 这一档)。
- 当前
v1alpha1:一次 capture 恰好一个容器。
8. 卸载
bash
helm uninstall snapshot -n "${NAMESPACE}"
chart 不会自动删 PVC。要清掉盘上的 artifact:
bash
kubectl delete pvc snapshot-pvc -n "${NAMESPACE}"
CRD 也可能留下。确认没有业务对象后再删:
bash
kubectl delete crd \
podsnapshots.nvidia.com \
podsnapshotcontents.nvidia.com \
snapshotjobs.nvidia.com
9. 和 e2e 的关系
e2e/ 会在目标集群上 helm install 同一份 chart 再跑生命周期测试。集群已有同名 release 时,要么复用要么先卸。chart 的 ClusterRole 名是固定的(如 snapshot-operator),两个 namespace 各装一份会抢这些名字。
本地直连集群示例见 e2e/README.md 的 Direct Mode。
参考
charts/snapshot/README.md、charts/snapshot/values.yamloperator/cmd/snapshotctl/README.mddocs/restore-pod-contract.md- snapshot0-snapshot介绍
- snapshot4-cuda-checkpoint分析
- snapshot5-cuda-checkpoint依赖