CCE中使用x86和ARM双架构镜像
华为云CCE支持x86与ARM节点混部在同一集群。但两种架构的指令集不兼容,导致x86镜像无法在ARM节点上运行,反之ARM镜像无法在x86节点上运行。如果镜像与节点架构不适配,就容易造成工作负载在拥有x86与ARM节点的集群中部署失败。
为解决这一问题,您可以构建x86和ARM双架构镜像,使用同一个镜像地址,Kubelet会根据节点架构自动拉取对应版本的镜像,实现一次配置,全架构运行。
工作原理
双架构镜像的核心原理是利用Docker的Manifest List功能,将一个逻辑镜像名(如defaultbackend:1.5)关联到多个物理镜像(如defaultbackend-linux-amd64:1.5、defaultbackend-linux-arm64:1.5)。这样在描述工作负载时,可以使用同一个镜像地址,且不用配置亲和性,工作负载描述文件更简洁更容易维护。当Pod调度到ARM架构节点时拉取ARM架构的镜像,当Pod调度到x86架构节点时拉取x86架构的镜像。

前提条件
- 制作双架构镜像,Docker客户端版本需要大于18.03。
- 已分别构建并测试通过对应x86和ARM架构的单体镜像。例如本示例中已经构建好了defaultbackend-linux-amd64:1.5和defaultbackend-linux-arm64:1.5两个镜像,分别是x86架构和ARM架构。
- 已登录目标SWR镜像仓库,并有推送权限。
操作步骤
步骤一:开启Docker功能
- 登录已安装Docker的虚拟机。
- 开启Docker功能。
# 临时开启(当前终端会话有效) export DOCKER_CLI_EXPERIMENTAL=enabled
- 验证是否开启成功。
docker version --format '{{.Client.Experimental}}'应输出true则表示开启成功。
步骤二:构建并上传x86与ARM单体镜像
本示例中已经构建好了defaultbackend-linux-amd64:1.5和defaultbackend-linux-arm64:1.5两个镜像,分别是x86架构和ARM架构。
将它们重命名(打标签) 并推送到SWR仓库,如下所示。上传镜像的具体方法请参见客户端上传镜像。
# 定义变量,请替换为你的实际信息
REGISTRY="swr.cn-north-4.myhuaweicloud.com" # 你的SWR仓库地址
NAMESPACE="test-namespace" # 你的SWR组织
IMAGE_NAME="defaultbackend" # 镜像名
VERSION="1.5" # 版本号
# ---- 处理 AMD64 (x86) 镜像 ----
# 给本地镜像打上SWR的完整标签
docker tag defaultbackend-linux-amd64:${VERSION} ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-amd64:${VERSION}
# 上传
docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-amd64:${VERSION}
# ---- 处理 ARM64 镜像 ----
docker tag defaultbackend-linux-arm64:${VERSION} ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-arm64:${VERSION}
docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-arm64:${VERSION} 步骤三:创建并推送Manifest列表
创建双架构Manifest列表并上传,将上面两个镜像关联到一个逻辑镜像名下。
- 创建Manifest列表。
docker manifest create --amend --insecure \ ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${VERSION} \ ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-amd64:${VERSION} \ ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-arm64:${VERSION}- --amend: 如果manifest存在则修改。
- --insecure: 允许与HTTP仓库交互(通常SWR是HTTPS,但保留参数不报错)。
- 为Manifest列表中的每个镜像标注操作系统架构。
docker manifest annotate ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${VERSION} \ ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-amd64:${VERSION} --arch amd64 docker manifest annotate ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${VERSION} \ ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-arm64:${VERSION} --arch arm64 - 推送Manifest列表到SWR。
docker manifest push -p --insecure ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${VERSION}- -p:推送列表本身,而不是镜像内容(内容已在上步推送)。
- 查看已创建的Manifest列表。
docker manifest inspect ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${VERSION}
步骤四:在CCE中使用双架构镜像
完成上述操作后,在CCE中创建工作负载时可以直接使用同一个逻辑镜像地址:
- 当Pod调度到x86架构的节点时,会拉取swr.cn-north-4.myhuaweicloud.com/test-namespace/defaultbackend-linux-amd64:1.5这个镜像。
- 当Pod调度到ARM架构的节点时,会拉取swr.cn-north-4.myhuaweicloud.com/test-namespace/defaultbackend-linux-arm64:1.5这个镜像。
apiVersion: apps/v1
kind: Deployment
metadata:
name: defaultbackend
spec:
replicas: 1
selector:
matchLabels:
app: defaultbackend
template:
metadata:
labels:
app: defaultbackend
spec:
containers:
# 直接使用双架构镜像地址
- image: swr.cn-north-4.myhuaweicloud.com/test-namespace/defaultbackend:1.5
name: nginx
# 可无需配置 nodeSelector,Kubelet会自动选择正确架构的镜像,但如果需要控制Pod调度到特定架构节点,仍需配合亲和性
# nodeSelector: # 可选:若仍想强制调度到某类节点,可添加nodeSelector
# kubernetes.io/arch: arm64 # 强制调度到ARM节点
imagePullSecrets:
- name: default-secret 常见问题
使用双架构镜像后是否还需要配置节点亲和性?
不一定。您可以根据实际需求进行选择。
- 无需配置:如果您的集群既有x86又有ARM节点,且不关心Pod具体跑在哪种架构上,仅需使用双架构镜像,无需任何亲和配置,调度器自动分配,Kubelet自动选镜像。
- 仍需配置:如果您必须让某个工作负载跑在x86节点上(例如某些旧版二进制依赖),则仍需要配置节点亲和性,此时双架构镜像可保证应用在x86节点上能拉取到正确镜像。
如何验证镜像是否支持双架构?
docker manifest inspect <镜像地址> 查看返回的manifests列表中是否包含platform.architecture为amd64和arm64的条目。