|
| 1 | +--- |
| 2 | +title: Create custom Azure Linux 3.0 Arm image for the VM |
| 3 | +weight: 3 |
| 4 | + |
| 5 | +### FIXED, DO NOT MODIFY |
| 6 | +layout: learningpathall |
| 7 | +--- |
| 8 | + |
| 9 | +## Roadmap to the Azure Linux 3.0 Arm VM image |
| 10 | + |
| 11 | +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. |
| 12 | + |
| 13 | +Next, switch to a Linux-based environment and proceed with the following steps. |
| 14 | + |
| 15 | +#### 1. Install the Dependencies |
| 16 | +```bash |
| 17 | +$ sudo apt update && sudo apt install qemu-system-arm qemu-system-aarch64 qemu-efi-aarch64 qemu-utils ovmf -y |
| 18 | +``` |
| 19 | +#### 2. Download the Azure Linux 3.0 ISO |
| 20 | +```bash |
| 21 | +$ wget https://aka.ms/azurelinux-3.0-aarch64.iso |
| 22 | +``` |
| 23 | +#### 3. Use qemu-img to create a 32 GB raw disk image |
| 24 | +```bash |
| 25 | +$ qemu-img create -f raw azurelinux-arm64.raw 34359738368 |
| 26 | +``` |
| 27 | +This step creates a 32 GB empty raw disk image to install the OS. |
| 28 | + |
| 29 | +#### 4. Boot the ISO and install the OS to the raw image |
| 30 | +```bash |
| 31 | +$ qemu-system-aarch64 \ |
| 32 | + -machine virt \ |
| 33 | + -cpu cortex-a72 \ |
| 34 | + -m 4096 \ |
| 35 | + -nographic \ |
| 36 | + -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \ |
| 37 | + -drive if=none,file=azurelinux-arm64.raw,format=raw,id=hd0 \ |
| 38 | + -device virtio-blk-device,drive=hd0 \ |
| 39 | + -cdrom azurelinux-3.0-aarch64.iso \ |
| 40 | + -netdev user,id=net0 \ |
| 41 | + -device virtio-net-device,netdev=net0 |
| 42 | +``` |
| 43 | + |
| 44 | +This step boots the Azure Linux 3.0 ISO on an emulated Arm VM and installs the OS onto the raw disk. |
| 45 | + |
| 46 | +Once the OS boots successfully, install Azure Linux Agent required for VM provisioning, and poweroff the VM, as below: |
| 47 | + |
| 48 | +```bash |
| 49 | +$ sudo dnf install WALinuxAgent -y |
| 50 | +$ sudo systemctl enable waagent |
| 51 | +$ sudo systemctl start waagent |
| 52 | +$ sudo poweroff |
| 53 | +``` |
| 54 | +#### 5. Convert Raw Disk to VHD Format |
| 55 | +Now that the raw disk image is all set to be used, convert the image to fixed-size VHD, campatible to Azure. |
| 56 | + |
| 57 | +```bash |
| 58 | +$ qemu-img convert -f raw -o subformat=fixed,force_size -O vpc azurelinux-arm64.raw azurelinux-arm64.vhd |
| 59 | +``` |
| 60 | + |
| 61 | +{{% notice Note %}} |
| 62 | +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. |
| 63 | +{{% /notice %}} |
| 64 | + |
| 65 | +#### 6. Set environment variables |
| 66 | +Below uploading the VHD file to Azure Blob storage, set the Environment Variables for the Azure CLI. |
| 67 | + |
| 68 | +```bash |
| 69 | +RESOURCE_GROUP="MyCustomARM64Group" |
| 70 | +LOCATION="centralindia" |
| 71 | +STORAGE_ACCOUNT="mycustomarm64storage" |
| 72 | +CONTAINER_NAME="mycustomarm64container" |
| 73 | +VHD_NAME="azurelinux-arm64.vhd" |
| 74 | +GALLERY_NAME="MyCustomARM64Gallery" |
| 75 | +IMAGE_DEF_NAME="MyAzureLinuxARM64Def" |
| 76 | +IMAGE_VERSION="1.0.0" |
| 77 | +PUBLISHER="custom" |
| 78 | +OFFER="custom-offer" |
| 79 | +SKU="custom-sku" |
| 80 | +OS_TYPE="Linux" |
| 81 | +ARCHITECTURE="Arm64" |
| 82 | +HYPERV_GEN="V2" |
| 83 | +STORAGE_ACCOUNT_TYPE="Standard_LRS" |
| 84 | +VM_NAME="MyAzureLinuxARMVM" |
| 85 | +ADMIN_USER="azureuser" |
| 86 | +VM_SIZE="Standard_D4ps_v6" |
| 87 | +``` |
| 88 | + |
| 89 | +{{% notice Note %}} |
| 90 | +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. |
| 91 | +{{% /notice %}} |
| 92 | + |
| 93 | +#### 7. Create a Resource Group on Azure |
| 94 | +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. |
| 95 | + |
| 96 | +```bash |
| 97 | +$ az group create --name "$RESOURCE_GROUP" --location "$LOCATION" |
| 98 | +``` |
| 99 | + |
| 100 | +#### 8. Create Azure Blob Storage on Azure |
| 101 | + |
| 102 | +```bash |
| 103 | +$ az storage account create \ |
| 104 | + --name "$STORAGE_ACCOUNT" \ |
| 105 | + --resource-group "$RESOURCE_GROUP" \ |
| 106 | + --location "$LOCATION" \ |
| 107 | + --sku Standard_LRS \ |
| 108 | + --kind StorageV2 |
| 109 | +``` |
| 110 | + |
| 111 | +#### 9. Create Blob Container in the Blob Storage Account |
| 112 | + |
| 113 | +```bash |
| 114 | + $ az storage container create \ |
| 115 | + --name "$CONTAINER_NAME" \ |
| 116 | + --account-name "$STORAGE_ACCOUNT" |
| 117 | +``` |
| 118 | + |
| 119 | +#### 10. Upload VHD to the Blob container created in step 9 |
| 120 | + |
| 121 | +```bash |
| 122 | +$ az storage blob upload \ |
| 123 | + --account-name "$STORAGE_ACCOUNT" \ |
| 124 | + --container-name "$CONTAINER_NAME" \ |
| 125 | + --name "$VHD_NAME" \ |
| 126 | + --file ./azurelinux-arm64.vhd |
| 127 | +``` |
| 128 | + |
| 129 | +This successfully uploads the VHD to the Azure Blob Storage account. Confirm the same after visiting the blob storage of your Azure account. |
| 130 | + |
| 131 | +Now, let’s create a custom VM image from this VHD, using Azure Shared Image Gallery. |
| 132 | + |
| 133 | +#### 11. Create Azure Shared Image Gallery |
| 134 | +```bash |
| 135 | +$ az sig create \ |
| 136 | + --resource-group "$RESOURCE_GROUP" \ |
| 137 | + --gallery-name "$GALLERY_NAME" \ |
| 138 | + --location "$LOCATION" |
| 139 | +``` |
| 140 | + |
| 141 | +#### 12. Create the Image Definition |
| 142 | +```bash |
| 143 | +$ az sig image-definition create |
| 144 | + --resource-group "$RESOURCE_GROUP" |
| 145 | + --gallery-name "$GALLERY_NAME" |
| 146 | + --gallery-image-definition "$IMAGE_DEF_NAME" |
| 147 | + --publisher "$PUBLISHER" |
| 148 | + --offer "$OFFER" |
| 149 | + --sku "$SKU" |
| 150 | + --os-type "$OS_TYPE" |
| 151 | + --architecture "$ARCHITECTURE" |
| 152 | + --hyper-v-generation "$HYPERV_GEN" |
| 153 | +``` |
| 154 | + |
| 155 | +#### 13. Create Image Version |
| 156 | +```bash |
| 157 | +$ az sig image-version create |
| 158 | + --resource-group "$RESOURCE_GROUP" |
| 159 | + --gallery-name "$GALLERY_NAME" |
| 160 | + --gallery-image-definition "$IMAGE_DEF_NAME" |
| 161 | + --gallery-image-version "$IMAGE_VERSION" |
| 162 | + --location "$LOCATION" |
| 163 | + --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)}" |
| 164 | + --os-vhd-storage-account "$STORAGE_ACCOUNT" |
| 165 | + --storage-account-type "$STORAGE_ACCOUNT_TYPE" |
| 166 | +``` |
| 167 | + |
| 168 | +This registers the VHD as a version of your custom image. |
| 169 | + |
| 170 | +#### 14. Retrieve the Image ID |
| 171 | +Once the image has been versioned, retrieve the unique ID for use in VM creation. |
| 172 | + |
| 173 | +```bash |
| 174 | +$ IMAGE_ID=$(az sig image-version show |
| 175 | + --resource-group "$RESOURCE_GROUP" |
| 176 | + --gallery-name "$GALLERY_NAME" |
| 177 | + --gallery-image-definition "$IMAGE_DEF_NAME" |
| 178 | + --gallery-image-version "$IMAGE_VERSION" |
| 179 | + --query "id" -o tsv) |
| 180 | +``` |
| 181 | + |
| 182 | +#### 15. Create the VM Using the Custom Image |
| 183 | +Finally, create the VM with this custom image. |
| 184 | + |
| 185 | +```bash |
| 186 | +$ az vm create \ |
| 187 | + --resource-group "$RESOURCE_GROUP" \ |
| 188 | + --name "$VM_NAME" \ |
| 189 | + --image "$IMAGE_ID" \ |
| 190 | + --size "$VM_SIZE" \ |
| 191 | + --admin-username "$ADMIN_USER" \ |
| 192 | + --generate-ssh-keys \ |
| 193 | + --public-ip-sku Standard |
| 194 | +``` |
| 195 | + |
| 196 | +This deploys Azure Linux 3.0 Arm64 VM from the custom image. Confirm the same after visiting your Azure account “Virtual Machines” section. |
| 197 | + |
| 198 | +After the VM is successfully created, fetch the Public IP of the VM. |
| 199 | + |
| 200 | +```bash |
| 201 | +$ az vm show \ |
| 202 | + --resource-group "$RESOURCE_GROUP" \ |
| 203 | + --name "$VM_NAME" \ |
| 204 | + --show-details \ |
| 205 | + --query "publicIps" \ |
| 206 | + -o tsv |
| 207 | +``` |
| 208 | +With the Public IP retrieved, SSH into the VM. |
| 209 | + |
| 210 | +```bash |
| 211 | +$ ssh azureuser@<public-ip-address> |
| 212 | +``` |
| 213 | + |
| 214 | +Replace **public-ip-address** with the IP returned in the previous command. |
| 215 | + |
| 216 | +You can now log into your custom Azure Linux 3.0 Arm64 VM and start using it! |
| 217 | + |
0 commit comments