After terraform is installed on the computer you use to deploy your first cloud resources – the initial sample in chapter 2 is to deploy a VM. A Linux based VM. You can find all the samples out of the book from Yevgeniy under this repro in GitHub.
So how do we do this in azure?
Deploy your first VM in Azure
One main difference to aws is that in Azure we deploy resources always in a resource group (RG) – so the script in Terraform is not so easy as in aws.
resource "azurerm_resource_group" "RG" { name = "myFirstTerraform-RG" location = "westeurope" }
So having the resource group deployed we can use it to put the VM in there. that’s not all we need to deploy a VM in Azure. Let’s have a look at the documentation of the Azure provider at HashiCorp for the “azurerm_virtual_machine”. And as you read the introduction you see, there is another resource type in the provider to directly focus on a Linux VM – “azurerm_linux_virtual_machine”.
Going thru the documentation we will find, that we need the following CONFIG arguments for a Linux VM:
- admin_username
- location
- name
- network_interface_ids
- os_disk
- resource_group_name
- size
and for sure one of these:
- admin_password
(if this option is used – be aware that _disable_passwordauthentication must be set to false) - admin_ssh_key
So if we compare this with a simple example in chapter 2 of the book – Azure seems to be more complex. For me it looks like that in aws you can a template and aws will add every configuration you needed with some default values (see page 43). So the Azure Resource Manager needs the configuration defined by the admin or better the script.
So let’s get back to our script.
We already have now the RG in it. Now we need to deploy a network:
resource "azurerm_virtual_network" "vnet" { name = "myFirstVnet" address_space = ["10.0.0.0/16"] location = "myFirstTerraform-RG" resource_group_name = "westeurope" }
In the Book, the concept of “DRY” is explained later, but I think it is good to think about it now. “DRY” means “don’t repeat yourself”. It would be no good idea to reference the location and the ressource_group_name by filling in the values defined in the script before. It is better to point to the values.
_{ressource}.{name}.{config}_
If we want to reference the name of the RG, we have to use:
azurerm_resource_group.myFirstTerraform-RG.name
and the same with the location used in the definition of the RG:
azurerm_resource_group.myFirstTerraform-RG.location
Taking this into the code leads to the following
resource "azurerm_virtual_network" "vnet" { name = "myFirstVnet" address_space = ["10.0.0.0/16"] location = azurerm_resource_group.myFirstTerraform-RG.name resource_group_name = azurerm_resource_group.myFirstTerraform-RG.location }
What is important to understand that terraform is now able to identify dependencies between the resources and can handle the order of deploying the needed resources (see Chapter 2 in the book page 51). The next steps in your terraform script would now to add all needed Resources including references as well as the VM itself.
The whole script would look like this:
## Deploy your first VM to Azure ## based on an Ubunto Image ## Define the provider provider "azurerm" { version = "~>2.0.0" features {} } ## define the resource gruop resource "azurerm_resource_group" "myFirstTerraform" { name = "myFirstTerraform-RG" location = "West Europe" } ## define the network resource "azurerm_virtual_network" "myFirstTerraform" { name = "myFirstTerraform-vNet" address_space = ["10.0.0.0/16"] location = azurerm_resource_group.myFirstTerraform.location resource_group_name = azurerm_resource_group.myFirstTerraform.name } ## define the subnet resource "azurerm_subnet" "myFirstTerraform" { name = "internal" resource_group_name = azurerm_resource_group.myFirstTerraform.name virtual_network_name = azurerm_virtual_network.myFirstTerraform.name address_prefix = "10.0.2.0/24" } ## define a public ip for the vm to ssh in resource "azurerm_public_ip" "myFirstTerraform" { name = "myFirstTerraform-pip" location = azurerm_resource_group.myFirstTerraform.location resource_group_name = azurerm_resource_group.myFirstTerraform.name allocation_method = "Dynamic" } ## define the networkinterface resource "azurerm_network_interface" "myFirstTerraform" { name = "myFirstTerraform-nic" location = azurerm_resource_group.myFirstTerraform.location resource_group_name = azurerm_resource_group.myFirstTerraform.name ip_configuration { name = "internal" subnet_id = azurerm_subnet.myFirstTerraform.id private_ip_address_allocation = "Dynamic" public_ip_address_id = azurerm_public_ip.myFirstTerraform.id } } ## define the VM resource "azurerm_linux_virtual_machine" "myFirstTerraform" { name = "myFirstTerraform-vm" resource_group_name = azurerm_resource_group.myFirstTerraform.name location = azurerm_resource_group.myFirstTerraform.location size = "Standard_B2s" computer_name = "myFirstLinuxVM" admin_username = "adminuser" admin_password = "Password1234!" disable_password_authentication = false network_interface_ids = [ azurerm_network_interface.myFirstTerraform.id, ] os_disk { caching = "ReadWrite" storage_account_type = "Standard_LRS" } source_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "16.04-LTS" version = "latest" } }
CAUTION We do not have defined any firewall in front of the VM. In azure we need e.g. a network security group for this, so one more component should be added to your script and should be applied to the network înterface.
To define a network security group in the script:
resource "azurerm_network_security_group" "myFirstTerrafrom" { name = "myFirstTerrafrom-NSG" location = azurerm_resource_group.myFirstTerraform.location resource_group_name = azurerm_resource_group.myFirstTerraform.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 = "*" } }
and we need the assignment to the network interface:
resource "azurerm_network_interface_security_group_association" "myFirstTerraform" { network_interface_id = azurerm_network_interface.myFirstTerraform.id network_security_group_id = azurerm_network_security_group.myFirstTerraform.id }
As soon as I have finished the whole chapter 2 – I will provide a GitHub Repro with all the information.