Changing Azure Subscriptions
In part 1 I discussed logging into Azure using Azure CLI and noting the default subscription, as that is where Terraform will deploy resources to. However, you may have multiple Azure subscriptions and want to deploy to one that is not the default. This can be accomplished using the Azure CLI:
az account list
This will list the accounts / subscriptions that you have access to.
az account show
This lists details about the current account / subscription that you are currently using.
az account set --subscription "subscription_name_here"
Changes you to the subscription you have named. If you run “az account” show pre and post the “az account set” command you will be able to see the subscription change has taken effect.
If changing the account / subscription via the Azure CLI seems a bit messy then Terraform also includes an option to define which subscription the build should take place within. Open the main.tf file and edit:
provider "azurerm" {
features{}
}
To include a new line indicating the subscription ID of the subscription you want to build in:
provider "azurerm" {
subscription_id = "subscription_ID_here"
features {}
}
The subscription ID can be found using the Azure CLI commands listed above. Terraform will now deploy to this subscription, even if another subscription is set within the Azure CLI.
azurerm_virtual_machive Vs azurerm_linux_virtual_machine
In part 1 I used the resource “azurerm_virutal_machine” which can be used to create a Windows virtual machine or a Linux virtual machine. However, as I know I want a Linux virtual machine and I want the options that come with using a Linux virtual machine I can change this to use the “azurerm_linux_virtual_machine” resource instead.
The azurerm_linux_virtual_machine has some changes to settings:
Setting | Changed? | Now Known As |
name | no | n/a |
location | no | n/a |
resource_group_name | no | n/a |
network_interface_ids | no | n/a |
vm_size | yes | size |
storage_os_disk | yes | os_disk |
storage_image_reference | yes | source_image_reference |
os_profile | yes | options now sit on their own (i.e. computer_name is now outside of os_profile) |
os_profile_linux_config | yes | options now sit on their own (i.e. disable_passworth_authentication is now outside of os_profile_linux_config |
Using the virtual machine example from part 1 it would now look like:
resource "azurerm_linux_virutal_machine" "vm" {
name = var.servername
location = var.location
resource_group_name = azurerm_resource_group.rg.name
network_interface_ids = [azurerm_network_interface.nic.id]
size = var.vm_size
os_disk {
name = "os-${var.servname}-disk"
caching = "ReadWrite"
}
source_image_reference {
publisher = var.os.publisher
offer = var.os.offer
sku = var.os.sku
version = var.os.version
}
computer_name = var.servername
admin_username = var.admin_username
admin_password = var.admin_password
disable_password_authentication = false
tags = {
...
}
SSH Key
Using a password with SSH, even SSH locked down to certain IP addresses is not recommended in a production environment so we need to add an SSH key to the virtual machine during the Terraform process. To add a public key to the virtual machine add the following lines to azurerm_linux_virtual_machine resource in main.tf:
admin_ssh_key {
username = var.admin_username
public_key = file("path_to_file_here")
}
With these lines added the “disable_password_authentication” can be set to true and the private key (partner to the public key) can be used to connect via SSH to the virtual machine.
Automating / Scripting
Terraform building a virtual machine (and appropriate Azure resources) is pretty cool, but having to log in to add applications or configuration seems a little poor. Thankfully Azure has a “custom data” option for virtual machines (like AWS’ EC2 User Data) that can run scripts as the machine starts for the first time, and as its an option in Azure it is also available for use in Terraform.
To utilise this option create a bash script e.g. here’s one for installing Apache on an Ubuntu based virtual machine:
#! /bin/bash
sudo apt-get update
sudo apt-get install -y apache2
Save the script (e.g. as apache_install.sh) in a location you can navigate to. Add a new section to the main.tf Terraform file, I generally put this above the “resource azurerm_linux_virtual_machine” section:
data "template_file" "apache_install" {
template = file("path_to_file")
}
Then within the “resource azurerm_linux_virtual_machine” section add a new line around the computer_name details saying:
custom_data = base64encode(data.template_file.apache_install.rendered)
This encodes the bash script as base64 so that it can be passed into the custom data field. The final main.tf Terraform file should now include something similar to:
data "template_file" "apache_install" {
template = file("path_to_bash_script")
}
resource "azurerm_linux_virutal_machine" "vm" {
name = var.servername
location = var.location
resource_group_name = azurerm_resource_group.rg.name
network_interface_ids = [azurerm_network_interface.nic.id]
size = var.vm_size
os_disk {
name = "os-${var.servname}-disk"
caching = "ReadWrite"
}
source_image_reference {
publisher = var.os.publisher
offer = var.os.offer
sku = var.os.sku
version = var.os.version
}
computer_name = var.servername
admin_username = var.admin_username
admin_password = var.admin_password
disable_password_authentication = true
custom_data = base64encode(data.template_file.apache_install.rendered)
admin_ssh_key {
username = var.admin_username
public_key = file("path_to_public_key")
}
tags = {
...
}
If multiple applications and configuration changes need to be carried out it may be more efficient to use Ansible and a playbook.
One thought on “Terraform and Azure (Infrastructure as Code) – Part 2”
Comments are closed.