Terraform Route53 And DNS Fun

3 minute read     Updated:

Adam Gordon Bell %
Adam Gordon Bell

We’re Earthly. We make building software simpler and therefore faster using containerization. Managing DNS records with Terraform? Earthly can complement your automation efforts. Check it out.

In my previous article about terraform I moved my lambda and all related infrastructure to Terraform. I even tested things by destroying everything and then recreating it.

Imagine my surprise then, when several days later I got this.

$ curl https://earthly-tools.com/text-mode
curl: (6) Could not resolve host: earthly-tools.com

In this post, I’ll show you how I fixed this and got my DNS records from AWS’s Route53 into terraform.

The Problem

So, I had a working lambda that was getting all requests to earthly-tools.com, but then it stopped working. What was going on?

First, lets check and see what dig says:

$ dig earthly-tools.com
;; QUESTION SECTION:
;earthly-tools.com.        IN    A

Dig is missing the IPs for the A record of my domain name. Here is what a DIG response should look like:

$ dig google.com 
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             210     IN      A       172.217.1.14

I can also use dnschecker.org to validate that something is wrong:

This is strange, because if I look in AWS, under Route53, I can see the A record is setup to point to my HTTP API.

Route 53 A Record

But here lies the problem. The A value of DNS record points to an API Gateway domain name, but not the one I have setup in AWS.

API Gateway doesn’t match DNS

The problem is when I tore down my API gateway, I left a dangling DNS record pointing to a non-existent API Gateway endpoint. The surprising thing is it kept working for a while. Both the new value and the old must resolve to the same IP, and with all the caching that happens in DNS things just kept working for a while.

So the solution is simple, I need to pull my DNS records into Terraform, so that when I make changes to my HTTP API my DNS records also get updated.

Terraform Import

First thing I do is define my zone resource:

resource "aws_route53_zone" "primary" {
 name = "earthly-tools.com" 
}

The I import the existing zone:

$ terraform import aws_route53_zone.primary Z0907636HDO135DJDT7G

With the zone in place, I can create the resource for my A record:

resource "aws_route53_record" "A" {
    name    = "earthly-tools.com"
    type    = "A"
    zone_id = aws_route53_zone.primary.id
}

And then I import it.


$ terraform import aws_route53_record.A Z0907636HDO135DJDT7G_earthly-tools.com_A

Then, I need to configure it to point to the domain name and zone of my API gateway. To do that I add in an alias property.

 resource "aws_route53_record" "A" {
     name    = "earthly-tools.com"
     type    = "A"
     zone_id = aws_route53_zone.primary.id
 
+    alias {
+        evaluate_target_health = true
+        name                   = aws_api_gateway_domain_name.earthly-tools-com.regional_domain_name
+        zone_id                = aws_api_gateway_domain_name.earthly-tools-com.regional_zone_id
+    }
 }

And with that in place, I can just apply everything.

$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_route53_record.A will be created
  + resource "aws_route53_record" "A" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "earthly-tools.com"
      + type            = "A"
      + zone_id         = "Z0907636HDO135DJDT7G"

      + alias {
          + evaluate_target_health = true
          + name                   = "d-i2cdn11lkf.execute-api.us-east-1.amazonaws.com"
          + zone_id                = "Z1UJRXOUMOOFQ8"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_route53_record.A: Creating...
aws_route53_record.A: Still creating... [10s elapsed]
aws_route53_record.A: Still creating... [20s elapsed]
aws_route53_record.A: Still creating... [30s elapsed]
aws_route53_record.A: Creation complete after 38s [id=Z0907636HDO135DJDT7G_earthly-tools.com_A]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

And now everything is working.

$ curl https://earthly-tools.com/text-mode
Earthly.dev Presents:                                                                                              

  _____                 _       
 |_   _|   ___  __  __ | |_     
   | |    / _ \ \ \/ / | __|    
   | |   |  __/  >  <  | |_     
   |_|    \___| /_/\_\  \__|    
                                
  __  __               _        
 |  \/  |   ___     __| |   ___ 
 | |\/| |  / _ \   / _` |  / _ \
 | |  | | | (_) | | (_| | |  __/
 |_|  |_|  \___/   \__,_|  \___|

The code is on GitHub

Earthly makes CI/CD super simple
Fast, repeatable CI/CD with an instantly familiar syntax – like Dockerfile and Makefile had a baby.

Learn More

Adam Gordon Bell %

Spreading the word about Earthly. Host of CoRecursive podcast. Physical Embodiment of Cunningham’s Law.
@adamgordonbell
✉Email Adam✉

Published:

Get notified about new articles!
We won't send you spam. Unsubscribe at any time.