In this post, we will deploy a VM to Azure using Terraform, in the previous post we deployed the Resource Group and Virtual Network. Now we will build on this to add
- Virtual network
- Subnet
- Network security group
- Network interface
- Virtual Machine
At the bottom of the post the full config will be posted, let’s start looking at each section
# Configure the Microsoft Azure Provider.
provider "azurerm" {
version = "~>1.35"
}
This is the provider block as described here. When running Terraform init, this will instruct to download the Azurerm plugin
# Create a resource group
resource "azurerm_resource_group" "rsg" {
name = "ResourceGroup"
location = "eastus"
}
The resource block will create a resource group within the EastUS region, which all that other resources will be grouped under.
# Create virtual network
resource "azurerm_virtual_network" "vnet" {
name = "Vnet"
address_space = ["10.0.0.0/16"]
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
}
# Create subnet
resource "azurerm_subnet" "subnet" {
name = "Subnet"
resource_group_name = azurerm_resource_group.rsg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = "10.0.1.0/24"
}
Virtual machines need to connect to a network, the above first creates a Virtual Network and then assigns a subnet to the network. Notice that the resource_group_name uses an expression azurerm_resource_group.rsg.name, Terraform uses this to get the name of the resource group that is referenced by azurerm_resource_group resource with the name rsg. Also, virtural_network_name is using an expression to retrieve the Virtual Network name.
# Create public IP
resource "azurerm_public_ip" "publicip" {
name = "VMPublicIP01"
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
allocation_method = "Static"
}
To connect to the VM we assign it a public IP address.
# Create Network Security Group and rule
resource "azurerm_network_security_group" "nsg" {
name = "NSG"
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
A Network Security Group (NSG) is a stateful firewall, port 22 is needed opened to allow SSH traffic through so that we can connect to the VM.
# Create network interface
resource "azurerm_network_interface" "nic" {
name = "NIC"
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
network_security_group_id = azurerm_network_security_group.nsg.id
ip_configuration {
name = "myNICConfg"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "dynamic"
public_ip_address_id = azurerm_public_ip.publicip.id
}
}
A VM needs a network card, notice that it applies the NSG to the card. In a production network, the NSG is normally applied to the Subnet.
# Create a Linux virtual machine
resource "azurerm_virtual_machine" "vm" {
name = "mVM"
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
network_interface_ids = [azurerm_network_interface.nic.id]
vm_size = "Standard_DS1_v2"
storage_os_disk {
name = "myOsDisk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Premium_LRS"
}
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04.0-LTS"
version = "latest"
}
os_profile {
computer_name = "VM"
admin_username = "plankton"
admin_password = "Password1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
}
This is the part of the code which creates the VM.
Complete config
# Configure the Microsoft Azure Provider.
provider "azurerm" {
version = "~>1.35"
}
# Create a resource group
resource "azurerm_resource_group" "rsg" {
name = "ResourceGroup"
location = "eastus"
}
# Create virtual network
resource "azurerm_virtual_network" "vnet" {
name = "Vnet"
address_space = ["10.0.0.0/16"]
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
}
# Create subnet
resource "azurerm_subnet" "subnet" {
name = "Subnet"
resource_group_name = azurerm_resource_group.rsg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = "10.0.1.0/24"
}
# Create public IP
resource "azurerm_public_ip" "publicip" {
name = "VMPublicIP01"
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
allocation_method = "Static"
}
# Create Network Security Group and rule
resource "azurerm_network_security_group" "nsg" {
name = "NSG"
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
# Create network interface
resource "azurerm_network_interface" "nic" {
name = "NIC"
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
network_security_group_id = azurerm_network_security_group.nsg.id
ip_configuration {
name = "myNICConfg"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "dynamic"
public_ip_address_id = azurerm_public_ip.publicip.id
}
}
# Create a Linux virtual machine
resource "azurerm_virtual_machine" "vm" {
name = "mVM"
location = "eastus"
resource_group_name = azurerm_resource_group.rsg.name
network_interface_ids = [azurerm_network_interface.nic.id]
vm_size = "Standard_DS1_v2"
storage_os_disk {
name = "myOsDisk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Premium_LRS"
}
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04.0-LTS"
version = "latest"
}
os_profile {
computer_name = "VM"
admin_username = "plankton"
admin_password = "Password1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
}