Build a multi-architecture Kubernetes cluster running nginx on Azure AKS
Introduction
Start your journey with Arm and x86 nginx workloads on a single Kubernetes cluster
Create the AKS cluster
Create the test utility
Deploy nginx on Intel x86
Deploy nginx on Arm
Deploy nginx multiarch service on AKS
Monitor performance with wrk and btop
Next Steps
Build a multi-architecture Kubernetes cluster running nginx on Azure AKS
Add the Arm deployment and service
In this section, you’ll add nginx on Arm to your existing cluster, completing your multi-architecture Intel/Arm environment for comprehensive performance comparison.
When you apply the arm_nginx.yaml file, it creates two Kubernetes objects:
- A deployment named
nginx-arm-deploymentthat pulls the multi-architecture nginx image from DockerHub, launches a pod on the Arm node, and mounts the shared ConfigMap as/etc/nginx/nginx.conf - A service called
nginx-arm-svcthat acts as a load balancer, targeting pods with bothapp: nginx-multiarchandarch: armlabels
Copy and paste the following commands into a terminal to download and apply the Arm deployment and service:
curl -o arm_nginx.yaml https://raw.githubusercontent.com/geremyCohen/nginxOnAKS/refs/heads/main/arm_nginx.yaml
kubectl apply -f arm_nginx.yaml
You will see output similar to:
deployment.apps/nginx-arm-deployment created
service/nginx-arm-svc created
Examining the deployment configuration
Take a closer look at the arm_nginx.yaml deployment file and you’ll see settings optimized for the Arm architecture:
The nodeSelector value of kubernetes.io/arch: arm64 ensures that the deployment only runs on Arm nodes, utilizing the arm64 version of the nginx container image.
spec:
nodeSelector:
kubernetes.io/arch: arm64
The service selector uses both app: nginx-multiarch and arch: arm labels to target only Arm pods. This dual-label approach allows for both architecture-specific and multi-architecture service routing.
selector:
app: nginx-multiarch
arch: arm
Verify the deployment
Get the status of nodes, pods, and services by running:
kubectl get nodes,pods,svc -nnginx
Your output should be similar to the following, showing two nodes, two pods, and two services:
NAME STATUS ROLES AGE VERSION
node/aks-arm-56500727-vmss000000 Ready <none> 59m v1.32.7
node/aks-intel-31372303-vmss000000 Ready <none> 63m v1.32.7
NAME READY STATUS RESTARTS AGE
pod/nginx-arm-deployment-5bf8df95db-wznff 1/1 Running 0 36s
pod/nginx-intel-deployment-78bb8885fd-mw24f 1/1 Running 0 9m21s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-arm-svc LoadBalancer 10.0.241.154 48.192.64.197 80:30082/TCP 36s
service/nginx-intel-svc LoadBalancer 10.0.226.250 20.80.128.191 80:30080/TCP 9m22s
You can also verify the shared ConfigMap is available:
kubectl get configmap -nnginx
The output is similar to:
NAME DATA AGE
nginx-config 1 10m
When the pods show Running and the service shows a valid External IP, you’re ready to test the nginx Arm service.
Test the nginx web service on Arm
Run the following command to make an HTTP request to the Arm nginx service using the script you created earlier:
./nginx_util.sh curl arm
The response includes both the HTTP data and details about which pod handled the request:
Using service endpoint 48.192.64.197 for curl on arm service
Response:
{
"message": "nginx response",
"timestamp": "2025-10-24T22:04:59+00:00",
"server": "nginx-arm-deployment-5bf8df95db-wznff",
"request_uri": "/"
}
Served by: nginx-arm-deployment-5bf8df95db-wznff
If you see similar output, you have successfully added Arm nodes to your cluster running nginx.
Compare both architectures
Now you can test both architectures and compare their responses:
./nginx_util.sh curl intel
./nginx_util.sh curl arm
Each command routes to its respective architecture-specific service, allowing you to compare performance and verify that your multi-architecture cluster is working correctly.