Terraform Functions - Part 4 - Advanced count and conditional expressions

In the final part of this blog series we will bring together the Terraform count and conditional expression functions in a more complex deployment to expand on what we learnt in part 2 and part 3.  We will deploy a Virtual Machine, using the conditional expression function to determine whether we should or shouldn't deploy a Public IP (PIP).  We use the count function to deploy multiple VMs, in part 2 of the blog series we used count to deploy a WebApp which was quite straightforward.  When deploying a VM we have related resources including NIC, PIPs and disks and we have to ensure we deploy the correct number of these and attach them to each VM resource.

In part 1 we cover an overview of the blog series and some pre-requisites you will need to get started when working through the deployment steps in this blog series, if you haven't seen this information please review this here before you get started with the steps below.  This include the code you will need to follow along with this lab.


WARNING!! In this lab we will be deploying a VNET (10.0.0/16) and subnet ( check these do not conflict with other networks in your Azure subscription before proceeding.

Let us firstly review how the count function is used in out templates.
  1. Review the code in \vm-foreach-demo\terraform.tfvars
  2. See that variable resource_count is currently set to 1
  3. Review the code in \vm-foreach-demo\virutal-machine.tfvars
  4. In the resource azurerm_virtual_machine you will see we use the count variable as we have done in Part 2 of this blog series
  5. If you take review the nested values and resources within the VM resource azurerm_virtual_machine you will see where we reference the count values
  6. On any name values we reference the value as below, this means as we deploy resources it will increment the count and name the resources accordingly for example, VM1, VM2, VM3.
    1. name = join("-", [var.prefix, "vm", count.index])
  7. When deploying multiple resources like  NIC, PIPs and disks as we are deploying multiple resources when we need to attach them to the VM using their resource IDs we have to reference the ID including the count index.  As we deploy multiple resources this has the effect of iterating through the count so NIC1 is attach to VM1, NIC2 is attached to VM2 and so on.  You can see how we reference the IDs in the example below.
    1. network_interface_ids = [azurerm_network_interface.test[count.index].id]
Now lets take a closer look at where and how we use the conditional expression function alongside count.
  1. Review the code in \vm-foreach-demo\terraform.tfvars
  2. See that variable public_ip is currently set to false
  3. Review the code in  \vm-foreach-demo\networking.tf
  4. Check the configuration of resource azurerm_public_ip
  5. See that we use the count and the conditional expression functions to check the value of var.public IP.  If it is "true" we set the count to the value of our variable resource count if it is "false" we set the value to 0 so no PIP will be deployed.
    1. count = var.public_ip == "true" ? var.resource_count : 0
  6. This has the effect of either creating or not creating a public IP. If we do deploy a PIP we increase the number of PIPs required to match the number of VMs
  7. Now check resource azurerm_network_interface you will see where we have to use a conditional expression again for the public IP address ID. If we don't deploy a PIP we need to pass this ID a null value so the deployment can continue
  8. You will see if we are deploying a PIP we also have to include the count index in the reference to the PIP ID so different PIPs get attached to different NIC/VMs 
    1. public_ip_address_id = var.public_ip == "true" ? azurerm_public_ip.test[count.index].id : ""
Deploying 1 VM and no Public IP

First we will deploy just one VM with no PIP to see how the resources look so we can compare this to the next deployment.
  1. Run terraform init
  2. Run terraform plan check there are no errors and confirm that it is going to deploy the resources you expect.
  3. Enter a Password for the VM and then enter and Admin username
  4. Run terraform apply and type yes to approve the change
  5. Check the Azure Portal to review what has been deployed in the resource group count-rg you should have the following resources deployed.  There should be now PIP.
  6. Notice how each resources except VNet has the count number, in this case, '0' in the name
Deploying 2 VMs and with Public IPs

Now we will increase the count to deploy multiple VMs and add public IP addresses to the NIC on each VM
  1. Edit terraform.tfvars and change 
    1.  public_ip from false to true
    2. resource_count to 2
  2. Save the changes
  3. Run terraform plan check there are no errors and confirm that it is going to deploy the resources you expect.
  4. Run terraform apply and type yes to approve the change
  5. Check the Azure Portal to review what has been deployed in the resource group count-rg you should now have the following resources;
  6. Note how we have two of every resource and we have Public IPs
  7. In the portal click on count-vm-0 
  8. Go to Networking and see how count-nic-0  is attached to count-vm-0 
  9. If you click on count-nic-0  you will see that in turn  count-publicip-0
  10. Go to Disks and see how count-osdisk-0  is attached to count-vm-0 
  11. If you do the same for count-vm-1 you will see that this has the resources ending in count 1 attached.  
  12. This method ensures we increase the count of all resources and iterate through the count to deploy and attach these resources.
  13. Now we need to clean up the resources we deployed in this lab
  14. From the terminal run terraform destroy
  15. Confirm that it is going to destroy only the resources you expect type yes to approve and cleanup the resources
  16. Check the resources have been deleted in the Azure Portal
After running through this lab you will have learned how we can use count and conditional expression functions in unison.  These functions help us to make Terraform configurations and modules that can fit different scenarios which adds to their re-usability. 

You can see where we use the conditional expression we can not only determine if a resource should be deployed by setting count to 0 or 1 but we can set the value of resources.  As an example, you could check the value of the environment if you are deploying to Dev you could set the SKU of a resources to small and if the environment is Prod you could set the SKU to large

I hope you have found this blog series useful and it helps you in creating your own Terraform configurations.  


Post a Comment

Popular posts from this blog

Terraform Functions - Part 3 - Conditional expression

Working with WSL and AKS

Azure Kubernetes Service (AKS) and Managed Identities