PowerShell, Office 365, Azure and automation
Provision Azure Traffic Manager with Terraform

Provision Azure Traffic Manager with Terraform

HashiCorp Terraform logo
HashiCorp Terraform

These days Terraform is the infrastructure as a code standard (IaC). Terraform can be used with various platforms, while I am writing about Azure here. One can provision almost any resource in Azure by Terraform. Terraform is a great tool for a resource provisioning automation and a cornerstone for DevOps. HashiCorp develops this tools and provides quite good Terraform documentation. Unfortunately, there are no specific examples of some Azure resource types. That’s why I made a decision to write this how-to provision Azure Traffic Manager with Terraform post.

Please see an example for Traffic Manager this time. Traffic Manager is a global load balancing solution. As an example, I make it directing traffic to two existing Application Gateway resource Public IP addresses sitting in Australia East and Australia Southeast regions.

Terraform : providers

Let’s start with the content for the primary code file main.tf. This code block is required to initialise Terraform and declare providers we are using (AzureRM in this case).  More information about “hashicorp/azurerm” Terraform provider can be found here.  The latest available version of Terraform AzureRM provider can be found here.

#####################
###   PROVIDERS   ###
#####################

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "2.59.0"
    }
  }
}

provider "azurerm" {
  features {}
}

Terraform : local variables

This block is to define local variables that can be used in various parts on the script. It is also good to have tags defined as variables so you can assign the same tags to all the resources you are provisioning. In this case we define resource groups, endpoint names and tags.

###########################
###   LOCAL VARIABLES   ###
###########################

locals {
  tm_location     = "Global"

  aue_shared_rg_name           = "${var.env}-aue-shared-rg"
  aue_fe_rg_name               = "${var.env}-aue-frontend-rg"
  aus_fe_rg_name               = "${var.env}-aus-frontend-rg"
  aue_front_pip                = "${var.env}-aue-appgw-pip"
  aus_front_pip                = "${var.env}-aus-appgw-pip"
  ep_name_aue = "${var.env}-aue-appgw"
  ep_name_aus = "${var.env}-aus-appgw"

  tags = {
    environment = "${var.env}"
    application = "Web"
    purpose     = "HA"
    owner       = "John Smith"
    location    = "${local.tm_location}"
  }
}

Terraform : input variables

There are more than one file can be used with Terraform. I have to mention, that there variables.tf file in the same folder as the primary file main.tf . The variables.tf file contains all the specific variables for this deployment. You can use these variables in any .tf file in the same folder.

The following block is the content of the variables.tf file for this deployment.

#####################
###   VARIABLES   ###
#####################

variable "locationlineaue" {
  default = "australiaeast"
}
variable "locationlineaus" {
  default = "australiaeast"
}
variable "env" {
  default = "ut"
}
variable "environment" {
  default = "UAT"
}
variable "ep_type" {
  default = "azureEndpoints"
}

Terraform : data sources

Getting back to the main.tf file. The next part of the script is the data query section. Here you can source properties of existing Azure resources. In this case, those resources required for our TM endpoints provisioning. If you have never done that before, I would recommend to read first How to use Terraform data sources page and type of resource properties available. The last one is explained in previously mentioned AzureRM module documentation.

In this block we query properties for earlier provisioned Application Gateways public IP-address. This is just an example. You may want to connect to another type of Azure resource in your case.

################
###   DATA   ###
################
## Querying resource groups
data "azurerm_resource_group" "aue_shared" {
  name = local.aue_shared_rg_name
}
data "azurerm_resource_group" "aue_frontend" {
  name = local.aue_fe_rg_name
}
data "azurerm_resource_group" "aus_frontend" {
  name = local.aus_fe_rg_name
}
## Querying public ip addresses
data "azurerm_public_ip" "aue_frontend_pip" {
  name                = local.aue_front_pip
  resource_group_name = local.aue_fe_rg_name
}
data "azurerm_public_ip" "aus_frontend_pip" {
  name                = local.aus_front_pip
  resource_group_name = local.aus_fe_rg_name
}

Terraform : Azure Traffic Manager resource provisioning

When all the variables and names in place, all the required resource properties obtained from the Azure environment – it is a good time to start provisioning resources.

#####################
###   RESOURCES   ###
#####################
# Create the TM 
resource "azurerm_traffic_manager_profile" "tm" {
  name                   = "${var.env}-net-tm"
  resource_group_name    = data.azurerm_resource_group.aue_shared.name
  traffic_routing_method = "Priority"
  dns_config {
    relative_name = "${var.env}-aue-tm"
    ttl           = 100
  }

# Create endpoint monitoring
  monitor_config {
    protocol                     = "HTTPS"
    port                         = 443
    path                         = "/"
    interval_in_seconds          = 60
    timeout_in_seconds           = 10
    tolerated_number_of_failures = 3
    expected_status_code_ranges  = ["200"]
  }

  traffic_view_enabled = "true"

  tags = local.tags
}

#Create Traffic Manager endpoints
resource "azurerm_traffic_manager_endpoint" "tm_ep_appgw_aue" {
  name                = "${local.ep_name_aue}-tf"
  resource_group_name = data.azurerm_traffic_manager_profile.tm.resource_group_name
  profile_name        = data.azurerm_traffic_manager_profile.tm.name
  type                = var.ep_type
  target              = data.azurerm_public_ip.aue_frontend_pip.fqdn
  target_resource_id  = data.azurerm_public_ip.aue_frontend_pip.id
  endpoint_location   = var.locationlineaue
  priority            = "1"
  depends_on = [
    data.azurerm_public_ip.aue_frontend_pip
  ]
}
resource "azurerm_traffic_manager_endpoint" "tm_ep_appgw_aus" {
  name                = "${local.ep_name_aus}-tf"
  resource_group_name = data.azurerm_traffic_manager_profile.tm.resource_group_name
  profile_name        = data.azurerm_traffic_manager_profile.tm.name
  type                = var.ep_type
  target              = data.azurerm_public_ip.aus_frontend_pip.fqdn
  target_resource_id  = data.azurerm_public_ip.aus_frontend_pip.id
  endpoint_location   = "${var.locationlineaus}"
  priority            = "2"
  depends_on = [
    data.azurerm_public_ip.aus_frontend_pip
  ]
}

Conclusion

As you can see it is not that difficult to provision Azure Traffic Manager with Terraform, but still quite complex because of dependencies on other resources.

You can download the code from this article by this link to GitHub

I would recommend you to just provision Azure Traffic Manager without endpoints first. When you get a success here you can add endpoints and other details to your Traffic Manager configuration.

You may also like to read more about Azure cost saving options.

Leave a Reply

Your email address will not be published. Required fields are marked *