事情本身不复杂,线索都在日志里。要把三十多个镜像从老机房 Harbor 迁到新集群,用 docker pull 再 tag 再 push,迁完发现两个镜像的 digest 变了,线上的 imagePullPolicy 校验直接对不上。

第一反应是「多架构镜像只迁了当前平台那一份,manifest list 丢了一半」,验证下来不成立。

真正麻烦的地方在于,几个原因的现象几乎一样。docker pull 和 push 之间经过本地解包再打包,压缩算法与层顺序可能变化,digest 就变了。也可能是中间用了 docker save 再 load,manifest 里的 config 被重写。

另外,仓库开了内容信任,签名没有随镜像一起搬过去。

上来先用 skopeo 直接仓库到仓库复制

skopeo copy --all docker://old.harbor/app:1.4 docker://new.harbor/app:1.4

复制前后核对 manifest digest

skopeo inspect --raw docker://new.harbor/app:1.4 | sha256sum

接着确认多架构列表完整

skopeo inspect --raw docker://new.harbor/app:1.4 | jq '.manifests[].platform'

批量脚本里加失败重试与校验

skopeo copy --retry-times 3 docker://old.harbor/app:1.4 docker://new.harbor/app:1.4

改完先别撤,确认这几项。新仓库里 image 的 digest 与老仓库完全一致,多架构列表里的平台数量相同,集群拉取后 Pod 正常启动。

这里还有个坑。走本地再 push 一定会在某处改掉 manifest,跨仓库搬镜像优先用 skopeo;–all 不加就只迁一个平台,ARM 节点会拉不到。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189