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 安装组件带来的限制
不能在同一个 namespace 里混用内外部镜像仓库(在同一集群里使用多个镜像仓库会有障碍)
Zarf 使用 admission webhook 的方式悄悄地替换了掌控 namespace 中所有容器的镜像,将他们替换成私有镜像仓库的版本。一个集群中可以做到部分 namespace 绕开 Zarf,正常访问其他镜像仓库,但不能在同一个 namespace 里再使用不同镜像仓库的镜像。你可以通过给 namespace 打上 zarf.dev/agent=ignore 标签忽略这一特性,使得你在其他 namespace 里可以使用其他镜像仓库而非 zarf init --registry-url ... 里指定的 registry。
不能再使用原生 Helm 管理同一批资源
一旦让 Zarf 接手了一批组件,再试图用另一套 Helm 流程去管理同一批资源,后面很容易遇到 ownership 冲突、升级打架或者状态难以判断的问题。这不是 Zarf 独有的毛病,是交付边界没划清时几乎必然会出现的结果。用 Zarf 可以很方便地拉起一套组件,但可不能想着装完以后就把 Zarf 一脚踢开,再用回 Helm 做日常迭代。因此,如无必要,请依赖密瓜智能团队做定期版本升级,不要自行迭代HAMi Enterprise。
很难灵活迭代
Zarf 的设计决定了每次我都在传输全量软件栈。这就注定和“灵活”不沾边。
迁移前准备
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