Using a Dual-Architecture Image (x86 and Arm)
Huawei Cloud CCE allows x86 and Arm nodes to coexist within the same cluster. However, because the instruction sets of these two architectures are incompatible, x86 images cannot run on Arm nodes, and Arm images cannot run on x86 nodes. If a workload's image does not match the target node's architecture, deployment will fail in heterogeneous clusters.
To address this, you can build a dual-architecture image that supports both x86 and Arm under a single image path. The kubelet automatically pulls the image matching the node's architecture, enabling one-time configuration with full-architecture compatibility.
How It Works
The core mechanism of a dual-architecture image leverages the Docker manifest list. This associates a single logical image name, for example, defaultbackend:1.5 with multiple physical images, such as defaultbackend-linux-amd64:1.5 and defaultbackend-linux-arm64:1.5. When deploying a workload, you specify only one image path without configuring node affinity rules. This simplifies the workload specification and improves maintainability. When a pod is scheduled to an Arm node, the container runtime automatically pulls the Arm image. When scheduled to an x86 node, it pulls the x86 image.

Prerequisites
- The Docker client version must be later than 18.03 to create a dual-architecture image.
- You have built and tested the single-architecture images for both x86 and Arm. For example, defaultbackend-linux-amd64:1.5 and defaultbackend-linux-arm64:1.5 are the x86 and Arm images, respectively.
- You have logged in to the SWR image repository and have push permissions.
Procedure
Step 1: Enable Docker
- Log in to the VM where Docker is installed.
- Enable Docker.
# Enable Docker temporarily for the current terminal session. export DOCKER_CLI_EXPERIMENTAL=enabled
- Verify that Docker is enabled.
docker version --format '{{.Client.Experimental}}'If true is displayed, Docker has been enabled.
Step 2: Build and Upload Single-Architecture Images for x86 and Arm
In this example, defaultbackend-linux-amd64:1.5 and defaultbackend-linux-arm64:1.5 are the x86 and Arm images, respectively.
Tag the images and push them to SWR. For details, see Pushing an Image.
# Define variables. Replace the placeholder values with your actual data.
REGISTRY="swr.ap-southeast-1.myhuaweicloud.com" # Your SWR repository address
NAMESPACE="test-namespace" # Your SWR organization
IMAGE_NAME="defaultbackend" # Image name
VERSION="1.5" # Version
# ---- Process the AMD64 (x86) image. ----
# Add the full SWR tag to the local image.
docker tag defaultbackend-linux-amd64:${VERSION} ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-amd64:${VERSION}
# Push the image.
docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-amd64:${VERSION}
# ---- Process the Arm64 image. ----
docker tag defaultbackend-linux-arm64:${VERSION} ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-arm64:${VERSION}
docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}-linux-arm64:${VERSION} Step 3: Create and Push a Manifest List
Create a dual-architecture manifest list and upload it to SWR. Associate the two single-architecture images with a single logical image name.
- Create a manifest list.
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: modifies the manifest if it already exists.
- --insecure: allows interaction with HTTP repositories. SWR typically uses HTTPS, but this parameter is included for compatibility and does not cause errors when HTTPS is used.
- Annotate each image in the manifest list with its OS architecture.
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 - Push the manifest list to SWR.
docker manifest push -p --insecure ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${VERSION}- -p: pushes the manifest list rather than the image content, which was already pushed in the previous step.
- View the created manifest list.
docker manifest inspect ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${VERSION}
Step 4: Use the Dual-Architecture Image in CCE
After completing the preceding steps, you can reference the same logical image path when creating a workload in CCE.
- When a pod using this image is scheduled to an x86 node, the swr.ap-southeast-1.myhuaweicloud.com/test-namespace/defaultbackend-linux-amd64:1.5 image is pulled automatically.
- When a pod using this image is scheduled to an Arm node, the swr.ap-southeast-1.myhuaweicloud.com/test-namespace/defaultbackend-linux-arm64:1.5 image is pulled automatically.
apiVersion: apps/v1
kind: Deployment
metadata:
name: defaultbackend
spec:
replicas: 1
selector:
matchLabels:
app: defaultbackend
template:
metadata:
labels:
app: defaultbackend
spec:
containers:
# Directly use the dual-architecture image path.
- image: swr.ap-southeast-1.myhuaweicloud.com/test-namespace/defaultbackend:1.5
name: nginx
# You do not need to configure nodeSelector. The kubelet automatically pulls the image matching the node's architecture. However, if you need to restrict pod scheduling to nodes of a specific architecture, affinity rules are still required.
# nodeSelector: # Optional. If you need to restrict pod scheduling to nodes of a specific architecture, add a nodeSelector.
# kubernetes.io/arch: arm64 # Forcibly schedule pods to Arm nodes.
imagePullSecrets:
- name: default-secret FAQs
Do I Need to Configure Node Affinity After Using a Dual-Architecture Image?
Not necessarily. Configure node affinity based on your deployment requirements.
- No configuration required: If your cluster contains both x86 and Arm nodes and the pod architecture is not a concern, you only need to specify a dual-architecture image. No affinity configuration is necessary. The scheduler automatically assigns the pod to an available node, and the kubelet automatically pulls the appropriate image.
- Configuration required: If a workload must run on a specific architecture, for example, due to legacy binary dependencies that support only x86, you must configure node affinity. In this case, the dual-architecture image ensures that the correct image is pulled once the pod is scheduled to the target node.
How Do I Check Whether an Image Supports Dual Architectures?
docker manifest inspect <image-path> Check whether the returned manifest list contains entries whose platform.architecture field is set to amd64 or arm64.
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot