Managing AWS Route 53 with Terraform
A comprehensive guide to managing DNS records and routing policies with AWS Route 53 using Terraform
Managing AWS Route 53 with Terraform
AWS Route 53 is a highly available and scalable Domain Name System (DNS) web service. This guide shows how to manage Route 53 resources using Terraform.
Prerequisites
- AWS CLI configured
- Terraform installed
- Registered domain name (optional)
- Basic understanding of DNS concepts
Project Structure
aws-route53-terraform/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
Basic Route 53 Configuration
# main.tf
provider "aws" {
region = var.aws_region
}
# Hosted Zone
resource "aws_route53_zone" "main" {
name = var.domain_name
tags = {
Environment = var.environment
}
}
# A Record
resource "aws_route53_record" "www" {
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
ttl = "300"
records = [var.ip_address]
}
# CNAME Record
resource "aws_route53_record" "subdomain" {
zone_id = aws_route53_zone.main.zone_id
name = "blog.${var.domain_name}"
type = "CNAME"
ttl = "300"
records = ["${var.cname_target}"]
}
Alias Records for AWS Services
# Alias record for CloudFront distribution
resource "aws_route53_record" "cloudfront" {
zone_id = aws_route53_zone.main.zone_id
name = var.domain_name
type = "A"
alias {
name = var.cloudfront_domain_name
zone_id = var.cloudfront_hosted_zone_id
evaluate_target_health = false
}
}
# Alias record for ALB
resource "aws_route53_record" "alb" {
zone_id = aws_route53_zone.main.zone_id
name = "api.${var.domain_name}"
type = "A"
alias {
name = var.alb_dns_name
zone_id = var.alb_zone_id
evaluate_target_health = true
}
}
Health Checks
resource "aws_route53_health_check" "web" {
fqdn = "www.${var.domain_name}"
port = 80
type = "HTTP"
resource_path = "/"
failure_threshold = "3"
request_interval = "30"
tags = {
Name = "web-health-check"
}
}
# Record with health check
resource "aws_route53_record" "www_with_health_check" {
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
health_check_id = aws_route53_health_check.web.id
failover_routing_policy {
type = "PRIMARY"
}
set_identifier = "primary"
records = [var.primary_ip]
ttl = 60
}
Routing Policies
1. Weighted Routing
resource "aws_route53_record" "www_weighted" {
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
weighted_routing_policy {
weight = 90
}
set_identifier = "primary"
records = [var.primary_ip]
ttl = 60
}
resource "aws_route53_record" "www_weighted_secondary" {
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
weighted_routing_policy {
weight = 10
}
set_identifier = "secondary"
records = [var.secondary_ip]
ttl = 60
}
2. Latency-Based Routing
resource "aws_route53_record" "www_latency" {
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
latency_routing_policy {
region = "us-west-2"
}
set_identifier = "us-west-2"
records = [var.us_west_2_ip]
ttl = 60
}
resource "aws_route53_record" "www_latency_eu" {
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
latency_routing_policy {
region = "eu-west-1"
}
set_identifier = "eu-west-1"
records = [var.eu_west_1_ip]
ttl = 60
}
3. Geolocation Routing
resource "aws_route53_record" "www_geo" {
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
geolocation_routing_policy {
country = "US"
}
set_identifier = "us"
records = [var.us_ip]
ttl = 60
}
resource "aws_route53_record" "www_geo_default" {
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
geolocation_routing_policy {
country = "*"
}
set_identifier = "default"
records = [var.default_ip]
ttl = 60
}
Variables Configuration
# variables.tf
variable "aws_region" {
description = "AWS region"
type = string
default = "us-west-2"
}
variable "domain_name" {
description = "Domain name"
type = string
}
variable "environment" {
description = "Environment name"
type = string
default = "production"
}
variable "ip_address" {
description = "IP address for A record"
type = string
}
variable "cname_target" {
description = "Target for CNAME record"
type = string
}
Best Practices
-
DNS Management
- Use meaningful TTL values
- Implement proper health checks
- Use alias records for AWS services
- Consider using private hosted zones for internal resources
-
Security
- Enable DNSSEC for additional security
- Use proper IAM policies
- Implement logging with CloudWatch
-
High Availability
- Use multiple records with health checks
- Implement failover routing when needed
- Consider multi-region setups
-
Cost Optimization
- Monitor query logs
- Use appropriate routing policies
- Clean up unused health checks
Monitoring Configuration
resource "aws_cloudwatch_metric_alarm" "dns_queries" {
alarm_name = "${var.domain_name}-dns-queries"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "1"
metric_name = "DNSQueries"
namespace = "AWS/Route53"
period = "300"
statistic = "Sum"
threshold = "1000"
alarm_description = "DNS queries exceeded threshold"
alarm_actions = [var.sns_topic_arn]
dimensions = {
HostedZoneId = aws_route53_zone.main.zone_id
}
}
Deployment Steps
- Initialize Terraform:
terraform init
- Plan the deployment:
terraform plan
- Apply the configuration:
terraform apply
Clean Up
Remove all resources when done:
terraform destroy
Common Use Cases
- Multi-Region Application
resource "aws_route53_record" "api_failover" {
zone_id = aws_route53_zone.main.zone_id
name = "api.${var.domain_name}"
type = "A"
failover_routing_policy {
type = "PRIMARY"
}
alias {
name = var.primary_alb_dns
zone_id = var.primary_alb_zone_id
evaluate_target_health = true
}
set_identifier = "primary"
}
- Blue-Green Deployment
resource "aws_route53_record" "www_weighted" {
count = 2
zone_id = aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
weighted_routing_policy {
weight = count.index == 0 ? 100 : 0
}
alias {
name = var.environment_alb_dns[count.index]
zone_id = var.environment_alb_zone_id[count.index]
evaluate_target_health = true
}
set_identifier = count.index == 0 ? "blue" : "green"
}
Conclusion
This setup provides a comprehensive foundation for managing Route 53 resources using Terraform. Remember to:
- Plan your DNS architecture carefully
- Implement proper health checks and monitoring
- Use appropriate routing policies for your use case
- Keep your DNS records organized and documented
- Version control your Terraform configurations
The complete code can be customized based on your specific requirements and use cases.