Engineering Azure DNS Infrastructure with Terraform

The orchestration of Domain Name System (DNS) infrastructure is a critical pillar of cloud architecture. In the Azure ecosystem, DNS serves as the fundamental hosting service for domain name resolution using Microsoft Azure's global infrastructure. However, managing DNS records manually via the Azure Portal is fraught with risk, often leading to configuration drift, manual entry errors, and a lack of versioned history. To mitigate these risks, Infrastructure as Code (IaC) using Terraform allows engineers to define, preview, and deploy DNS zones and records with precision and repeatability.

Terraform utilizes HashiCorp Configuration Language (HCL) to specify the cloud provider and the specific elements of the cloud infrastructure. This declarative approach ensures that the desired state of the DNS environment is documented in code, allowing for the automatic spin-up of complete environments with proper DNS configurations and providing a full audit trail of every change.

Core Architecture and Prerequisites

Before deploying Azure DNS resources via Terraform, a specific set of environmental prerequisites must be met to ensure the provider can authenticate and communicate with the Azure Resource Manager (ARM) API.

The following table outlines the mandatory requirements for initiating a Terraform-led Azure DNS project:

Requirement Specification Purpose
Azure CLI Configured with appropriate permissions Authentication and account management
Terraform Version 1.0.0 or later (1.5.0+ recommended) Support for modern HCL syntax and AzureRM provider features
Resource Group Pre-created or defined in code Logical container for all DNS resources
DNS Concepts Foundational knowledge of A, CNAME, MX, SOA Understanding of record types and resolution logic

A professional project structure is essential for maintainability, especially when scaling from a simple test zone to a production enterprise environment. A recommended directory layout includes:

  • terraform-azure-dns/
    • main.tf: The primary configuration file where resources are declared.
    • variables.tf: Definitions for configurable parameters (e.g., domain names, subscription IDs).
    • outputs.tf: Definitions for values to be exported after deployment (e.g., DNS zone name).
    • modules/: Reusable logic for DNS components.
      • dns/
        • main.tf
        • variables.tf
        • outputs.tf
    • configs/: External configuration files, such as records.json, for data-driven record creation.

Provider Configuration and Environment Setup

To interact with Azure, the Terraform configuration must first define the required providers and versions. Using a dedicated versions.tf or including it in the main configuration ensures that the environment remains stable and is not broken by unexpected provider updates.

The current standard for modern Azure deployments requires Terraform version 1.5.0 or later and the azurerm provider version 4.0 or higher.

```hcl

versions.tf

terraform {
requiredversion = ">= 1.5.0"
required
providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}

provider "azurerm" {
features {}
subscriptionid = var.subscriptionid
}

variable "subscription_id" {
description = "Azure subscription ID to deploy resources into"
type = string
}
```

Once the provider is configured, a Resource Group must be established. This serves as the management boundary for the DNS zones and their associated records.

```hcl

main.tf

resource "azurermresourcegroup" "dns" {
name = "rg-dns-production"
location = "East US"
}
```

Implementing Public DNS Zones

A public DNS zone is used to host records that must be resolvable from the public internet. This is typically used for customer-facing websites, API endpoints, and mail servers. When an azurerm_dns_zone is created, Azure automatically assigns name servers that the domain registrar must point to for the zone to become active.

The Start of Authority (SOA) record is a critical component of the public zone, providing administrative information about the zone and timing parameters for caching.

```hcl

public-zone.tf

resource "azurermdnszone" "main" {
name = "example.com"
resourcegroupname = azurermresourcegroup.dns.name

soarecord {
email = "admin.example.com"
expire
time = 2419200
minimumttl = 300
refresh
time = 3600
retrytime = 300
serial
number = 1
ttl = 3600
}

tags = {
environment = "production"
managed_by = "terraform"
}
}
```

The SOA parameters defined above ensure that the DNS resolution behavior is predictable:
- refresh_time: The interval at which secondary DNS servers check for updates.
- retry_time: The time to wait before retrying a failed refresh.
- expire_time: The duration after which the zone data is considered invalid if the primary server is unreachable.
- minimum_ttl: The default time-to-live for records that do not have their own TTL specified.

Private DNS Zones and Virtual Network Integration

Unlike public DNS, Azure Private DNS zones provide custom domain name resolution specifically for virtual networks (VNets) within Azure. This allows engineers to use their own domain names for internal resources without needing to manage a custom DNS server (like BIND or Windows DNS) or exposing internal IP addresses to the public internet.

To make a Private DNS zone functional, it must be linked to a Virtual Network through a azurerm_private_dns_zone_virtual_network_link.

```hcl

Private DNS Zone

resource "azurermprivatednszone" "private" {
name = "internal.example.com"
resource
groupname = azurermresource_group.dns.name

soarecord {
email = "admin.internal.example.com"
expire
time = 2419200
minimumttl = 300
refresh
time = 3600
retry_time = 300
ttl = 3600
}

tags = {
environment = "internal"
managed_by = "terraform"
}
}

Virtual Network Link

resource "azurermprivatednszonevirtualnetworklink" "main" {
name = "project-dns-link"
resourcegroupname = azurermresourcegroup.dns.name
privatednszonename = azurermprivatednszone.private.name
virtualnetworkid = var.virtualnetworkid
registration_enabled = true
}
```

The registration_enabled property is particularly useful; when set to true, it allows Azure to automatically register the DNS records of virtual machines within the linked VNet into the private DNS zone.

Deploying the Azure DNS Private Resolver

For complex hybrid cloud scenarios—such as resolving names between an on-premises data center and an Azure VNet—the Azure DNS Private Resolver is employed. This service provides a specialized endpoint for DNS resolution, eliminating the need to maintain custom DNS VMs.

The deployment of a Private Resolver involves several interconnected components:
1. A dedicated Virtual Network (VNet).
2. A specific Subnet delegated to the DNS Private Resolver service.
3. The Resolver resource itself.

The DNS resolver is associated with the virtual network, and the subnet must be configured with a delegation to the Microsoft.Network/dnsResolvers service to function correctly. This ensures that the network traffic destined for DNS resolution is routed through the resolver's managed infrastructure.

Managing DNS Records with Terraform

Once the zone is established, adding records (such as A records, CNAME, or TXT) is the next step. Terraform allows these to be managed as separate resources, which prevents a single large file from becoming unmanageable.

For example, creating an A record to map a hostname to a specific IPv4 address:

hcl resource "azurerm_dns_a_record" "web_server" { name = "www" zone_name = azurerm_dns_zone.main.name resource_group_name = azurerm_resource_group.dns.name ttl = 300 records = ["10.0.0.4"] }

By using Terraform for records, teams gain a version history of every change, meaning that if a record is accidentally deleted or pointed to the wrong IP, the change can be reverted via a Git commit and a terraform apply.

Operational Workflow: Plan and Apply

The Terraform workflow follows a strict "Define -> Preview -> Deploy" lifecycle. This is critical for DNS, where a mistake can cause an entire application to go offline.

The Execution Cycle

  • terraform init: Initializes the working directory, downloads the azurerm provider, and sets up the backend.
  • terraform plan: Creates an execution plan. This is a preview of exactly what Azure resources will be created, modified, or destroyed. It allows the engineer to verify that only the intended records are being changed.
  • terraform apply: Executes the plan. Terraform makes the necessary API calls to Azure to bring the actual state in line with the configuration files.
  • terraform destroy: Removes all resources defined in the configuration. This is typically used in dev/test environments to save costs.

Verification and Validation

After applying the configuration, engineers can verify the deployment using the Azure CLI or PowerShell.

Using Azure CLI:
```bash

Retrieve the resource group and zone name from terraform outputs

resourcegroupname=$(terraform output -raw resourcegroupname)
dnszonename=$(terraform output -raw dnszonename)

Display the DNS zone information

az network dns zone show --resourcegroup $resourcegroupname --name $dnszone_name
```

Using Azure PowerShell:
```powershell
$resourcegroupname=$(terraform output -raw resourcegroupname)
$dnszonename=$(terraform output -raw dnszonename)

Get information about the new DNS service

Get-AzDnsZone -ResourceGroupName $resourcegroupname -Name $dnszonename
```

Comparative Analysis of DNS Zone Types

Choosing between a public and private zone depends entirely on the visibility requirements of the hosted records.

Feature Public DNS Zone Private DNS Zone
Accessibility Globally resolvable via internet Only resolvable within linked VNets
Primary Resource azurerm_dns_zone azurerm_private_dns_zone
Linking Assigned Name Servers VNet Links (azurerm_private_dns_zone_virtual_network_link)
Use Case Public Website, Email (MX) Internal microservices, DB endpoints
Auto-Registration No Yes (via VNet link)

Conclusion

Implementing Azure DNS through Terraform transforms DNS management from a manual, error-prone task into a disciplined engineering process. By leveraging HCL to define public zones, private zones, and the Azure DNS Private Resolver, organizations can ensure that their name resolution infrastructure is scalable, version-controlled, and resilient. The ability to define the Start of Authority (SOA) record precisely and link private zones to specific virtual networks provides a level of granular control that is unattainable through manual portal configurations.

The integration of the Azure DNS Private Resolver further extends these capabilities, enabling seamless hybrid-cloud name resolution. When combined with a rigorous workflow of terraform plan and terraform apply, the risk of DNS-related downtime is significantly reduced. For any modern Azure architecture, the transition to IaC for DNS is not merely an optimization but a necessity for maintaining stability and security in a dynamic cloud environment.

Sources

  1. Managing Azure DNS with Terraform
  2. Azure DNS Private Resolver Get Started Terraform
  3. Azure DNS Get Started Terraform
  4. Create an Azure DNS zone and record using Terraform
  5. How to create Azure DNS zones and records in Terraform

Related Posts