Managing Azure DNS with Terraform
Learn how to set up and manage Azure DNS using Terraform, including zones, records, and private DNS
Managing Azure DNS with Terraform
Azure DNS is a hosting service for DNS domains that provides name resolution using Microsoft Azure infrastructure. This guide demonstrates how to set up and manage Azure DNS using Terraform.
Video Tutorial
Learn more about managing Azure DNS 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 concepts
Project Structure
terraform-azure-dns/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── dns/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── configs/
└── records.json
DNS Configuration
Create modules/dns/main.tf
:
# Public DNS Zone
resource "azurerm_dns_zone" "public" {
name = var.domain_name
resource_group_name = var.resource_group_name
soa_record {
email = "admin.${var.domain_name}"
expire_time = 2419200
minimum_ttl = 300
refresh_time = 3600
retry_time = 300
serial_number = 1
ttl = 3600
}
tags = var.tags
}
# Private DNS Zone
resource "azurerm_private_dns_zone" "private" {
name = "internal.${var.domain_name}"
resource_group_name = var.resource_group_name
soa_record {
email = "admin.internal.${var.domain_name}"
expire_time = 2419200
minimum_ttl = 300
refresh_time = 3600
retry_time = 300
ttl = 3600
}
tags = var.tags
}
# Virtual Network Link
resource "azurerm_private_dns_zone_virtual_network_link" "main" {
name = "${var.project_name}-link"
resource_group_name = var.resource_group_name
private_dns_zone_name = azurerm_private_dns_zone.private.name
virtual_network_id = var.virtual_network_id
registration_enabled = true
tags = var.tags
}
# A Records
resource "azurerm_dns_a_record" "www" {
name = "www"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
records = ["20.0.0.4"]
tags = var.tags
}
resource "azurerm_dns_a_record" "app" {
name = "app"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
target_resource_id = var.app_service_id
tags = var.tags
}
# CNAME Records
resource "azurerm_dns_cname_record" "blog" {
name = "blog"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
record = "blog.example.com"
tags = var.tags
}
# MX Records
resource "azurerm_dns_mx_record" "mail" {
name = "@"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
record {
preference = 10
exchange = "mail1.example.com"
}
record {
preference = 20
exchange = "mail2.example.com"
}
tags = var.tags
}
# TXT Records
resource "azurerm_dns_txt_record" "spf" {
name = "@"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
record {
value = "v=spf1 include:spf.protection.outlook.com -all"
}
tags = var.tags
}
# NS Records
resource "azurerm_dns_ns_record" "subdomain" {
name = "subdomain"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
records = [
"ns1.example.com",
"ns2.example.com"
]
tags = var.tags
}
# PTR Records
resource "azurerm_dns_ptr_record" "ptr" {
name = "ptr"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
records = ["contoso.com"]
tags = var.tags
}
# SRV Records
resource "azurerm_dns_srv_record" "service" {
name = "_sip._tcp"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
record {
priority = 1
weight = 5
port = 8080
target = "sip.example.com"
}
tags = var.tags
}
# CAA Records
resource "azurerm_dns_caa_record" "caa" {
name = "@"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
record {
flags = 0
tag = "issue"
value = "letsencrypt.org"
}
record {
flags = 0
tag = "issuewild"
value = ";"
}
tags = var.tags
}
# Private A Records
resource "azurerm_private_dns_a_record" "internal" {
name = "internal"
zone_name = azurerm_private_dns_zone.private.name
resource_group_name = var.resource_group_name
ttl = 300
records = ["10.0.0.4"]
tags = var.tags
}
# Private CNAME Records
resource "azurerm_private_dns_cname_record" "db" {
name = "db"
zone_name = azurerm_private_dns_zone.private.name
resource_group_name = var.resource_group_name
ttl = 300
record = "database.internal.${var.domain_name}"
tags = var.tags
}
Monitoring Configuration
- Diagnostic Settings
resource "azurerm_monitor_diagnostic_setting" "dns" {
name = "${var.project_name}-diag"
target_resource_id = azurerm_dns_zone.public.id
log_analytics_workspace_id = var.log_analytics_workspace_id
metric {
category = "AllMetrics"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
}
# DNS Alerts
resource "azurerm_monitor_metric_alert" "query_volume" {
name = "${var.project_name}-query-volume-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_dns_zone.public.id]
description = "Alert when DNS query volume is high"
criteria {
metric_namespace = "Microsoft.Network/dnszones"
metric_name = "QueryVolume"
aggregation = "Total"
operator = "GreaterThan"
threshold = 10000
}
action {
action_group_id = var.action_group_id
}
}
Advanced Features
- DNS Alias Records
resource "azurerm_dns_a_record" "alias" {
name = "alias"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
target_resource_id = var.public_ip_id
tags = var.tags
}
- Traffic Manager Integration
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 = 100
}
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_dns_cname_record" "tm" {
name = "tm"
zone_name = azurerm_dns_zone.public.name
resource_group_name = var.resource_group_name
ttl = 300
record = "${azurerm_traffic_manager_profile.main.name}.trafficmanager.net"
tags = var.tags
}
Best Practices
-
Security
- Use DNSSEC
- Configure CAA records
- Monitor queries
- Review access
-
Performance
- Set appropriate TTLs
- Use aliases
- Monitor latency
- Configure caching
-
High Availability
- Use Traffic Manager
- Configure failover
- Monitor health
- Review metrics
-
Cost Optimization
- Monitor usage
- Optimize queries
- Review records
- Clean up unused
Conclusion
You’ve learned how to set up and manage Azure DNS using Terraform. This setup provides:
- Public DNS zones
- Private DNS zones
- Record management
- Traffic routing
Remember to:
- Monitor queries
- Update records
- Review configurations
- Maintain zones