You already got an idea of the use case of Terraform and also about how we can connect to Azure using terraform. If not, please refer to my first two articles:
So far we are able to connect to Azure and now, we will deploy some serious entities inside Azure using terraform. In this article, I thought to proceed with an Azure virtual machine deployment. We are expected to get the below entities inside Azure after this proposed Terraform deployment.
So far we are able to connect to Azure and now, we will deploy some serious entities inside Azure using terraform. In this article, I thought to proceed with an Azure virtual machine deployment. We are expected to get the below entities inside Azure after this proposed Terraform deployment.
- A Windows 2016 server
- VNet with a dynamic public IP, Subnet, NSG, NIC etc...
- Connection ports open for HTTPS, WinRM and RDP. Able to connect using both RDP and WinRM
- VMAgent to run automatically
Terraform configuration(azurevm.tf) for this deployment has been uploaded here and only use that version for your reference. Below, I have explained the sections of interest so that you can refer to the configuration with a better understanding, rather than just following it.
- provider "azurerm" {}
- variable "location" {
- default = "Southeast Asia"
- }
- variable "username" {
- default = "jaishmathews"
- }
- variable "password" {
- default = "jaishmathews$1234"
- }
- resource "azurerm_resource_group" "resourceGroup" {
- name = "MindcrackerResourceGroup"
- location = "${var.location}"
- }
- resource "azurerm_public_ip" "publicip" { //Here defined the public IP
- name = "mindcrackpublicip"
- location = "${var.location}"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- public_ip_address_allocation = "Dynamic"
- idle_timeout_in_minutes = 30
- domain_name_label = "mindcrackvm" //Here defined the dns name
- tags {
- environment = "test"
- }
- }
- resource "azurerm_virtual_network" "vnet" { //Here defined the virtual network
- name = "mindcracknetwork"
- address_space = ["10.0.0.0/16"]
- location = "${var.location}"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- }
- resource "azurerm_network_security_group" "nsg" { //Here defined the network secrity group
- name = "mindcracknsg"
- location = "${var.location}"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- security_rule { //Here opened https port
- name = "HTTPS"
- priority = 1000
- direction = "Inbound"
- access = "Allow"
- protocol = "Tcp"
- source_port_range = "*"
- destination_port_range = "443"
- source_address_prefix = "*"
- destination_address_prefix = "*"
- }
- security_rule { //Here opened WinRMport
- name = "winrm"
- priority = 1010
- direction = "Inbound"
- access = "Allow"
- protocol = "Tcp"
- source_port_range = "*"
- destination_port_range = "5985"
- source_address_prefix = "*"
- destination_address_prefix = "*"
- }
- security_rule { //Here opened https port for outbound
- name = "winrm-out"
- priority = 100
- direction = "Outbound"
- access = "Allow"
- protocol = "*"
- source_port_range = "*"
- destination_port_range = "5985"
- source_address_prefix = "*"
- destination_address_prefix = "*"
- }
- security_rule { //Here opened remote desktop port
- name = "RDP"
- priority = 110
- direction = "Inbound"
- access = "Allow"
- protocol = "Tcp"
- source_port_range = "*"
- destination_port_range = "3389"
- source_address_prefix = "*"
- destination_address_prefix = "*"
- }
- tags {
- environment = "test"
- }
- }
- resource "azurerm_subnet" "subnet" { //Here defined subnet
- name = "mindcracksubnet"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- virtual_network_name = "${azurerm_virtual_network.vnet.name}"
- address_prefix = "10.0.2.0/24"
- }
- resource "azurerm_network_interface" "nic" { //Here defined network interface
- name = "mindcracknic"
- location = "${var.location}"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- network_security_group_id = "${azurerm_network_security_group.nsg.id}"
- ip_configuration {
- name = "mindcrackconfiguration"
- subnet_id = "${azurerm_subnet.subnet.id}"
- private_ip_address_allocation = "dynamic"
- public_ip_address_id = "${azurerm_public_ip.publicip.id}"
- }
- }
- resource "azurerm_storage_account" "storageacc" { //Here defined a storage account for disk
- name = "mindcrackstoacc"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- location = "${var.location}"
- account_tier = "Standard"
- account_replication_type = "GRS"
- }
- resource "azurerm_storage_container" "storagecont" { //Here defined a storage account container for disk
- name = "mindcrackstoragecont"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- storage_account_name = "${azurerm_storage_account.storageacc.name}"
- container_access_type = "private"
- }
- resource "azurerm_managed_disk" "datadisk" { //Here defined data disk structure
- name = "mindcrackdatadisk"
- location = "${var.location}"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- storage_account_type = "Standard_LRS"
- create_option = "Empty"
- disk_size_gb = "1023"
- }
- resource "azurerm_virtual_machine" "vm" { //Here defined virtual machine
- name = "mindcrackvm"
- location = "${var.location}"
- resource_group_name = "${azurerm_resource_group.resourceGroup.name}"
- network_interface_ids = ["${azurerm_network_interface.nic.id}"]
- vm_size = "Standard_A2" //Here defined virtual machine size
- storage_image_reference { //Here defined virtual machine OS
- publisher = "MicrosoftWindowsServer"
- offer = "WindowsServer"
- sku = "2016-Datacenter"
- version = "latest"
- }
- storage_os_disk { //Here defined OS disk
- name = "mindcrackosdisk"
- caching = "ReadWrite"
- create_option = "FromImage"
- managed_disk_type = "Standard_LRS"
- }
- storage_data_disk { //Here defined actual data disk by referring to above structure
- name = "${azurerm_managed_disk.datadisk.name}"
- managed_disk_id = "${azurerm_managed_disk.datadisk.id}"
- create_option = "Attach"
- lun = 1
- disk_size_gb = "${azurerm_managed_disk.datadisk.disk_size_gb}"
- }
- os_profile { //Here defined admin uid/pwd and also comupter name
- computer_name = "mindcrackhost"
- admin_username = "${var.username}"
- admin_password = "${var.password}"
- }
- os_profile_windows_config { //Here defined autoupdate config and also vm agent config
- enable_automatic_upgrades = true
- provision_vm_agent = true
- winrm = { //Here defined WinRM connectivity config
- protocol = "http"
- }
- }
- }
Verification of this deployment includes the below steps. I am not mentioning about how to run a terraform configuration file as it has been mentioned in my previous articles.
- Successful Deployment
Please verify that you got something like below on command prompt before anything else.
- Verify Azure Portal
You should see something like the below image,
- Test RDP
You should be able to login with uid/pwd inside the configuration file. Below is the screenshot from my side after login using the IP showing in the Azure portal
- Verify WinRM
After your successful login above, open a command prompt as Admin in the same logged machine. Then run the below command to get the details of an HTTP listener for WinRM connection, as mentioned in our configuration.
- Verify Running VMAgent
In the same logged machine, open task manager and click more details option on the bottom left side of the task manager window. Then make sure that the below task is running.
- Verify Remote WinRM Connection
We should be able to connect to our new VM using WinRM remotely. So, again come back to your local machine from where you are running terraform. Open PowershellISE as Admin. Then try the below 4 commands. The first three commands are to establish a WinRM connection to our new VM and the fourth command is a normal command to make sure that the connected machine is our new VM.
That's all there is to show here. Please refer to the attached configuration file. In this series, next, I will show how to run certain bootstrap scripts during this VM deployment as part of Terraform. Until then, cheers.




Anrudh BPosted Aug 6, 2019, 5:48 AM
9444905898 India(91)
Anrudh BPosted Aug 6, 2019, 5:48 AM
Hi Jaish Mathews , Pls ping me on WhatsApp
Jingwei ZhangPosted Jul 16, 2019, 4:11 PM
Those screen shots of verification are not very clear to see
Vikas SrivastavaPosted Jul 23, 2018, 1:08 AM
Nice one..
Viknaraj ManogararajahPosted Jul 20, 2018, 7:06 PM
thank you for sharing
Hadshana KamalanathanPosted Jul 20, 2018, 4:05 AM
Nice explanation...
Jaish MathewsPosted Jul 20, 2018, 2:17 AM
Really happy if this helps you and it's not ARM template, but terraform config file. ARM template for creating VM is different :)
Prabu ElavarasanPosted Jul 20, 2018, 1:12 AM
Thanks much for the clear explanation and for the ARM Template :-)