When working with AWS VPCs, one persistent challenge is maintaining reliable internal DNS resolution. Traditional approaches like manually updating /etc/hosts files or running custom DNS servers (MaraDNS, BIND) create operational overhead and fragility.
Consider this common scenario: Your application servers need to connect to a database cluster. Hardcoding IP addresses creates maintenance headaches:
# Bad practice - IP-based connection
db_connection = "jdbc:mysql://10.0.1.25:3306/mydb"
# Better - DNS-based connection
db_connection = "jdbc:mysql://db-primary.internal.example.com:3306/mydb"
AWS Route53 offers private hosted zones that solve this elegantly. Here's how to implement it:
aws route53 create-hosted-zone \
--name internal.example.com \
--vpc VPCRegion=us-west-2,VPCId=vpc-1a2b3c4d \
--caller-reference $(date +%s) \
--hosted-zone-config Comment="Internal DNS",PrivateZone=true
With VPC DNS settings enabled (enableDnsHostnames and enableDnsSupport), EC2 instances automatically register:
- Instance name: ip-10-0-1-25.ec2.internal
- Reverse DNS: 25.1.0.10.in-addr.arpa
For custom naming (like db-primary.internal.example.com):
aws route53 change-resource-record-sets \
--hosted-zone-id Z1234567890 \
--change-batch '{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "db-primary.internal.example.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{ "Value": "10.0.1.25" }]
}
}]
}'
For systems that can't use Route53 directly, consider a DNS forwarder:
# /etc/bind/named.conf.local
zone "internal.example.com" {
type forward;
forwarders { 10.0.0.2; }; # VPC DNS server
};
Verify your setup with dig/nslookup:
dig +short db-primary.internal.example.com
nslookup 10.0.1.25
Remember to configure your VPC DHCP options set to use the AmazonProvidedDNS server (169.254.169.253).
When working with non-RDS database servers or any inter-service communication within AWS VPC, relying on IP addresses creates several operational challenges:
# Bad practice - Hardcoded IP
database_url = "jdbc:postgresql://10.0.1.25:5432/mydb"
# Better practice - DNS name
database_url = "jdbc:postgresql://db-primary.internal.mydomain.com:5432/mydb"
AWS Route53 Private Hosted Zones provide a fully managed DNS service specifically for VPC environments. Unlike maintaining separate DNS servers or /etc/hosts files, this offers:
- Automatic DNS resolution for EC2 instances using their hostnames
- Seamless integration with AWS services (RDS, Elasticache, etc.)
- High availability without managing servers
- Tag-based DNS record management
Creating a Private Hosted Zone via AWS CLI:
aws route53 create-hosted-zone \
--name internal.mydomain.com \
--vpc VPCRegion=us-west-2,VPCId=vpc-1a2b3c4d \
--caller-reference $(date +%s) \
--hosted-zone-config Comment="Internal VPC DNS",PrivateZone=true
Automating DNS registration for EC2 instances:
#!/bin/bash
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
PRIVATE_IP=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)
HOSTNAME=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$INSTANCE_ID" "Name=key,Values=Name" --query 'Tags[0].Value' --output text)
aws route53 change-resource-record-sets --hosted-zone-id Z1234567890 \
--change-batch '{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "'"$HOSTNAME"'.internal.mydomain.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{ "Value": "'"$PRIVATE_IP"'"}]
}
}]
}'
For complex environments, consider these approaches:
# Terraform configuration for Route53 Private Zone
resource "aws_route53_zone" "private" {
name = "internal.mydomain.com"
vpc {
vpc_id = aws_vpc.main.id
}
}
# DNS-based service discovery
resource "aws_service_discovery_private_dns_namespace" "example" {
name = "example.internal"
description = "Service discovery namespace"
vpc = aws_vpc.main.id
}
When moving from legacy solutions (like MaraDNS or /etc/hosts):
- Start with a parallel DNS system during transition
- Update application configurations to use DNS names
- Monitor DNS resolution metrics in CloudWatch
- Gradually phase out old DNS infrastructure
Essential commands for DNS management:
# Test DNS resolution
dig +short db-primary.internal.mydomain.com
# Check Route53 resolver endpoints
aws ec2 describe-route53-resolver-endpoints
# View DNS query logs
aws route53resolver list-resolver-query-log-configs