Reputation: 10506
With AWS, how can I get deterministic name server addresses between terraform apply/destroy executions?
At the moment, my name servers are something like this:
ns-XXX.awsdns-YY.com.
ns-XXX.awsdns-YY.org.
ns-XXX.awsdns-YY.net.
ns-XXX.awsdns-YY.co.uk.
And each time I run apply/destroy, the values of XXX
and YY
change.
So if I have a domain registered with godaddy/namecheap/other, then these also need to be updated, which takes time to propagate.
So I am wondering is there a way to influence what XXX/YY
values are, so that they may persist between sessions?
For example, I tried this, and although it set the name servers as I had desired, unfortunately it wouldn't resolve.
resource "aws_route53_record" "ns" {
allow_overwrite = true
name = "my_fixed_ns"
ttl = 30
type = "NS"
zone_id = aws_route53_zone.zone.zone_id
records = [
"ns1.amazon.com",
"ns2.amazon.org",
"ns3.amazon.net",
"ns4.amazon.co.uk"
]
}
Upvotes: 2
Views: 318
Reputation: 56887
You can use reusable delegation sets to make Route53 zones use the same name servers for each zone whether that's multiple concurrent zones or rebuilding the zone over and over:
A set of four authoritative name servers that you can use with more than one hosted zone. By default, Route 53 assigns a random selection of name servers to each new hosted zone. To make it easier to migrate DNS service to Route 53 for a large number of domains, you can create a reusable delegation set and then associate the reusable delegation set with new hosted zones. (You can't change the name servers that are associated with an existing hosted zone.)
In Terraform these are created with the aws_route53_delegation_set
resource and the example given in the docs looks like this:
resource "aws_route53_delegation_set" "main" {
reference_name = "DynDNS"
}
resource "aws_route53_zone" "primary" {
name = "hashicorp.com"
delegation_set_id = aws_route53_delegation_set.main.id
}
resource "aws_route53_zone" "secondary" {
name = "terraform.io"
delegation_set_id = aws_route53_delegation_set.main.id
}
If you're destroying the zones and rebuilding them and wanting the same name servers then you'll need to make sure not to destroy the delegation set at the same time.
You could do this by running terraform destroy -target aws_route53_zone.example
if you wanted to select just the zone.
Alternatively you could create the delegation set in one directory and then the Route53 zones (plus anything else) in a separate directory and just not destroy the delegation set resource directory. So you'd have something like this:
.
├── delegation-set
│ └── delegation-set.tf
└── route53-zone
└── route53-zone.tf
### delegation-set.tf
resource "aws_route53_delegation_set" "example" {
reference_name = "Example"
}
output "delegation_set_id" {
value = aws_route53_delegation_set.example.id
}
### route53-zone.tf
data "aws_route53_delegation_set" "example" {
id = "INSERT_DELEGATION_SET_ID_HERE"
}
resource "aws_route53_zone" "example" {
name = "example.com"
delegation_set_id = data.aws_route53_delegation_set.example.id
}
Unfortunately, as you can see in the above example, the aws_route53_delegation_set
data source only takes the ID of a delegation set rather than be able to give it a caller reference so you'd need to hardcode the reference ID generated and outputted by running terraform apply delegation-set
.
Alternatively you could use the terraform_remote_state
data source instead of the aws_route53_delegation_set
data source:
### route53-zone.tf
data "terraform_remote_state" "delegation_set" {
backend = "remote"
config = {
organization = "example"
workspaces = {
name = "delegation-set"
}
}
}
resource "aws_route53_zone" "example" {
name = "example.com"
delegation_set_id = data.terraform_remote_state.delegation_set.id
}
The above configuration would need adapting for however you are storing your state.
Upvotes: 3