Skip to main content

Deploying a Virtual Machine

In this guide, we'll walk through the steps to deploy a Virtual Machine.

note

In this exercise not all commands to deploy the virtual machine are pre-provided.

A virtual machine needs a few things before it can be deployed:

  • A resource group to deploy the virtual machine to.
  • A virtual network to connect the virtual machine to.
  • A subnet to connect the virtual machine to.
  • A virtual machine image to deploy.
  • A virtual machine size to deploy.

In Azure, an image is a template that is used to create a new, running instance of a virtual machine. It can include an operating system and preinstalled applications.

  • Publisher: The organization that created the image. This could be Microsoft, Canonical (for Ubuntu), RedHat, SUSE, etc. They are responsible for creating and maintaining the image.
  • Offer: This is a group of related images created by a publisher.
    For example, a publisher like Canonical might have offers like 'Ubuntu Server 18.04 LTS', 'Ubuntu Server 20.04 LTS', etc.
  • SKU: This stands for Stock Keeping Unit. It's an instance of an offer, such as a major release of a distribution.
    For example, under the 'Ubuntu Server 18.04 LTS' offer, there might be SKUs for different configurations of that version, like '18.04-LTS-gen2', '18.04-LTS-gen1', etc.

Together, the Publisher, Offer, and SKU uniquely identify an image in Azure.

BICEP Module

You will use a Bicep module to deploy the virtual machine. Refer to this example in the introduction of how this is applied.

Define what SKU/image you want to deploy

In Azure we can deploy different types of virtual machine images.

First we need to define our publisher:

az vm image list-publishers -l westeurope --output table

This list will show a lot of publishers. For example, we can see the publisher Canonical which is the publisher for Ubuntu images.

To get a more filtered list use the following command:

az vm image list-publishers -l westeurope --query "[?starts_with(name, 'MicrosoftWin')]" --output table

This will show a list of publishers that start with MicrosoftWin and are available in the westeurope region.
This is the publisher for Windows images and will be used during this course.

Next we need to select an offer from the publisher:

az vm image list-offers --location westeurope --publisher MicrosoftWindowsServer --output table

For this course we will use the WindowsServer offer.

Finally we need to select a SKU from the offer:

az vm image list-skus --location westeurope --publisher MicrosoftWindowsServer --offer WindowsServer --output table

Now we have al the information we need to deploy a virtual machine operating system, these settings can be used in the bicep file.
You don't need to copy them.

param publisher string = 'MicrosoftWindowsServer'
param offer string = 'WindowsServer'
param sku string = '2022-datacenter-azure-edition'

If you want to deploy a linux or other marketplace image you need a combination of these three parameters.

Sizing the virtual machine

The next step is to size the virtual machine.

az vm list-sizes -l westeurope --output table

This list will show all the available virtual machine sizes in the westeurope region.

More info on when to apply which SKU can be found here.

For now we will use a cheap size for the virtual machine, this settings can be used in the bicep file.
You don't need to copy this.

param vmSize string = 'Standard_B2ms'
info

When your SKU is not available due to capacity restrictions, please re-run this powershell command to select another vmSize.

Create a bicep deploy file

Create new bicep file: virtualmachine.bicep.

targetScope = 'resourceGroup'

param location string = 'westeurope'
param vmName string

param publisher string
param offer string
param sku string

param vmSize string

param virtualNetworkResourceGroup string
param virtualNetworkName string
param subnetName string
param adminUsername string = 'LocalAdmin'
param osStorageAccountType string = 'Standard_LRS'
param privateIPAddress string = ''

var postNumberLength = 3
var networkInterfaceName = 'nic-${vmName}-${padLeft(1, postNumberLength, '0')}'
var varNicName =
var varOsDiskName = 'osdisk-${vmName}'
var varAdminPassword = '${uniqueString(resourceGroup().id)}${uniqueString(vmName)}d#*t1x!'
var varTimeZone = 'W. Europe Standard Time'
var varEnableAutomaticUpdates = false
var varPatchMode = 'Manual'
var varBootDiagnostics = true
var varComputerName = vmName
var varOsType = 'Windows'
var subnetID = resourceId(virtualNetworkResourceGroup, 'Microsoft.Network/virtualNetworks/subnets', virtualNetworkName, subnetName)

module modNetworkInterfaces './networkinterface.bicep' = {
name: 'nic-${networkInterfaceName}'
scope: resourceGroup()
params: {
location: location
nicName: networkInterfaceName
subnetID: subnetID
privateIPAddress: privateIPAddress
acceleratedNetworking: startsWith(vmSize, 'Standard_B') ? false : true
}
}

resource resVirtualMachine 'Microsoft.Compute/virtualMachines@2022-11-01' = {
name: vmName
location: location
identity: {
type: 'SystemAssigned'
}
zones: null
properties: {
licenseType: 'Windows_Server'
hardwareProfile: {
vmSize: vmSize
}
osProfile: {
computerName: varComputerName
adminUsername: adminUsername
adminPassword: varAdminPassword
windowsConfiguration: {
timeZone: varTimeZone
enableAutomaticUpdates: varEnableAutomaticUpdates
patchSettings: {
patchMode: varPatchMode
}
}
}
storageProfile: {
osDisk: {
name: varOsDiskName
osType: varOsType
createOption: 'FromImage'
caching: 'ReadOnly'
diskSizeGB: 127
managedDisk: {
storageAccountType: osStorageAccountType
}
}
imageReference: {
publisher: publisher
offer: offer
sku: sku
version: 'latest'
}
}
diagnosticsProfile: {
bootDiagnostics: {
enabled: varBootDiagnostics
}
}
networkProfile: {
networkInterfaces: [
{
id: resourceId('Microsoft.Network/networkInterfaces', networkInterfaceName)
}
]
}
}
dependsOn: [
modNetworkInterfaces
]
}

We now have created the bicep file to deploy a virtual machine.

Create a main bicep file

Create a bicep file and name this virtualmachine-main.bicep, at the following lines of code:

targetScope = 'subscription'

param location string = 'westeurope'
param resourceGroupName string
param vmName string

param virtualNetworkResourceGroup string
param virtualNetworkName string
param subnetName string

param publisher string = 'MicrosoftWindowsServer'
param offer string = 'WindowsServer'
param sku string = '2022-datacenter-azure-edition'
param vmSize string = 'Standard_B2ms'

module moduleResourceGroup './resourcegroup.bicep' = {
name: 'rg-${resourceGroupName}'
scope: subscription()
params: {
location: location
name: resourceGroupName
}
}

module moduleVirtualMachine './virtualmachine.bicep' = {
name: 'vm-${resourceGroupName}'
scope: resourceGroup(resourceGroupName)
params: {
location: location
vmName: vmName
virtualNetworkResourceGroup: virtualNetworkResourceGroup
virtualNetworkName: virtualNetworkName
subnetName: subnetName
publisher: publisher
offer: offer
sku: sku
vmSize: vmSize
}
dependsOn: [
moduleResourceGroup
]
}

Create bicepparam file from the virtualmachine-main.bicep file, and fill in the values you want to use for deployment.

Deploy the parameter file to your Azure environment.

Version overview

This document has the following versions:

VersionDateOverview of changes
1.12024-03021Add comments from test
1.02024-03-14Initial version.