Learn Terraform and deploy Azure resource via Azure DevOps pipeline (Part 4)
Part 4: Install application on Azure Virtual Machine using Terraform
In my last blog (Part 3), we have provisioned a Windows Virtual Machine (VM) using terraform modules. In this part we will learn how we can install an application or software on that VM.
At first, I will try to install IIS Web Server on the VM, as IIS is a built-in feature of Windows server, I do not need any executable to install it. I only need to run a PowerShell command to install IIS on the VM. I just have to figure out how I can run the command via terraform.
I was doing some research on this and found Azure Custom Script Extension is a great way to install something on a VM via terraform as to do this you do not need to login to the VM and hence, a private Azure DevOps agent is not necessary.
To, achieve this I am gonna create another module called install-iis, then call the module from main to install IIS on my VM. So below is my latest folder structure.
rohan@K42N:~/Documents/tfdemo$ tree --dirsfirst
.
└── azuredeploy
├── modules
│ ├── install-iis
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── README.md
│ │ └── variables.tf
│ ├── network-interface
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── README.md
│ │ └── variables.tf
│ ├── virtual-machine
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── README.md
│ │ └── variables.tf
│ └── virtual-network
│ ├── main.tf
│ ├── outputs.tf
│ ├── README.md
│ └── variables.tf
├── main.tf
├── terraform.tfvars
└── variables.tf
Lets take a look at the main.tf file of the install-iis module
resource "azurerm_virtual_machine_extension" "install-iis" {
name = "iis-webserver"
virtual_machine_id = var.virtual_machine_id
publisher = "Microsoft.Compute"
type = "CustomScriptExtension"
type_handler_version = "1.10"
settings = <<SETTINGS
{
"commandToExecute": "powershell Install-WindowsFeature -Name Web-Server -IncludeAllSubFeature"
}
SETTINGS
}
Here, I am gonna need the output of the virtual-machine module, which is the VM id. Under settings section, I am running a simple powershell command to install IIS Web Server feature including all sub-features. Technically I can run any powershell command within the VM this way.
Now that our new module is ready, we have to update main to call it. Let’s take a look.
terraform {
backend "azurerm" {}
}provider "azurerm" {
version = "=2.0.0"
features {}
}resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.location
}module "virtual-network" {
source = "./modules/virtual-network"virtual_network_name = var.virtual_network_name
resource_group_name = var.resource_group_name
location = var.location
virtual_network_address_space = var.virtual_network_address_space
subnet_name = var.subnet_name
subnet_address_prefix = var.subnet_address_prefix
}module "network-interface" {
source = "./modules/network-interface"vmname = var.vmname
location = var.location
resource_group_name = var.resource_group_name
subnet_id = module.virtual-network.subnet_id
}module "virtual-machine" {
source = "./modules/virtual-machine"vmname = var.vmname
location = var.location
resource_group_name = var.resource_group_name
network_interface_ids = [module.network-interface.nic_id]
vm_size = var.vm_size
os_disk_type = var.os_disk_type
admin_usename = var.admin_usename
admin_password = var.admin_password
image_publisher = var.image_publisher
image_offer = var.image_offer
image_sku = var.image_sku
}module "install-iis" {
source = "./modules/install-iis"virtual_machine_id = module.virtual-machine.vm_id
}
So, I just added the last module block where I am calling the install-iis module and passing out vm id output of virtual-machine module to it.
Now we have to perform the same steps again to deploy this on Azure.
- Commit code on local git repo
- Push code to Azure DevOps repo
- Run build pipeline
- Create a release
On successful release, we will be verify from portal that our custom extension has been provision successfully. We can login to the VM and check IIS as well.
Now, I was thinking what if I have to install something that has an executable. I have to copy the executable to the VM and install it, right? I think this can be achieved by using custom script extension as well. I will try this some time soon.
Thanks for reading, give it a 👏 if you like it. Please leave a comment and let me know if you have any feedback.