Managing Azure Traffic Manager with Terraform

Learn how to set up and manage Azure Traffic Manager using Terraform, including routing methods and endpoint configurations

Managing Azure Traffic Manager with Terraform

Azure Traffic Manager is a DNS-based traffic load balancer that enables you to distribute traffic optimally to services across global Azure regions. This guide demonstrates how to set up and manage Traffic Manager using Terraform.

Video Tutorial

Learn more about managing Azure Traffic Manager with Terraform in this comprehensive video tutorial:

Prerequisites

  • Azure CLI configured with appropriate permissions
  • Terraform installed (version 1.0.0 or later)
  • Resource group created
  • Understanding of DNS and routing concepts

Project Structure

terraform-azure-trafficmanager/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│   └── trafficmanager/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
└── configs/
    └── endpoints.json

Traffic Manager Configuration

Create modules/trafficmanager/main.tf:

# Traffic Manager Profile
resource "azurerm_traffic_manager_profile" "main" {
  name                   = "${var.project_name}-tm"
  resource_group_name    = var.resource_group_name
  traffic_routing_method = "Performance"

  dns_config {
    relative_name = var.project_name
    ttl          = 60
  }

  monitor_config {
    protocol                     = "HTTPS"
    port                        = 443
    path                        = "/health"
    interval_in_seconds         = 30
    timeout_in_seconds          = 10
    tolerated_number_of_failures = 3
    custom_header {
      name  = "host"
      value = var.monitor_host
    }
    expected_status_code_ranges = ["200-299"]
  }

  traffic_view_enabled = true

  tags = var.tags
}

# Azure Endpoints
resource "azurerm_traffic_manager_azure_endpoint" "primary" {
  name               = "primary"
  profile_id         = azurerm_traffic_manager_profile.main.id
  target_resource_id = var.primary_app_id
  weight             = 100
  priority           = 1

  custom_header {
    name  = "x-region"
    value = "primary"
  }

  geo_mappings = ["WORLD"]
}

resource "azurerm_traffic_manager_azure_endpoint" "secondary" {
  name               = "secondary"
  profile_id         = azurerm_traffic_manager_profile.main.id
  target_resource_id = var.secondary_app_id
  weight             = 100
  priority           = 2

  custom_header {
    name  = "x-region"
    value = "secondary"
  }

  geo_mappings = ["WORLD"]
}

# External Endpoint
resource "azurerm_traffic_manager_external_endpoint" "backup" {
  name       = "backup"
  profile_id = azurerm_traffic_manager_profile.main.id
  target     = "backup.example.com"
  weight     = 100
  priority   = 3

  endpoint_location = var.backup_location

  custom_header {
    name  = "x-region"
    value = "backup"
  }

  geo_mappings = ["WORLD"]
}

# Nested Profile
resource "azurerm_traffic_manager_nested_endpoint" "nested" {
  name                      = "nested"
  profile_id                = azurerm_traffic_manager_profile.main.id
  target_resource_id        = azurerm_traffic_manager_profile.nested.id
  weight                    = 100
  priority                  = 4
  minimum_child_endpoints   = 1
  
  custom_header {
    name  = "x-region"
    value = "nested"
  }

  geo_mappings = ["WORLD"]
}

# Geographic Routing Profile
resource "azurerm_traffic_manager_profile" "geo" {
  name                   = "${var.project_name}-tm-geo"
  resource_group_name    = var.resource_group_name
  traffic_routing_method = "Geographic"

  dns_config {
    relative_name = "${var.project_name}-geo"
    ttl          = 60
  }

  monitor_config {
    protocol                     = "HTTPS"
    port                        = 443
    path                        = "/health"
    interval_in_seconds         = 30
    timeout_in_seconds          = 10
    tolerated_number_of_failures = 3
  }

  tags = var.tags
}

resource "azurerm_traffic_manager_azure_endpoint" "us" {
  name               = "us"
  profile_id         = azurerm_traffic_manager_profile.geo.id
  target_resource_id = var.us_app_id
  weight             = 100

  geo_mappings = ["US", "CA"]
}

resource "azurerm_traffic_manager_azure_endpoint" "eu" {
  name               = "eu"
  profile_id         = azurerm_traffic_manager_profile.geo.id
  target_resource_id = var.eu_app_id
  weight             = 100

  geo_mappings = ["GB", "FR", "DE"]
}

# Weighted Routing Profile
resource "azurerm_traffic_manager_profile" "weighted" {
  name                   = "${var.project_name}-tm-weighted"
  resource_group_name    = var.resource_group_name
  traffic_routing_method = "Weighted"

  dns_config {
    relative_name = "${var.project_name}-weighted"
    ttl          = 60
  }

  monitor_config {
    protocol                     = "HTTPS"
    port                        = 443
    path                        = "/health"
    interval_in_seconds         = 30
    timeout_in_seconds          = 10
    tolerated_number_of_failures = 3
  }

  tags = var.tags
}

resource "azurerm_traffic_manager_azure_endpoint" "prod" {
  name               = "prod"
  profile_id         = azurerm_traffic_manager_profile.weighted.id
  target_resource_id = var.prod_app_id
  weight             = 80
}

resource "azurerm_traffic_manager_azure_endpoint" "canary" {
  name               = "canary"
  profile_id         = azurerm_traffic_manager_profile.weighted.id
  target_resource_id = var.canary_app_id
  weight             = 20
}

## DNS Configuration

1. **DNS Zone Setup**
```hcl
resource "azurerm_dns_zone" "main" {
  name                = "example.com"
  resource_group_name = var.resource_group_name

  tags = var.tags
}

resource "azurerm_dns_cname_record" "tm" {
  name                = "www"
  zone_name           = azurerm_dns_zone.main.name
  resource_group_name = var.resource_group_name
  ttl                 = 300
  record              = azurerm_traffic_manager_profile.main.fqdn
}

Monitoring Configuration

  1. Diagnostic Settings
resource "azurerm_monitor_diagnostic_setting" "tm" {
  name                       = "${var.project_name}-diag"
  target_resource_id        = azurerm_traffic_manager_profile.main.id
  log_analytics_workspace_id = var.log_analytics_workspace_id

  metric {
    category = "AllMetrics"
    enabled  = true

    retention_policy {
      enabled = true
      days    = 30
    }
  }
}

resource "azurerm_monitor_metric_alert" "tm" {
  name                = "${var.project_name}-endpoint-alert"
  resource_group_name = var.resource_group_name
  scopes              = [azurerm_traffic_manager_profile.main.id]
  description         = "Alert when endpoint is degraded"

  criteria {
    metric_namespace = "Microsoft.Network/trafficManagerProfiles"
    metric_name      = "ProbeAgentCurrentEndpointStateByProfileResourceId"
    aggregation      = "Maximum"
    operator         = "GreaterThan"
    threshold        = 0
  }

  action {
    action_group_id = var.action_group_id
  }
}

Advanced Features

  1. Real User Measurements
resource "azurerm_traffic_manager_profile" "rum" {
  name                   = "${var.project_name}-tm-rum"
  resource_group_name    = var.resource_group_name
  traffic_routing_method = "Performance"

  dns_config {
    relative_name = "${var.project_name}-rum"
    ttl          = 60
  }

  monitor_config {
    protocol                     = "HTTPS"
    port                        = 443
    path                        = "/health"
    interval_in_seconds         = 30
    timeout_in_seconds          = 10
    tolerated_number_of_failures = 3
  }

  traffic_view_enabled = true

  tags = var.tags
}
  1. Subnet Routing
resource "azurerm_traffic_manager_profile" "subnet" {
  name                   = "${var.project_name}-tm-subnet"
  resource_group_name    = var.resource_group_name
  traffic_routing_method = "Subnet"

  dns_config {
    relative_name = "${var.project_name}-subnet"
    ttl          = 60
  }

  monitor_config {
    protocol                     = "HTTPS"
    port                        = 443
    path                        = "/health"
    interval_in_seconds         = 30
    timeout_in_seconds          = 10
    tolerated_number_of_failures = 3
  }

  tags = var.tags
}

Best Practices

  1. Performance

    • Choose appropriate routing method
    • Configure monitoring
    • Optimize TTL settings
    • Enable Traffic View
  2. High Availability

    • Use multiple endpoints
    • Configure health checks
    • Implement failover
    • Monitor endpoint status
  3. Global Distribution

    • Use geographic routing
    • Configure regional endpoints
    • Implement load balancing
    • Monitor regional performance
  4. Cost Optimization

    • Use appropriate routing
    • Monitor endpoints

Conclusion

You’ve learned how to set up and manage Azure Traffic Manager using Terraform. This setup provides:

  • Global traffic routing
  • Multiple routing methods
  • High availability
  • Performance optimization

Remember to:

  • Monitor endpoint health
  • Review routing settings
  • Update DNS records
  • Maintain endpoint configurations