Terraform Azure Series: Parameters and Modules
As you may recall that I have started to publish my Terraform notes for Azure while I am experiencing it as future another obsolete reference :) Please refer my first introductory article if you haven't read the basics of infrastructure as code - IAC
Purpose of this article is to teach you basic concepts like variables, modules, state files through very basic provisioning of a virtual server from the Azure environment.
Variables & Modules:
Terraform stores bits and pieces of infra in *.tf files where you might have only one long tf file or multiple *.tf files to manage a large number of assets and for flexibility and modularity. You can use representative names for above-mentioned tf files such as securityGroups.tf, servers.tf, resourceGroups.tf, resourcemanaegrs.tf etc. All of these files combined into one large tf file behind the scenes once terraform command such as plan, apply or destroy is called.
The proper naming convention will give you a clear overview of the setting and objects to be created. As you can see in the above image, various settings and resources are stored in different files. For example, variables are stored in variables.tf, where "azure_region" is a variable and its default value, is set to "North Europe". Now see the below snippet that uses a variable defined in another file (variables.tf):
resource "azurerm_public_ip" "public_ip_for_prototypeVM" { name = "public_ip" location = "${var.azure_region}" resource_group_name = "${azurerm_resource_group.azure_resource_group.name}" allocation_method = "Dynamic" tags = { environment = "Public Ip Azure Demo" }
The code above (ipAddresses.tf) uses ${var.xxxxx} definition from variables.tf file and variables stored in this separate file can be reached from any tf file stored under the project folder.
location = "${var.azure_region}"
State Files:
State files such as terraform.tfstate keeps track of the id's of created resources to manage in later stages. Remember that state file might contain sensitive information such as plain passwords, secrets, connection strings, tenant id's and more so MUST NOT be committed to terraform the main repository.
Now is time to complete the mission: " spin a virtual server in the Azure Cloud" Here are the basic prerequisites:
Network/Sub Networks with private/public IP addresses.
Basic Security Group to control in/out traffic.
Network Interface - NIC to assign to our VM.
Let's start with the first item network and subnetwork as follows:
resource "azurerm_virtual_network" "azureVPC" { address_space = ["10.0.0.0/16"] location = "${var.azure_region}" name = "azureVPC" resource_group_name = "${azurerm_resource_group.azure_resource_group.name}" dns_servers = ["10.0.0.4","10.0.0.5"] } resource "azurerm_subnet" "subnetOne_for_AzureVPC" { address_prefix = "10.0.1.0/24" name = "subnetOne" resource_group_name = "${azurerm_resource_group.azure_resource_group.name}" virtual_network_name = "${azurerm_virtual_network.azureVPC.name}" } resource "azurerm_subnet" "subnetTwo_for_AzureVPC" { address_prefix = "10.0.2.0/24" name = "subnetOne" resource_group_name = "${azurerm_resource_group.azure_resource_group.name}" virtual_network_name = "${azurerm_virtual_network.azureVPC.name}"
}
The above code is self-explanatory: it creates a new virtual network called "azureVPC' with address space of 10.0.0.0/16 under main resource group. Similar to the virtual network, subnetworks are created accordingly subnetOne and subnetTwo. Below is our basic security group:
resource "azurerm_network_security_group" "security_group_standartPorts" { name = "standartPorts-SSH-Web" location = "${var.azure_region}" resource_group_name = "${azurerm_resource_group.azure_resource_group.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 = "*" }
}
Our security group only contains one inbound rule for the SSH port 22 that accepts any port and IP as a source address. Now it is time to define our NIC but before we need an IP address to assign it:
resource "azurerm_public_ip" "public_ip_for_prototypeVM" { name = "public_ip" location = "${var.azure_region}" resource_group_name = "${azurerm_resource_group.azure_resource_group.name}" allocation_method = "Dynamic" tags = { environment = "Public Ip Azure Demo" }
}
it is dynamically allocated IP address managed under same Azure resource group. Time to create a NIC and assign our fresh IP address to it:
resource "azurerm_network_interface" "interface1" { name = "interface1" location = "${var.azure_region}" resource_group_name = "${azurerm_resource_group.azure_resource_group.name}" network_security_group_id = "${azurerm_network_security_group.security_group_standartPorts.id}" ip_configuration { name = "myNicConfiguration" subnet_id = "${azurerm_subnet.subnetOne_for_AzureVPC.id}" private_ip_address_allocation = "Dynamic" public_ip_address_id = "${azurerm_public_ip.public_ip_for_prototypeVM.id}" }
}
Our NIC called interface1 uses public IP address created in the previous step. Now showtime: Ask for our first VM:
resource "azurerm_virtual_machine" "demo_VM" { name = "DemoVM" location = "${var.azure_region}" resource_group_name = "${azurerm_resource_group.azure_resource_group.name}" network_interface_ids = ["${azurerm_network_interface.interface1.id}"] vm_size = "Standard_B1s" storage_os_disk { name = "mainDisk" caching = "ReadWrite" create_option = "FromImage" managed_disk_type = "Standard_LRS" } storage_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "16.04.0-LTS" version = "latest" } os_profile { computer_name = "DemoVM" admin_username = "azureuser" } os_profile_linux_config { disable_password_authentication = true ssh_keys { path = "/home/azureuser/.ssh/authorized_keys" key_data = file("~/.ssh/id_rsa.pub") } }
}
Our Linux VM is very tiny as Standart B1s type with Standard main disk. Don't forget you can separate image references, os related information into a centeralized file for further flexibilit.y you can find the list of VM types and their details at:
https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-general
Our tiny ubuntu uses ssh key (read from a local system as a file("~/.ssh/id_rsa.pub") ) to login rather password-based authentication. I am sure that you know to generate a key as (MAC) or use Putty for MS. Windows systems:
ssh-keygen -t rsa -b 4096
Time to see everything is ok and you already know which command to run!
terraform plan
See if there aren't any errors. Fix them and be ready to spin your first VM with:
terraform apply
I assume you reply "yes" after the above command. You can now see the created resources:
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
Find out your IP address and login to your new Linux using ssh as:
Congratulations! Your first VM is ready now enjoy but delete all components for additional charges (terraform destroy)
Let me have some break and continue with another article such as deploy dockerized container or k8s using Terraform.
p.s. : Please let me know if you stuck at any step due to miss explanations again everything in a rush.

















