Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
13c576a
Add nginx on AKS multi-architecture learning path - initial cluster s…
geremyCohen Oct 9, 2025
46e52ed
Add Intel nginx deployment with nginx_util.sh testing script
geremyCohen Oct 9, 2025
20f24bb
Complete multiarch nginx on AKS tutorial - AMD, ARM, and multiarch de…
geremyCohen Oct 9, 2025
e8d5cbf
Improve nginx_util.sh output formatting with console bold text for be…
geremyCohen Oct 9, 2025
162fb00
Add login functionality and btop installation to nginx_util.sh script
geremyCohen Oct 10, 2025
5dce967
Restructure tutorial chapters and fix nginx access logs for proper mo…
geremyCohen Oct 10, 2025
90da748
Fix nginx_util.sh script to correctly identify serving pods
geremyCohen Oct 14, 2025
4b8197c
Update chapter weights for multiarch nginx tutorial
geremyCohen Oct 23, 2025
0809c02
Update AKS cluster tutorial to enhance clarity and accuracy for Arm n…
geremyCohen Oct 23, 2025
b46981f
Refactor introduction section for clarity in the Learning Path descri…
geremyCohen Oct 23, 2025
b6e1931
Enhance AKS cluster tutorial with improved clarity and additional not…
geremyCohen Oct 23, 2025
4955525
Replace embedded script with curl download from GitHub repo
geremyCohen Oct 24, 2025
8b253aa
Update nginx utility script instructions for clarity and include curl…
geremyCohen Oct 24, 2025
4423636
Replace embedded YAML with curl downloads from nginxOnAKS repo
geremyCohen Oct 24, 2025
a76deb4
Update deployment instructions for Intel nginx setup and add jq as a …
geremyCohen Oct 24, 2025
40c5b23
Replace embedded ARM YAML with curl/kubectl commands
geremyCohen Oct 24, 2025
f154ec7
Extract multiarch service YAML to repo, use curl + kubectl pattern
geremyCohen Oct 24, 2025
8210d9d
Add example outputs to chapter 0 (cluster creation)
geremyCohen Oct 24, 2025
c54e02e
Remove AMD reference and update put command to btop in chapter 1.5
geremyCohen Oct 24, 2025
014114b
Update chapter 1: Add ConfigMap, fix nodeSelector/container name, upd…
geremyCohen Oct 24, 2025
5027344
Add note explaining amd64 architecture naming convention
geremyCohen Oct 24, 2025
ba20ce7
Update chapter 3: Add ConfigMap, fix nodeSelector, update outputs, ad…
geremyCohen Oct 24, 2025
eea0422
Remove duplicate 'Verify the deployment' heading in chapter 3
geremyCohen Oct 24, 2025
80e4395
Update chapter 4: Remove AMD references, update outputs to show 2 nod…
geremyCohen Oct 24, 2025
48fddcd
Update performance monitoring section: change title, remove AMD refer…
geremyCohen Oct 24, 2025
fa2d2b8
Replace 'nginx_util.sh get' with 'nginx_util.sh curl' throughout tuto…
geremyCohen Oct 24, 2025
14e27d1
Merge branch 'ArmDeveloperEcosystem:main' into ignite-demo
geremyCohen Oct 27, 2025
4536710
Update performance monitoring section: change title, remove AMD refer…
geremyCohen Oct 27, 2025
2f90972
Update performance monitoring section: change title, remove AMD refer…
geremyCohen Oct 27, 2025
11f5741
Renamed files
geremyCohen Oct 27, 2025
f232560
Add .gitignore to exclude default ignored files
geremyCohen Oct 29, 2025
6acf3c0
Enhance AKS cluster deployment guide with multi-architecture benefits…
geremyCohen Oct 29, 2025
a4016f0
Merge branch 'main' into ignite-demo
geremyCohen Nov 2, 2025
b737c5c
Update tutorials: add shared nginx-configmap, remove ARM vs Intel con…
geremyCohen Nov 4, 2025
55b346b
Merge branch 'ignite-demo' of github.com:geremyCohen/arm-learning-pat…
geremyCohen Nov 4, 2025
f919619
Fix 5 documentation issues for shared ConfigMap architecture
geremyCohen Nov 4, 2025
8ad75ec
Merge branch 'ignite-demo' of github.com:geremyCohen/arm-learning-pat…
geremyCohen Nov 4, 2025
d70fb81
Fix confusing reference to Intel deployment in test utility section
geremyCohen Nov 4, 2025
0bc72bc
Merge branch 'ArmDeveloperEcosystem:main' into ignite-demo
geremyCohen Nov 4, 2025
a7fefa3
Merge branch 'ignite-demo' of github.com:geremyCohen/arm-learning-pat…
geremyCohen Nov 4, 2025
03b2b7d
removing .idea and .gitignore
geremyCohen Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: Add Arm nodes to your Azure Kubernetes Services cluster using a multi-architecture nginx container image

minutes_to_complete: 60

who_is_this_for: This Learning Path is for developers who want to compare the performance of x64 and arm64 deployments by running nginx on a hybrid Azure Kubernetes Service (AKS) cluster using nginx's multi-architecture container image. Once you've seen how easy it is to add arm64 nodes to an existing cluster, you'll be ready to explore arm64-based nodes for other workloads in your environment.


learning_objectives:
- Create a hybrid AKS cluster with x64 and arm64 nodes.
- Deploy nginx's multi-architecture container image, pods, and services to the AKS cluster.
- Smoke test nginx from each architecture in the cluster to verify proper installation.
- Performance test against each architecture in the cluster to better understand performance.


prerequisites:
- An [Azure account](https://azure.microsoft.com/en-us/free/).
- A local machine with [jq](https://jqlang.org/download/), [curl](https://curl.se/download.html), [wrk](https://github.com/wg/wrk), [Azure CLI](/install-guides/azure-cli/) and [kubectl](/install-guides/kubectl/) installed.

author:
- Geremy Cohen

### Tags
skilllevels: Introductory

subjects: Containers and Virtualization
cloud_service_providers: Microsoft Azure

armips:
- Neoverse

operatingsystems:
- Linux
- macOS

tools_software_languages:
- nginx
- Web Server

further_reading:
- resource:
title: nginx - High Performance Load Balancer, Web Server, & Reverse Proxy
link: https://nginx.org/
type: documentation
- resource:
title: nginx Docker Hub
link: https://hub.docker.com/_/nginx
type: documentation
- resource:
title: Azure Kubernetes Service (AKS) documentation
link: https://docs.microsoft.com/en-us/azure/aks/
type: documentation
- resource:
title: Learn how to tune Nginx
link: https://learn.arm.com/learning-paths/servers-and-cloud-computing/nginx_tune/
type: documentation

### FIXED, DO NOT MODIFY
# ================================================================================
weight: 1 # _index.md always has weight of 1 to order correctly
layout: "learningpathall" # All files under learning paths have this same wrapper
learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content.
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
title: Monitor performance with wrk and btop
weight: 70

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Apply configuration updates

Now that you have all your nginx deployments running across Intel and ARM architectures, you can monitor performance across each architecture using wrk to generate load and btop to monitor system performance.

{{% notice Note %}}
This tutorial uses wrk to generate load, which is readily available on apt and brew package managers. [wrk2](https://github.com/giltene/wrk2) is a modern fork of wrk with additional features. wrk was chosen for this tutorial due to its ease of install, but if you prefer to install and use wrk2 (or other http load generators) for your testing, feel free to do so.
{{% /notice %}}

### Apply performance configuration

The `nginx_util.sh` script includes a `put config` command that will:

- Apply a performance-optimized nginx configuration to all pods
- Install btop monitoring tool on all pods for system monitoring
- Restart pods with the new configuration

1. Run the following command to apply the configuration updates:

```bash
./nginx_util.sh put btop
```

You will see output similar to the following:

```output
Installing btop on all nginx pods...
Installing btop on nginx-amd-deployment-56b547bb47-vgbjj...
✓ btop installed on nginx-amd-deployment-56b547bb47-vgbjj
Installing btop on nginx-arm-deployment-66cb47ddc9-fgmsd...
✓ btop installed on nginx-arm-deployment-66cb547ddc9-fgmsd
Installing btop on nginx-intel-deployment-6f5bff9667-zdrqc...
✓ btop installed on nginx-intel-deployment-6f5bff9667-zdrqc
✅ btop installed on all pods!
```

### Verify configuration updates

2. Check that all pods have restarted with the new configuration:

```bash
kubectl get pods -n nginx
```

You should see all pods with recent restart times.

{{% notice Note %}}
Because pods are ephemeral, btop will need to be reinstalled if the pods are deleted or restarted. If you get an error saying btop is not found, simply rerun the `./nginx_util.sh put btop` command to reinstall it.
{{% /notice %}}


### Monitor pod performance

You can now login to any pod and use btop to monitor system performance. There are many variables which may affect an individual workload's performance, btop (like top), is a great first step in understanding those variables.

{{% notice Note %}}
When performing load generation tests from your laptop, local system and network settings may interfere with proper load generation between your machine and the remote cluster services. To mitigate these issues, its suggested to install the nginx_util.sh (or whichever tool you wish to use) on a [remote Azure instance](https://learn.arm.com/learning-paths/servers-and-cloud-computing/csp/azure/) in the same region and zone as your K8s cluster (us-west-2 if you follow these tutorial instructions exactly) for best results. If you aren't seeing at least 70K+ requests/s to either K8s service endpoint, switching to a better located/tuned system is advised.
{{% /notice %}}

Bringing up two btop terminals, one for each pod, is a convenient way to view performance in realtime. To bring up btop on both Arm and Intel pods:

1. Open a new terminal window or tab.
2. Within the terminal, run the `login arm` command from the nginx utility script to enter the pod:

```bash
# Login to AMD pod (replace with intel or arm as needed)
./nginx_util.sh login arm
```

3. Once inside the pod, run btop to see real-time system monitoring:

```bash
btop --utf-force
```
4. Repeat, from Step 1, but this time, using the `login intel` command.

You should now see something similar to below, that is, one terminal for each Arm and Intel, running btop:

![Project Overview](images/btop_idle.png)

To visualize performance with btop against the Arm and Intel pods via the load balancer service endpoints, you can use the nginx_util.sh wrapper to generate the load two both simultaneoulsy:

```bash
./nginx_util.sh wrk both
```

This runs wrk with predefined setting (1 thread, 50 simultaneous connections) to generate load to the K8s architecture-specific endpoints. While it runs (for a default of 30s), you can observe some performance characteristics from the btop outputs:

![Project Overview](images/under_load.png)

Of particular interest is memory and CPU resource usage per pod. For Intel, figure 1 shows memory usage for the process, with figure 2 showing total cpu usage. Figures 3 and 4 show us the same metrics, but for Arm.

![Project Overview](images/mem_and_cpu.png)

In addition to the visual metrics, the script also returns runtime results including requests per second, and latencies:

```output
azureuser@gcohen-locust-1:/tmp/1127$ ./nginx_util.sh wrk both
Running wrk against both architectures in parallel...

Intel: wrk -t1 -c50 -d30 http://172.193.227.195/
ARM: wrk -t1 -c50 -d30 http://20.252.73.72/

========================================

INTEL RESULTS:
Running 30s test @ http://172.193.227.195/
1 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 752.40us 1.03ms 28.95ms 94.01%
Req/Sec 84.49k 12.14k 103.08k 73.75%
2528743 requests in 30.10s, 766.88MB read
Requests/sec: 84010.86
Transfer/sec: 25.48MB

ARM RESULTS:
Running 30s test @ http://20.252.73.72/
1 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 621.56us 565.90us 19.75ms 95.43%
Req/Sec 87.54k 10.22k 107.96k 82.39%
2620567 requests in 30.10s, 789.72MB read
Requests/sec: 87062.21
Transfer/sec: 26.24MB

========================================
Both tests completed
```

### Experimenting with wrk

The nginx_util.sh script shows the results of the load generation, as well as the command lines used to generate them.

```output
...
Intel: wrk -t1 -c50 -d30 http://172.193.227.195/
ARM: wrk -t1 -c50 -d30 http://20.252.73.72/
...
```


Feel free to experiment increasing/decreasing client threads, connections, and durations to better understand the performance characteristics under different scenarios.

For example, to generate load using 500 connections across 4 threads to the Arm service for five minutes (300s), you could use the following commandline:

```bash
wrk -t4 -c500 -d300 http://20.252.73.72/
```

As mentioned earlier, unless your local system is tuned to handle load generation, you may find better traffic generation results by running on a VM. If aren't seeing at least 70K+ requests/s to either K8s service endpoint when running `wrk`, switching to a better located/tuned system is advised.

## Next Steps

You learned in this learning path how to run a sample nginx workload on a dual-architecture (Arm and Intel) Azure Kubernetes Service. Once setup, you learned how to generate load with the wrk utility, and monitor runtime metrics with btop. If you wish to continue experimenting with this learning path, some ideas you may wish to explore include:

* What do the performance curves look like between the two architectures as a function of load?
* How do larger instance types scale versus smaller ones?

Most importantly, you now possess the knowledge needed to begin experimenting with your own workloads on Arm-based AKS nodes to identify performance and efficiency opportunities unique to your own environments.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Create the test utility
weight: 20

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Test utility script

You'll create a utility script to test and manage your nginx services across all architectures. This script will be used throughout the tutorial to test services, apply configurations, and access pods.

### Script functionality

The `nginx_util.sh` script provides three main functions:

- **`curl intel|arm|multiarch`** - Test nginx services and show which pod served the request
- **`put btop`** - Install btop monitoring tool on all pods
- **`login intel|arm`** - Interactive bash access to architecture-specific pods

The script conveniently bundles test and logging commands into a single place, making it easy to test, troubleshoot, and view services. You'll use it throughout the tutorial to test services, apply configurations, and access pods across all architectures.


### Create the utility script

{{% notice Note %}}
The following utility `nginx_util.sh` is provided for convenience.

It's a wrapper for kubectl and other commands, utilizing [curl](https://curl.se/). Make sure you have curl installed before running.
{{% /notice %}}

Copy and paste the following command into a terminal to download and create the `nginx_util.sh` script:

```bash
curl -o nginx_util.sh https://raw.githubusercontent.com/geremyCohen/nginxOnAKS/refs/heads/main/nginx_util.sh
chmod +x nginx_util.sh
```

In the folder you ran the curl command, you should now see the `nginx_util.sh` script. Test it by running:

```bash
./nginx_util.sh
```

The output should include usage instructions:
```output
Invalid first argument. Use 'curl', 'wrk', 'put', or 'login'.
```

With it working, you're now ready to deploy nginx to the Intel nodes in the cluster.
Loading