The Microsoft Cloud Blog

Expert insights on Microsoft Azure, Cloud Architecture, and Enterprise Technology

3 min read

How to: Deploy a Virtual Machine to Azure using Bicep.

As some of the readers will know I became aware of and blogged about Bicep a month or so ago. Since then work has interfered with me giving this more than a cursory glance. However, I started to look at this in a little more detail last week.

Anyway, I was interested in seeing how I could use bicep to deploy a virtual machine to Azure. As a result of this I came up with the following simple example. Please note I only included the components that I would need to deploy and access a Windows VM, this included a VNet, Public IP (to allow for RDP connections) and a network interface. I have not included elements such as additional storage etc. and have made an assumption that a target resource group already exists.

Just for ease of use I have included everything in one bicep file and have not parametrising some of the variables, I will do this as part of my next post in this series which will take this starting file and extend it to allow deployment of multiple VMs.

First off, I needed to create a VNet and a subnet, to do this I used the following code.

resource VNet_Default 'Microsoft.Network/virtualNetworks@2020-08-01' = {
  name: 'VMVNet01'
  location: 'uksouth'
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/24'
      ]
    }
    subnets: [
      {
        name: 'VMSubnet'
        properties: {
          addressPrefix: '10.0.0.0/24'
          delegations: []
          privateEndpointNetworkPolicies: 'Enabled'
          privateLinkServiceNetworkPolicies: 'Enabled'
        }
      }
    ]
    virtualNetworkPeerings: []
    enableDdosProtection: false
  }
}

I also want a public IP address as this will allow me to access the VM via Remote Desktop. However, if you are using a bastion service or similar or want to use SSH then this may not be required or will need to be modified.

resource VM_PublicIP 'Microsoft.Network/publicIPAddresses@2021-02-01' ={
  name:'VMPublicIPAddress'
  location: 'uksouth'
  sku: {
    name: 'Basic'
    tier: 'Regional'
  }
  properties: {
    publicIPAddressVersion: 'IPv4'
    publicIPAllocationMethod: 'Dynamic'
  }
}

Finally, before getting to the VM creation template I need to add a network interface to the VM incorporating the VNet and Public IP address created using the above sections, to do this use the below structure.

resource NIC_VM 'Microsoft.Network/networkInterfaces@2020-08-01' = {
  name: 'nic01'
  location: 'uksouth'
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig1'
        properties: {
          publicIPAddress: {
            id: VM_PublicIP.id
          }
          privateIPAllocationMethod: 'Dynamic'
          subnet: {
            id: '${VNet_Default.id}/subnets/${'vmSubnet'}'
          }
          primary: true
          privateIPAddressVersion: 'IPv4'
        }
      }
    ]
  }
}

At this point I have the code for all the prerequisite components that the virtual machine requires. However, there is one area which required a bit of thought/work and that is the information needed for the underlying OS image, which includes the parameters publisher, offer, SKU & version. To get these details there are a suite of PowerShell commands which can be used for this (Get-AzVMImagePublisher, Get-AzVMImageOffer, Get-AzVMImageSku & Get-AzVMImage) see https://bit.ly/3lQanbd for more information and the links to the other commands.

Once you have the details for the above then use the following to create the VM.

resource VirtualMachine 'Microsoft.Compute/virtualMachines@2021-03-01' = {
  name: 'VM01'
  location: 'uksouth'
  properties:{
    hardwareProfile: {
      vmSize:'Standard_D2s_v3'
      }
      storageProfile: {
        osDisk: {
          createOption: 'FromImage'
          osType: 'Windows'
          managedDisk: {
            storageAccountType: 'StandardSSD_LRS'
          }
        }
        imageReference: {
          publisher: 'MicrosoftWindowsDesktop'
          offer: 'Windows-10'
          sku: '19H1-ent'
          version: '18362.1198.2011031735'
        }
      }
      osProfile: {
        computerName: 'testcomputer'
        adminUsername: 'vmAdministrator'
        adminPassword: 'Adm1nP@55w0rd'
      }
      networkProfile: {
        networkInterfaces: [
          {
            id: NIC_VM.id
          }
        ]
      }
  }
}

At this point you will just need to run the following line of PowerShell to deploy the templates. Please note this is assuming that the resource group already exists.

New-AzResourceGroupDeployment -ResourceGroupName '<ResourceGroupName>' -TemplateFile ./<filename>.bicep 

I will upload the full sample code to GitHub and will publish the link here a little later.

UPDATED:
I have now uploaded the code samples to my public GitHub repository which can be found here https://bit.ly/3lQ2FOw.

Want more cloud insights? Listen to Cloudy with a Chance of Insights podcast:

Spotify | YouTube | Apple Podcasts

Like this article?

Comments

Loading comments...

Richard Hogan - Global Chief Architect, Microsoft Practice

Richard Hogan

Global Chief Architect, Microsoft Practice | IBM

Global Chief Architect, Microsoft Practice at IBM. 20+ years experience working at the intersection of cloud architecture, security, and emerging AI capabilities across Azure and the wider Microsoft ecosystem. Host of the Cloudy with a Chance of Insights podcast. Regular speaker at tech conferences and active contributor to the Microsoft Tech Community.

You might also like

Practical discussions on cloud engineering, architecture, and the reality behind the diagrams.

Bi-weekly reflections on cloud architecture, Azure, and the decisions teams wrestle with in practice.