Skip to content

Create Azure Linux 3.0 custom Arm VM #2103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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,62 @@
---
title: Create Azure Linux 3.0 custom Arm VM

minutes_to_complete: 120

who_is_this_for: This learning path helps developers create a custom Azure Linux 3.0 VM for Arm and utilize the default software stack provided by the Microsoft team.


learning_objectives:
- Use the qemu-img utility to create a raw disk image, boot a VM with Aarch64 ISO to install the OS onto that disk, and convert the raw disk image into VHD
- Upload the VHD to Azure and use the Azure Shared Image Gallery to create a custom image.
- Use Azure CLI to create Azure Linux 3.0 VM for Arm, using the custom image from Azure SIG.

prerequisites:
- A [Microsoft Azure](https://azure.microsoft.com/) account with permission to create resources, including Cobalt 100 (Arm64) instances (Dpsv6).
- A local Linux machine with [QEMU](https://www.qemu.org/download/) installed to emulate Aarch64.
- An [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) installed and authenticated on your local machine.

author: Zach Lasiuk

### Tags
skilllevels: Advanced
subjects: Containers and Virtualization
cloud_service_providers: Microsoft Azure


armips:
- Neoverse-N2

tools_software_languages:
- QEMU
- Azure CLI

operatingsystems:
- Linux

further_reading:
- resource:
title: Azure Virtual Machines documentation
link: https://learn.microsoft.com/en-us/azure/virtual-machines/
type: documentation
- resource:
title: Azure Shared Image Gallery documentation
link: https://learn.microsoft.com/en-us/azure/virtual-machines/shared-image-galleries
type: documentation
- resource:
title: QEMU User Documentation
link: https://wiki.qemu.org/Documentation
type: documentation
- resource:
title: Upload a VHD to Azure and create an image
link: https://learn.microsoft.com/en-us/azure/virtual-machines/linux/upload-vhd
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,8 @@
---
# ================================================================================
# FIXED, DO NOT MODIFY THIS FILE
# ================================================================================
weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation.
title: "Next Steps" # Always the same, html page title.
layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing.
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
---
title: Create custom Azure Linux 3.0 Arm image for the VM
weight: 3

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

## Roadmap to the Azure Linux 3.0 Arm VM image

In this learning path, we will start by [downloading the Aarch64 ISO of Azure Linux 3.0](https://github.com/microsoft/azurelinux#iso). Using qemu-img, we’ll create a raw disk image and boot a virtual machine with the ISO to install the OS onto the disk. Once the installation is complete, we will convert the raw disk to a fixed-size VHD, upload it to Azure Blob Storage, and then use the Azure CLI to create a custom Arm image. This custom image will enable us to launch Azure Linux 3.0 virtual machines on Arm-based infrastructure, even though the Azure Marketplace currently provides this image only for x64 systems.

Next, switch to a Linux-based environment and proceed with the following steps.

#### 1. Install the Dependencies
```bash
$ sudo apt update && sudo apt install qemu-system-arm qemu-system-aarch64 qemu-efi-aarch64 qemu-utils ovmf -y
```
#### 2. Download the Azure Linux 3.0 ISO
```bash
$ wget https://aka.ms/azurelinux-3.0-aarch64.iso
```
#### 3. Use qemu-img to create a 32 GB raw disk image
```bash
$ qemu-img create -f raw azurelinux-arm64.raw 34359738368
```
This step creates a 32 GB empty raw disk image to install the OS.

#### 4. Boot the ISO and install the OS to the raw image
```bash
$ qemu-system-aarch64 \
-machine virt \
-cpu cortex-a72 \
-m 4096 \
-nographic \
-bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
-drive if=none,file=azurelinux-arm64.raw,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0 \
-cdrom azurelinux-3.0-aarch64.iso \
-netdev user,id=net0 \
-device virtio-net-device,netdev=net0
```

This step boots the Azure Linux 3.0 ISO on an emulated Arm VM and installs the OS onto the raw disk.

Once the OS boots successfully, install Azure Linux Agent required for VM provisioning, and poweroff the VM, as below:

```bash
$ sudo dnf install WALinuxAgent -y
$ sudo systemctl enable waagent
$ sudo systemctl start waagent
$ sudo poweroff
```
#### 5. Convert Raw Disk to VHD Format
Now that the raw disk image is all set to be used, convert the image to fixed-size VHD, campatible to Azure.

```bash
$ qemu-img convert -f raw -o subformat=fixed,force_size -O vpc azurelinux-arm64.raw azurelinux-arm64.vhd
```

{{% notice Note %}}
VHD files have 512 bytes of footer attached at the end. The “force_size” flag ensures that the exact virtual size specified is used for the final VHD file (in our case, 32 GiB). Without this, qemu-img may round the size or adjust for footer overhead (especially when converting from raw to VHD). “force_size” forces the final image to match the original size. This flag helps make the final VHD size a clean, whole number in MB or GiB, which Azure requires.
{{% /notice %}}

#### 6. Set environment variables
Below uploading the VHD file to Azure Blob storage, set the Environment Variables for the Azure CLI.

```bash
RESOURCE_GROUP="MyCustomARM64Group"
LOCATION="centralindia"
STORAGE_ACCOUNT="mycustomarm64storage"
CONTAINER_NAME="mycustomarm64container"
VHD_NAME="azurelinux-arm64.vhd"
GALLERY_NAME="MyCustomARM64Gallery"
IMAGE_DEF_NAME="MyAzureLinuxARM64Def"
IMAGE_VERSION="1.0.0"
PUBLISHER="custom"
OFFER="custom-offer"
SKU="custom-sku"
OS_TYPE="Linux"
ARCHITECTURE="Arm64"
HYPERV_GEN="V2"
STORAGE_ACCOUNT_TYPE="Standard_LRS"
VM_NAME="MyAzureLinuxARMVM"
ADMIN_USER="azureuser"
VM_SIZE="Standard_D4ps_v6"
```

{{% notice Note %}}
You can modify the values of these environment variables—such as RESOURCE_GROUP, VM_NAME, LOCATION, and others—based on your naming preferences, region, and resource requirements.
{{% /notice %}}

#### 7. Create a Resource Group on Azure
After [installing the Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest), create a new resource group.

```bash
$ az group create --name "$RESOURCE_GROUP" --location "$LOCATION"
```

#### 8. Create Azure Blob Storage on Azure

```bash
$ az storage account create \
--name "$STORAGE_ACCOUNT" \
--resource-group "$RESOURCE_GROUP" \
--location "$LOCATION" \
--sku Standard_LRS \
--kind StorageV2
```

#### 9. Create Blob Container in the Blob Storage Account

```bash
$ az storage container create \
--name "$CONTAINER_NAME" \
--account-name "$STORAGE_ACCOUNT"
```

#### 10. Upload VHD to the Blob container created in step 9

```bash
$ az storage blob upload \
--account-name "$STORAGE_ACCOUNT" \
--container-name "$CONTAINER_NAME" \
--name "$VHD_NAME" \
--file ./azurelinux-arm64.vhd
```

This successfully uploads the VHD to the Azure Blob Storage account. Confirm the same after visiting the blob storage of your Azure account.

Now, let’s create a custom VM image from this VHD, using Azure Shared Image Gallery.

#### 11. Create Azure Shared Image Gallery
```bash
$ az sig create \
--resource-group "$RESOURCE_GROUP" \
--gallery-name "$GALLERY_NAME" \
--location "$LOCATION"
```

#### 12. Create the Image Definition
```bash
$ az sig image-definition create
--resource-group "$RESOURCE_GROUP"
--gallery-name "$GALLERY_NAME"
--gallery-image-definition "$IMAGE_DEF_NAME"
--publisher "$PUBLISHER"
--offer "$OFFER"
--sku "$SKU"
--os-type "$OS_TYPE"
--architecture "$ARCHITECTURE"
--hyper-v-generation "$HYPERV_GEN"
```

#### 13. Create Image Version
```bash
$ az sig image-version create
--resource-group "$RESOURCE_GROUP"
--gallery-name "$GALLERY_NAME"
--gallery-image-definition "$IMAGE_DEF_NAME"
--gallery-image-version "$IMAGE_VERSION"
--location "$LOCATION"
--os-vhd-uri "[https://${STORAGE_ACCOUNT}.blob.core.windows.net/${CONTAINER_NAME}/${VHD_NAME](https://${storage_account}.blob.core.windows.net/$%7BCONTAINER_NAME%7D/$%7BVHD_NAME)}"
--os-vhd-storage-account "$STORAGE_ACCOUNT"
--storage-account-type "$STORAGE_ACCOUNT_TYPE"
```

This registers the VHD as a version of your custom image.

#### 14. Retrieve the Image ID
Once the image has been versioned, retrieve the unique ID for use in VM creation.

```bash
$ IMAGE_ID=$(az sig image-version show
--resource-group "$RESOURCE_GROUP"
--gallery-name "$GALLERY_NAME"
--gallery-image-definition "$IMAGE_DEF_NAME"
--gallery-image-version "$IMAGE_VERSION"
--query "id" -o tsv)
```

#### 15. Create the VM Using the Custom Image
Finally, create the VM with this custom image.

```bash
$ az vm create \
--resource-group "$RESOURCE_GROUP" \
--name "$VM_NAME" \
--image "$IMAGE_ID" \
--size "$VM_SIZE" \
--admin-username "$ADMIN_USER" \
--generate-ssh-keys \
--public-ip-sku Standard
```

This deploys Azure Linux 3.0 Arm64 VM from the custom image. Confirm the same after visiting your Azure account “Virtual Machines” section.

After the VM is successfully created, fetch the Public IP of the VM.

```bash
$ az vm show \
--resource-group "$RESOURCE_GROUP" \
--name "$VM_NAME" \
--show-details \
--query "publicIps" \
-o tsv
```
With the Public IP retrieved, SSH into the VM.

```bash
$ ssh azureuser@<public-ip-address>
```

Replace **public-ip-address** with the IP returned in the previous command.

You can now log into your custom Azure Linux 3.0 Arm64 VM and start using it!

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: "Background"

weight: 2

layout: "learningpathall"
---

## Introduction to Azure Linux 3.0

Azure Linux 3.0 is Microsoft's in-house, lightweight Linux distribution optimized for running cloud-native workloads on Azure. Designed with performance, security, and reliability in mind, it is fully supported by Microsoft and tailored for containers, microservices, and Kubernetes. With native support for Arm64 (Aarch64) architecture, Azure Linux 3.0 enables efficient execution of workloads on energy-efficient ARM-based infrastructure, making it a powerful choice for scalable and cost-effective cloud deployments.

As of now, the Azure Marketplace offers official VM images of Azure Linux 3.0 only for x64-based architectures, published by Ntegral Inc. However, native Arm64 (Aarch64) images are not yet officially available. This learning path bridges that gap by guiding developers through the process of building a custom Arm VM image using the Azure Linux 3.0 ISO. By the end of this path, you'll be able to deploy and run Azure Linux 3.0 VMs on Arm-based Azure infrastructure with confidence.