Using CDK for Terraform to spin up Azure VMs

In this post, you learn how to use CDK for Terraform to spin up Virtual Machines in Azure. This tutorial might incure costs in your account, so don’t forget to run “cdktf destroy” at the end.

First thing’s first, let’s initialize an empty CDK typescript project:

cdktf init

This brings a couple of interview-like questions which enables you to initialize the project. First, it asks you whether you want your statefile locally or in the cloud. For this demo, we opt for local version, but if you work within a team, or use this production workload, cloud variant could be the choice. Then with arrow keys you can choose the programming language of your choice. You can choose Typescript, Csharp, Java, go and many more.

Slightly different to AWS CDK, we then go to cdktf.json to declare the providers for our project. You add azurrm to the terraformProviders:

{
  "language": "typescript",
  "app": "npm run --silent compile && node main.js",
  "terraformProviders": ["azurerm@~> 2.46.0"],
  "terraformModules": [],
  "context": {
    "excludeStackIdFromLogicalIds": "true",
"allowSepCharsInLogicalIds": "true"
  }
}

This is an optional step, but go ahead and run “npm run get” which sets up some code for the providers, in our case, azure.

Open main.ts and add the following import statements to before class declaration:

import { Construct } from “constructs”; import { App, TerraformStack } from “cdktf”; import { AzurermProvider, VirtualNetwork, ResourceGroup, LinuxVirtualMachine, Subnet, NetworkInterface } from “./.gen/providers/azurerm”

Then we specifiy our provider:

new AzurermProvider(this, "AzureRm", {
  features: [{}]
})

Initializing our resource group:

let rg = new ResourceGroup(this, "rg1", {
      name: "rg1",
      location: "eastus"
})

We begin by creating our Virtual Network (or VPC in AWS terms):

let vnet = new VirtualNetwork(this, "vnet1", {
  name: "network1",
  location: rg.location,
  addressSpace: ["10.0.1.0/16"],
  resourceGroupName: rg.name
})

Subnet and Network Interface Card:

    let subnet = new Subnet(this, "subnet1", {
  name: "subnet1",
  resourceGroupName: rg.name,
  virtualNetworkName: vnet.name,
  addressPrefixes: ["10.0.2.0/24"]
})

let network_interface = new NetworkInterface(this, "nic", {
  name: "nic1",
  resourceGroupName: rg.name,
  location: rg.location,
  ipConfiguration: [{
    name: "internal",
    subnetId: subnet.id,
    privateIpAddressAllocation: "Dynamic"
  }]
})

Finally we add our VM:

    new LinuxVirtualMachine(this, 'vm1', {
  name: "vm1",
  resourceGroupName: rg.name,
  adminUsername: "testuser",
  size: "Standard_F2",
  location: rg.location,
  networkInterfaceIds: [
    network_interface.id
  ],
  osDisk: [{
    caching: "ReadWrite",
    storageAccountType: "Standard_LRS"
  }],
  sourceImageReference: [{
    publisher: "Canonical",
    offer: "UbuntuServer",
    sku: "16.04-LTS",
    version: "latest"
  }]
})

Just to be safe, verify your instanceType for the VM you want to choose.

Now we are ready to verify our cdk stack. First run ‘npm run build’ which compiles typescript to javascript. Then run cdktf synth. This should give a cloud formation template. If it returns an error, go to previous steps and verify your work.

The source code on github: https://github.com/pedramha/cdktf-azurevm

This project is maintained by pedramha