Zarf 迁移手册
本文用于指导已部署 HAMi Enterprise/AI Platform 的集群迁移到 Zarf 离线包部署。适用对象是负责集群交付、升级和运维的客户侧 SRE、平台工程师或 Kubernetes 管理员。
文中的包名、组件名和 values 文件名请按实际交付包替换。示例中使用:
<PACKAGE_FILE> # HAMi Enterprise Zarf 主部署包,例如 hami-enterprise-*.tar.zst
<VALUES_FILE> # 迁移时使用的 values 文件,例如 my-overrides.yaml
推荐迁移路线
先判断当前 HAMi Enterprise 是怎么安装的:
--adopt-existing-resources 和 --force-conflicts 是 2 个重要的 zarf package deploy 参数。
| 当前状态 | 推荐做法 | 默认使用 --adopt-existing-resources | 默认使用 --force-conflicts |
|---|---|---|---|
| 集群里还没有 HAMi Enterprise | 直接使用 Zarf 部署 | 否 | 否 |
| 已有同名 Helm release | 用 Zarf 包接管后续部署和升级入口 | 否 | 否 |
| 已有不同名 Helm release | 建议维护窗口内迁移,不建议两个 release 管同一批资源 | 视情况 | 否 |
资源由 Kustomize 或 kubectl apply 创建 | 使用 --adopt-existing-resources 接管资源 | 是 | 仅字段冲突时 |
只是部分字段被 HPA 或人工 kubectl 改过 | 正常部署,遇到 SSA 字段冲突时再处理 | 否 | 必要时 |
不建议让旧 Helm release 和 Zarf 管理的 release 长期同时管理同一批对象。后续任何一边执行 upgrade、rollback 或 uninstall,都可能影响另一边已经接管的资源。
使用 Zarf 安装组件带来的限制
镜像改写范围应通过标签明确控制
建议在初始化时使用 zarf init --agent-mutation-policy=labeled。此策略只改写带 zarf.dev/agent: mutate 标签的资源,或位于带该标签 Namespace 中的资源;需要保留原镜像地址的单个工作负载可标记 zarf.dev/agent: ignore,且资源标签优先于 Namespace 标签。因此,同一集群甚至同一 Namespace 中可以按资源划分是否由 Zarf 改写,不再需要让 Agent 默认接管全部业务 Namespace。需要注意:只有已经打入 Zarf package 的镜像才能在离线环境中被改写并拉取;修改标签后还需重新创建 Pod,已创建 Pod 不会自动变化。
同一批资源应由单一交付链管理
Zarf 通过 Helm 管理 package 中的 Chart release。对同一批 Kubernetes 资源再并行使用另一套原生 Helm 流程,仍可能产生 release ownership、字段所有权和升级顺序冲突。日常升级应继续使用新的 Zarf package;若确需把已有资源交给 Zarf 管理,应先核对 release 和资源范围,再使用 --take-ownership。--force-conflicts 仅用于确认可以覆盖的 Server-Side Apply 字段冲突,不应作为常规安装参数。
迁移前准备
1. 确认工具可用
kubectl version
kubectl get nodes
zarf version
如果目标环境没有单独安装 Helm,可以使用 Zarf 自带的 Helm:
zarf tools helm version
zarf tools helm list -A
2. 确认当前安装方式
查看当前 Helm release:
zarf tools helm list -A
如果看到 HAMi Enterprise 对应 release,记录它的 namespace 和 release name。常见情况是:
namespace: hami-system
release: hami
查看 HAMi 相关资源:
kubectl get ns hami-system
kubectl -n hami-system get pods,deploy,ds,svc,cm,secret
查看资源上的 Helm 归属信息:
kubectl -n hami-system get deploy,ds,svc,cm,secret,sa,role,rolebinding \
-o custom-columns='KIND:.kind,NAME:.metadata.name,MANAGED_BY:.metadata.labels.app\.kubernetes\.io/managed-by,RELEASE:.metadata.annotations.meta\.helm\.sh/release-name,RELEASE_NS:.metadata.annotations.meta\.helm\.sh/release-namespace'
查看 HAMi 相关集群级资源:
kubectl get clusterrole,clusterrolebinding,mutatingwebhookconfiguration,validatingwebhookconfiguration \
-o name | grep -i hami
3. 备份现有配置和状态
如果当前是 Helm release:
zarf tools helm -n hami-system get values <OLD_RELEASE> -o yaml > hami-current-values.yaml
zarf tools helm -n hami-system get manifest <OLD_RELEASE> > hami-current-manifest.yaml
zarf tools helm -n hami-system status <OLD_RELEASE> > hami-current-status.txt
如果当前不是 Helm 管理,也建议导出现有 YAML:
kubectl -n hami-system get deploy,ds,svc,cm,secret,sa,role,rolebinding -o yaml > hami-current-resources.yaml
保存当前运行状态:
kubectl -n hami-system get pods -o wide
kubectl get nodes --show-labels
kubectl get events -A --sort-by=.lastTimestamp | tail -100
如果集群里已有 HAMi license Secret 或客户侧自定义配置,请一并备份。
4. 准备迁移用 values
通常可以从现有 Helm values 开始整理:
cp hami-current-values.yaml <VALUES_FILE>
请重点核对:
-
是否启用 DRA。
-
hami-scheduler副本数是否适合集群规模。 -
是否启用 scheduler leader election。
-
kube-scheduler镜像版本是否与目标 Kubernetes 版本匹配。 -
GPU 节点是否使用
gpu=on标签。 -
是否需要保留已有 webhook、RBAC、Service、ConfigMap 的名称。
部署前离线检查
部署前建议先查看 values 合并结果:
zarf package inspect values-files <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true"
再查看 Zarf 包将要部署的 manifests:
zarf package inspect manifests <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true" \
> hami-zarf-rendered.yaml
检查重点:
-
目标 namespace 是否正确。
-
目标 release name 是否与迁移方案一致。
-
资源名称是否与现有资源对应。
-
镜像是否都来自离线包或目标环境可访问的 registry。
-
values 是否正确覆盖了当前集群需要的配置。
场景一:已有同名 Helm release
适用条件:
-
当前 HAMi Enterprise 已由 Helm 安装。
-
旧 release name 与 Zarf 包中的 HAMi release name 一致。
-
namespace 一致。
-
后续希望统一通过 Zarf 包部署和升级。
这种情况下,通常按 Helm upgrade 思路迁移。不要默认添加 --adopt-existing-resources 或 --force-conflicts。
执行迁移:
zarf package deploy <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true" \
--confirm
迁移后检查:
zarf package list
zarf tools helm -n hami-system status hami
kubectl -n hami-system get pods
kubectl -n hami-system rollout status deploy/hami-scheduler
迁移完成后,请把日常升级入口切换到 Zarf 包。除非是在执行明确的回退方案,否则不要再用旧 Helm 流程直接升级同一个 release。
场景二:已有不同名 Helm release
如果旧 release name 与 Zarf 包中的 release name 不一致,这是高风险迁移。不要直接部署一个新的 Zarf release 去覆盖同一批资源。
推荐在维护窗口内选择一种方案:
| 方案 | 适用情况 | 说明 |
|---|---|---|
| 使用与旧 release name 一致的 Zarf 包 | 希望尽量原地迁移 | 需要确认交付包中的 release name 已匹配旧环境 |
| 卸载旧 release 后部署 Zarf | 可以接受短暂停机或重建 | 生命周期最清晰 |
使用 --adopt-existing-resources 接管 | 资源必须保留,且不能重建 | 需要逐项核对资源归属,风险较高 |
如果选择卸载旧 release 后部署 Zarf,先确认已经备份 values、manifest、license Secret 和必要配置。然后在维护窗口内执行:
zarf tools helm -n hami-system uninstall <OLD_RELEASE>
zarf package deploy <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true" \
--confirm
如果选择接管已有资源,至少先确认:
-
旧 Helm release 后续不会再执行 upgrade、rollback 或 uninstall。
-
Zarf 渲染出的资源名称与现有资源能够对应。
-
资源所在 namespace 没有混入其他系统的同名或同类资源。
-
已有完整备份,并且有维护窗口。
接管命令示例:
zarf package deploy <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true" \
--adopt-existing-resources \
--confirm
只有部署日志明确显示 Server-Side Apply 字段冲突,并且确认这些字段应由 Zarf/Helm 接管时,才考虑叠加
--force-conflicts:
zarf package deploy <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true" \
--adopt-existing-resources \
--force-conflicts \
--confirm
这不是默认迁移命令,只用于已经确认接管范围和字段冲突来源的情况。
场景三:现有资源由 Kustomize 或 kubectl apply 管理
如果现有 HAMi Enterprise 资源不是 Helm release,而是通过 Kustomize 或 kubectl apply 创建,迁移重点是把这些资源纳入
Zarf 管理的 Helm chart。
推荐流程:
-
导出现有 YAML。
-
使用 Zarf 渲染目标 manifests。
-
对比资源名称、namespace、labels、annotations 和关键 spec。
-
使用
--adopt-existing-resources接管。 -
只有遇到 Server-Side Apply 字段冲突时,再使用
--force-conflicts。
接管命令:
zarf package deploy <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true" \
--adopt-existing-resources \
--confirm
如果失败信息明确是字段 ownership 冲突,再执行:
zarf package deploy <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true" \
--adopt-existing-resources \
--force-conflicts \
--confirm
Prometheus 和 GPU Operator
迁移 HAMi Enterprise 不等于必须同时接管 Prometheus 或 NVIDIA GPU Operator。
如果集群已经有 Prometheus 或 GPU Operator,建议先只迁移 HAMi:
zarf package deploy <PACKAGE_FILE> \
--components=hami-deploy-scripts,hami \
--values=<VALUES_FILE> \
--features="values=true" \
--confirm
需要迁移 Prometheus 或 GPU Operator 时,请分别按它们自己的 release、namespace、values 和资源归属做评估。
特别注意:
-
如果集群已有 GPU Operator,通常不要重复部署 Zarf 包里的
gpu-operatorcomponent。 -
如果 GPU Operator 默认 NVIDIA device-plugin 与 HAMi device-plugin 冲突,应通过 GPU Operator values 禁用默认 device-plugin。
-
--force-conflicts不能解决两个 device-plugin 同时运行导致的运行时冲突。
迁移后验收
检查 Zarf 包状态:
zarf package list
检查 Helm release:
zarf tools helm -n hami-system status hami
zarf tools helm -n hami-system get values hami
检查核心组件:
kubectl -n hami-system get pods -o wide
kubectl -n hami-system rollout status deploy/hami-scheduler
kubectl get nodes --show-labels | grep gpu=on
检查证书和 GPU 调度链路:
bash collect-hami-license-info.sh
kubectl describe node <GPU_NODE_NAME>
如交付包包含示例 workload,可继续使用 GPU burn 或 vLLM 示例验证调度链路。
回滚建议
回滚方案取决于迁移方式:
| 迁移方式 | 回滚思路 |
|---|---|
| 同名 Helm release 迁移 | 使用迁移前保存的 values 和 manifest,按既定 Helm/Zarf 回退流程恢复 |
| 卸载旧 release 后重新部署 Zarf | 使用旧 release values 和原 Helm chart 重新安装 |
--adopt-existing-resources 接管 | 回滚前先确认资源 ownership,避免旧 release uninstall 删除正在使用的资源 |
Kustomize / kubectl apply 接管 | 使用迁移前导出的 YAML 和变更记录恢复 |
任何回滚都建议在维护窗口内执行。不要在没有确认资源归属的情况下直接删除 release 或 namespace。
常见问题处理
| 现象 | 可能原因 | 处理 |
|---|---|---|
invalid ownership metadata | 资源已存在,但 Helm release ownership 不匹配或缺失 | 判断是否需要 --adopt-existing-resources,或在维护窗口内清理冲突资源 |
field manager conflict / SSA conflict | 某些字段由其他 manager 管理 | 确认字段应由 Zarf/Helm 接管后,再使用 --force-conflicts |
| 旧 Helm release uninstall 后资源被删除 | 旧 release 仍然认为自己拥有这些资源 | 不要让两个 release 同时管理同一批资源;回滚前先确认 ownership |
hami-device-pluginCrashLoopBackOff | 可能与 NVIDIA 默认 device-plugin 冲突 | 禁用 GPU Operator 内置 device-plugin,检查 GPU 驱动 |
workload 一直 Pending | 证书未激活、GPU 节点未打标签、GPU 不足 | 检查 license、gpu=on 标签和 kubectl describe pod 事件 |
| scheduler 启动异常 | values、镜像版本或 leader election 配置不匹配 | 核对 <VALUES_FILE> 和目标 Kubernetes 版本 |
参考
-
Zarf package deploy options: https://docs.zarf.dev/commands/zarf_package_deploy
-
Zarf resource adoption: https://docs.zarf.dev/tutorials/8-resource-adoption
-
Zarf Helm chart configuration: https://docs.zarf.dev/ref/components