AWS with Terraform Tutorial: AWS Route 53 (DNS) (14)

· Updated · 13 min read · Terraform & OpenTofu Tutorials

How to create Amazon Route 53 (DNS) with Terraform #

Using the Terraform aws_route53_delegation_set, aws_route53_zone, and aws_route53_record resource blocks to configure DNS in AWS.

Welcome to our tutorial series where we dive into cloud infrastructure deployment using Terraform or OpenTofu on AWS. In this series, the fundamentals are shown, guiding you through the process of minimizing resource usage and simplifying the deployment complexities associated with cloud infrastructure.

This comprehensive OpenTofu and Terraform tutorial guides you step-by-step through creating infrastructure in AWS using Terraform.

Terraform is an Infrastructure as Code (IaC) tool used to provision and manage infrastructure. It helps define and deploy resources across various cloud providers using code, making it easier to maintain and scale infrastructure.Terraform is an Infrastructure as Code (IaC) tool used to provision and manage infrastructure. It helps define and deploy resources across various cloud providers using code, making it easier to maintain and scale infrastructure.
Terraform
Basics
Terraform...
AWS is the world’s leading cloud platform, it is used by a wide range of organizations, from startups to large enterprises, to power their online businesses. AWS offers a wide range of services, including computing, storage, database, networking, analytics, machine learning, and artificial intelligence.AWS is the world’s leading cloud platform, it is used by a wide range of organizations, from startups to large enterprises, to power their online businesses. AWS offers a wide range of services, including computing, storage, database, networking, analytics, machine learning, and artificial intelligence.
AWS
Basics
AWS...
The Terraform official AWS provider acts as an abstraction layer that lets Terraform configurations written in HCL define AWS services and infrastructure using code (IaC). Internally Terraform and the AWS provider handle authentication, and make the necessary AWS API calls to query, create, modify, and destroy the resources.The Terraform official AWS provider acts as an abstraction layer that lets Terraform configurations written in HCL define AWS services and infrastructure using code (IaC). Internally Terraform and the AWS provider handle authentication, and make the necessary AWS API calls to query, create, modify, and destroy the resources.
Terraform
AWS Provider
Terraform...
How to Create, and Manage AWS VPCs with TerraformHow to Create, and Manage AWS VPCs with Terraform
AWS VPC
AWS VPC
How to configure and use the Terraform aws_subnet resource block to create and manage AWS Subnets inside a VPC.How to configure and use the Terraform aws_subnet resource block to create and manage AWS Subnets inside a VPC.
AWS Subnets
AWS Subnets
How to configure and use the Terraform aws_internet_gateway resource block to create and manage AWS Internet Gateway inside a VPC to enable Internet access to and from instances. How to configure and use the Terraform aws_internet_gateway resource block to create and manage AWS Internet Gateway inside a VPC to enable Internet access to and from instances.
AWS Internet
Gateway
AWS Internet...
How to configure and use the Terraform aws_nat_gateway and aws_eip resource blocks to create and manage AWS NAT Gateway and its corresponding Public IPs inside each availability zone to enable Internet access from instances in private subnets.How to configure and use the Terraform aws_nat_gateway and aws_eip resource blocks to create and manage AWS NAT Gateway and its corresponding Public IPs inside each availability zone to enable Internet access from instances in private subnets.
AWS NAT
Gateway
AWS NAT...
How to configure and use the Terraform aws_route_table, aws_route, and aws_main_route_table_association resource blocks to create and manage AWS Routing Tables.How to configure and use the Terraform aws_route_table, aws_route, and aws_main_route_table_association resource blocks to create and manage AWS Routing Tables.
AWS Routing
Tables
AWS Routing...
How to configure and use the Terraform aws_security_group and aws_security_group_rule resource blocks to create and manage AWS Security Groups and secure the infrastructure.How to configure and use the Terraform aws_security_group and aws_security_group_rule resource blocks to create and manage AWS Security Groups and secure the infrastructure.
AWS Security
Groups
AWS Security...
How to configure and use the Terraform aws_key_pair resource block to create and manage AWS Key Pairs for performing SSH Public Key Authentication into EC2 instances.How to configure and use the Terraform aws_key_pair resource block to create and manage AWS Key Pairs for performing SSH Public Key Authentication into EC2 instances.
AWS Key
Pairs
AWS Key...
How to configure and use the Terraform aws_ami data source block to find and use AWS AMIs as templates (root volume snapshot with operating system and applications) for EC2 instances.How to configure and use the Terraform aws_ami data source block to find and use AWS AMIs as templates (root volume snapshot with operating system and applications) for EC2 instances.
AWS AMIs
AWS AMIs
Using the Terraform aws_instance resource block to configure, launch, and secure EC2 instances.Using the Terraform aws_instance resource block to configure, launch, and secure EC2 instances.
AWS EC2
Instances
AWS EC2...
AWS RDS
AWS RDS
Using the Terraform aws_route53_delegation_set, aws_route53_zone, and aws_route53_record resource blocks to configure DNS in AWS. Using the Terraform aws_route53_delegation_set, aws_route53_zone, and aws_route53_record resource blocks to configure DNS in AWS.
AWS Route 53
(DNS)
AWS Route 53...
Amazon EC2 Auto Scaling groups keep the right number of instances running, replace failed ones and scale with the load.Amazon EC2 Auto Scaling groups keep the right number of instances running, replace failed ones and scale with the load.
AWS Auto
Scaling
AWS Auto...
Elastic Load Balancing distributes the traffic between healthy instances. The tutorial creates an Application Load Balancer with HTTPS.Elastic Load Balancing distributes the traffic between healthy instances. The tutorial creates an Application Load Balancer with HTTPS.
AWS Load
Balancers
AWS Load...
This tutorial shows how to create infrastructure in AWS using Terraform and configure the operating system and applications using Ansible.This tutorial shows how to create infrastructure in AWS using Terraform and configure the operating system and applications using Ansible.
Terraform,
AWS & Ansible
Terraform,...
Modules package resources behind variables and outputs so they can be reused. The tutorial refactors the network into a module.Modules package resources behind variables and outputs so they can be reused. The tutorial refactors the network into a module.
Terraform
Modules
Terraform...
A backend stores the Terraform state. The tutorial uses an encrypted, versioned S3 bucket with state locking.A backend stores the Terraform state. The tutorial uses an encrypted, versioned S3 bucket with state locking.
Terraform
Backends
Terraform...
fmt, validate, TFLint, Trivy, Checkov, terraform-docs, Infracost and pre-commit: check the code before it reaches AWS.fmt, validate, TFLint, Trivy, Checkov, terraform-docs, Infracost and pre-commit: check the code before it reaches AWS.
Terraform
Tools
Terraform...
Run checks, plans and approved applies automatically with GitHub Actions and OIDC, without access keys.Run checks, plans and approved applies automatically with GitHub Actions and OIDC, without access keys.
Terraform
CI/CD
Terraform...
Select a tutorial section 
Select a tutorial sectio...

Infrastructure as Code (IaC) helps maintain consistency, enables version control, enhances collaboration among teams, allows for easier replication of environments, streamlines the deployment and management of infrastructure boosting efficiency, and reducing errors in managing complex systems.

Prerequisites #

Read the previous sections of the tutorial, listed in the series index at the end of this page.

AWS Route 53 #

Amazon Route 53 is a scalable and highly available Domain Name System (DNS) web service provided by Amazon Web Services (AWS). It is designed to route end-user requests to globally distributed endpoints, such as web applications or resources, and effectively connects user requests to the corresponding AWS resources.

AWS offers domain registration and also DNS Service for domains registered outside AWS. For simplicity, we will use Amazon Route 53 as a DNS Server for a subdomain of an already registered domain name.

The tutorial defined two zones, a public zone to be used for public instance ditwl-ec-front-end-001 registration, and a private zone that will be used for internal hostname resolution.

DNS Diagrams #

The DNS diagram shows the different DNS Zones and the registration of the hosts.

AWS Terraform Essentials Route 53 14

Definition of Route 53 DNS Zones and Records with Terraform #

Previous sections of this AWS with Terraform guide have covered basic information about Terraform and AWS and have configured and used the AWS Terraform provider to create a VPC, four subnets, one Internet Gateway, two NAT Gateways, three Routing Tables, Security Groups, and a Private Key.

Add the following blocks to the terraform-aws-tutorial.tf created in previous sections.

Route 53 Delegation Set: ditwl-r53ds-001 #

A Route 53 delegation set is a set of four authoritative name servers created for a hosted zone in Amazon Route 53. These name servers are assigned to a hosted zone and are responsible for answering DNS queries for that zone. Delegation sets are used to delegate authority for a domain’s DNS to Route 53, allowing Route 53 to manage DNS records and respond to queries on behalf of that domain. This delegation enables efficient management and distribution of DNS information for the domain across multiple name servers.

The assigned four authoritative name servers will be used to delegate the subdomain to Amazon Route 53. Delegation sets are mostly used for public zones, usually created once and re-used across Terraform plans to avoid having to update the delegation to the four authoritative name servers in other name servers or registrars.

Route 53 Delegation Sets are created using terraform resource block aws_route53_delegation_set.

# Route53 Delegation Set
resource "aws_route53_delegation_set" "ditwl-r53ds-001" {
  reference_name    = "ditwl-r53ds-001"
}

Route 53 Zones: ditwl-r53-public and ditwl-r53-private #

Two DNS Zones are created:

  • ditwl-r53-public: a public DNS zone for the subdomain “demo.itwonderlab.com” that uses the delegation set ditwl-r53ds-001.
  • ditwl-r53-private: a private DNS zone for the subdomain “demo.itwonderlab.local” assigned to the VPC ditlw-vpc. (VPC-assigned zones are internal and act as private DNS zones and can only be queried inside the VPC).

In AWS DNS Resolver, private DNS queries take precedence over public DNS queries. This means that if a DNS query is made for a domain name that exists in the private hosted zone associated with the VPC, the resolver will resolve the query using the private DNS records. If the domain name doesn’t exist in the private hosted zone, only then will the resolver look for public DNS records. This approach helps ensure that private resources within a VPC are resolved using the appropriate private DNS configuration before attempting to resolve public DNS records.

DNS Zones are created using the Terraform resource block aws_route53_zone.

# Route53 Public Zone (*.demo.itwonderlab.com)
resource "aws_route53_zone" "ditwl-r53-public" {
  name    = "demo.itwonderlab.com"
  delegation_set_id = aws_route53_delegation_set.ditwl-r53ds-001.id
  tags = {
    Name = "ditwl-r53-public"
  }  
}

# Route53 Private Zone (*.demo.itwonderlab.local)
resource "aws_route53_zone" "ditwl-r53-private" {
  name    = "demo.itwonderlab.local"
  vpc {
    vpc_id = aws_vpc.ditlw-vpc.id
  }
  tags = {
    Name = "ditwl-r53-private"
  }  
}

DNS Records: ditwl-r53-public-front-end-001, ditwl-r53-private-front-end-001, ditwl-r53-private-back-end-123 and ditwl-r53-private-rds-001 #

A DNS record is created for each instance using its private name and, for the instances in public subnets, its public name.

Public records created in the Public zone ditwl-r53-public serving the demo.itwonderlab.com subdomain:

  • ditwl-r53-public-front-end-001: Creates an Address record (IN A) using the Public Name assigned to the instance (in a Tag) and associates it with the public IPv4 address assigned by AWS. The record is created in the Public zone ditwl-r53-public serving the demo.itwonderlab.com subdomain.

Private records created in the Private zone ditwl-r53-private serving the demo.itwonderlab.local subdomain:

  • ditwl-r53-private-front-end-001: Creates an Address record (IN A) using the Private Name assigned to the instance (in a Tag) and associates it with the private IPv4 address assigned by AWS.
  • ditwl-r53-private-back-end-123: Creates an Address record (IN A) using the Private Name assigned to the instance (in a Tag) and associates it with the private IPv4 address assigned by AWS.
  • ditwl-r53-private-rds-001: Creates a CNAME or alias record (IN CNAME) using the Database Instance name and associates it with the private FQDN assigned by AWS. AWS will update the IP assigned to the private FQDN when the standby replica becomes active.

DNS Records are created using the Terraform resource block aws_route53_record.

# Public A DNS Record: Front-end server (ditwl-ec-front-end-001)
resource "aws_route53_record" "ditwl-r53-public-front-end-001" {
  zone_id = aws_route53_zone.ditwl-r53-public.id
  name    = aws_instance.ditwl-ec-front-end-001.tags["public_name"]
  type    = "A"
  ttl     = "300"
  records = [aws_instance.ditwl-ec-front-end-001.public_ip]
}

# Private A DNS Record: Front-end server (ditwl-ec-front-end-001)
resource "aws_route53_record" "ditwl-r53-private-front-end-001" {
  zone_id = aws_route53_zone.ditwl-r53-private.id
  name    = aws_instance.ditwl-ec-front-end-001.tags["private_name"]
  type    = "A"
  ttl     = "300"
  records = [aws_instance.ditwl-ec-front-end-001.private_ip]
}

# Private A DNS Record: Back-end server (ditwl-ec-back-end-123) 
resource "aws_route53_record" "ditwl-r53-private-back-end-123" {
  zone_id = aws_route53_zone.ditwl-r53-private.id
  name    = aws_instance.ditwl-ec-back-end-123.tags["private_name"]
  type    = "A"
  ttl     = "300"
  records = [aws_instance.ditwl-ec-back-end-123.private_ip]
}

# Private A DNS Record: DB Server (ditwl-rds-001)
resource "aws_route53_record" "ditwl-r53-private-rds-001" {
  zone_id = aws_route53_zone.ditwl-r53-private.id
  name    = aws_db_instance.ditwl-rds-001.identifier
  type    = "CNAME"
  ttl     = "300"
  records = [aws_db_instance.ditwl-rds-001.address]
}

Run the Terraform Plan #

Open a command line shell in the directory where the file terraform-aws-tutorial.tf is located, and run the Terraform or OpenTofu plan and apply commands.

Plan using OpenTofu #

Run tofu plan to generate and review the execution plan. Check each line and value to make sure that it corresponds to the desired change.

Terraform will refresh the state by comparing it with the Cloud resources and produce a plan for the resources that need to be created, updated, or destroyed.

In the previous section of the tutorial, some resources were commented out to reduce the infrastructure cost during development. The DNS zones have dependencies with the EC2 instances and the RDS, please uncomment all resources to proceed with the Terraform plan.

Run the Terraform plan:

$ tofu plan
data.aws_ami.ubuntu-23-04-arm64-minimal: Reading...
...
aws_db_instance.ditwl-rds-001: Refreshing state... [id=db-ACRNKG6LHOJHW34OBW3YBTGIVU]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

OpenTofu will perform the following actions:

  # aws_route53_delegation_set.ditwl-r53ds-001 will be created
  + resource "aws_route53_delegation_set" "ditwl-r53ds-001" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + name_servers   = (known after apply)
      + reference_name = "ditwl-r53ds-001"
    }

  # aws_route53_record.ditwl-r53-private-back-end-123 will be created
  + resource "aws_route53_record" "ditwl-r53-private-back-end-123" {
      + name            = "ditwl-ec-back-end-123"
      + records         = [
          + "172.21.2.106",
        ]
      + ttl             = 300
      + type            = "A"
      ...
    }

  # aws_route53_record.ditwl-r53-private-front-end-001 will be created
  + resource "aws_route53_record" "ditwl-r53-private-front-end-001" {
      + name            = "ditwl-ec-front-end-001"
      + records         = [
          + "172.21.0.174",
        ]
      + ttl             = 300
      + type            = "A"
      ...
    }

  # aws_route53_record.ditwl-r53-private-rds-001 will be created
  + resource "aws_route53_record" "ditwl-r53-private-rds-001" {
      + name            = "ditwl-rds-001"
      + records         = [
          + "ditwl-rds-001.crcp5q8td9pz.us-east-1.rds.amazonaws.com",
        ]
      + ttl             = 300
      + type            = "CNAME"
    }

  # aws_route53_record.ditwl-r53-public-front-end-001 will be created
  + resource "aws_route53_record" "ditwl-r53-public-front-end-001" {
      + name            = "www"
      + records         = [
          + "44.199.183.221",
        ]
      + ttl             = 300
      + type            = "A"
    }

  # aws_route53_zone.ditwl-r53-private will be created
  + resource "aws_route53_zone" "ditwl-r53-private" {
      + name                = "demo.itwonderlab.local"
      + tags_all            = {
          + "Name"        = "ditwl-r53-private"
          + "cost_center" = "marketing-department"
          + "environment" = "pro"
          + "owner"       = "IT Wonder Lab"
        }
    ...
    }

  # aws_route53_zone.ditwl-r53-public will be created
  + resource "aws_route53_zone" "ditwl-r53-public" {
      + name                = "demo.itwonderlab.com"
      + tags_all            = {
          + "Name"        = "ditwl-r53-public"
          + "cost_center" = "marketing-department"
          + "environment" = "pro"
          + "owner"       = "IT Wonder Lab"
        }
     ...
    }

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

Apply the changes using OpenTofu #

Run tofu apply to generate and apply the execution plan. OpenTofu will generate a new plan and ask for confirmation before applying the changes. Review the changes and answer yes or no to apply the changes in AWS.

$ tofu apply
aws_key_pair.ditwl-kp-config-user: Refreshing state... [id=ditwl-kp-config-user]
aws_kms_key.ditwl-kms-rds-001-key: Refreshing state... [id=a9925f60-c871-41bd-ba3f-e5a4066c58da]
aws_vpc.ditlw-vpc: Refreshing state... [id=vpc-02b934f2426acc5f1]
data.aws_ami.ubuntu-23-04-arm64-minimal: Reading...
data.aws_ami.ubuntu-23-04-arm64-minimal: Read complete after 1s [id=ami-01eba98c26f317c58]
aws_kms_alias.ditwl-kmsalias-rds-001-key: Refreshing state... [id=alias/ditwl-kms-rds-001-key]
aws_security_group.ditwl-sg-base-ec2: Refreshing state... [id=sg-0e84b8db62b8e0d09]
aws_internet_gateway.ditwl-ig: Refreshing state... [id=igw-0d045eed1d3e2a2b8]
aws_security_group.ditwl-sg-back-end: Refreshing state... [id=sg-04cffe5ba3a4a91ad]
aws_subnet.ditwl-sn-za-pro-pub-00: Refreshing state... [id=subnet-0da274b2ae72deb21]
aws_security_group.ditwl-sg-front-end: Refreshing state... [id=sg-0556ce9da95889d16]
aws_security_group.ditwl-sg-rds-001: Refreshing state... [id=sg-0a2e113b0ab14b423]
aws_route_table.ditwl-rt-priv-zb: Refreshing state... [id=rtb-025ac07e1c24d1e7c]
aws_subnet.ditwl-sn-za-pro-pri-02: Refreshing state... [id=subnet-06185d2fababe83a2]
aws_subnet.ditwl-sn-zb-pro-pub-04: Refreshing state... [id=subnet-0b55d911b7f66e6a6]
aws_subnet.ditwl-sn-zb-pro-pri-06: Refreshing state... [id=subnet-033ae71558502ef32]
aws_route_table.ditwl-rt-priv-za: Refreshing state... [id=rtb-0d5a5f00f57bb8010]
aws_security_group_rule.ditwl-sr-internet-to-ec2-ssh: Refreshing state... [id=sgrule-1652936524]
aws_security_group_rule.ditwl-sr-all-outbund: Refreshing state... [id=sgrule-4250796018]
aws_security_group_rule.ditwl-sr-internet-to-ec2-icmp: Refreshing state... [id=sgrule-4113347279]
aws_security_group_rule.ditwl-sr-back-end-to-db: Refreshing state... [id=sgrule-3209111098]
aws_security_group_rule.ditwl-sr-front-end-to-api: Refreshing state... [id=sgrule-85780268]
aws_security_group_rule.ditwl-sr-internet-to-front-end-http: Refreshing state... [id=sgrule-3488157431]
aws_instance.ditwl-ec-front-end-001: Refreshing state... [id=i-027a11618f6f2ac3e]
aws_route_table.ditwl-rt-pub-main: Refreshing state... [id=rtb-0832c63d2f3fa55b9]
aws_instance.ditwl-ec-back-end-123: Refreshing state... [id=i-079cc3dd35be83128]
aws_route_table_association.ditwl-rta-zb-pro-pri-06: Refreshing state... [id=rtbassoc-028d21a6ba2556f31]
aws_db_subnet_group.ditwl-dbsng-zab-pro-pri: Refreshing state... [id=ditwl-dbsng-zab-pro-pri]
aws_route_table_association.ditwl-rta-za-pro-pri-02: Refreshing state... [id=rtbassoc-047705296475cde67]
aws_main_route_table_association.ditwl-rta-default: Refreshing state... [id=rtbassoc-03cfb8d8b23d3b33a]
aws_db_instance.ditwl-rds-001: Refreshing state... [id=db-ACRNKG6LHOJHW34OBW3YBTGIVU]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

OpenTofu will perform the following actions:

  # aws_route53_delegation_set.ditwl-r53ds-001 will be created
  + resource "aws_route53_delegation_set" "ditwl-r53ds-001" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + name_servers   = (known after apply)
      + reference_name = "ditwl-r53ds-001"
    }

  # aws_route53_record.ditwl-r53-private-back-end-123 will be created
  + resource "aws_route53_record" "ditwl-r53-private-back-end-123" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "ditwl-ec-back-end-123"
      + records         = [
          + "172.21.2.106",
        ]
      + ttl             = 300
      + type            = "A"
      + zone_id         = (known after apply)
    }

  # aws_route53_record.ditwl-r53-private-front-end-001 will be created
  + resource "aws_route53_record" "ditwl-r53-private-front-end-001" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "ditwl-ec-front-end-001"
      + records         = [
          + "172.21.0.174",
        ]
      + ttl             = 300
      + type            = "A"
      + zone_id         = (known after apply)
    }

  # aws_route53_record.ditwl-r53-private-rds-001 will be created
  + resource "aws_route53_record" "ditwl-r53-private-rds-001" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "ditwl-rds-001"
      + records         = [
          + "ditwl-rds-001.crcp5q8td9pz.us-east-1.rds.amazonaws.com",
        ]
      + ttl             = 300
      + type            = "CNAME"
      + zone_id         = (known after apply)
    }

  # aws_route53_record.ditwl-r53-public-front-end-001 will be created
  + resource "aws_route53_record" "ditwl-r53-public-front-end-001" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "www"
      + records         = [
          + "44.199.183.221",
        ]
      + ttl             = 300
      + type            = "A"
      + zone_id         = (known after apply)
    }

  # aws_route53_zone.ditwl-r53-private will be created
  + resource "aws_route53_zone" "ditwl-r53-private" {
      + arn                 = (known after apply)
      + comment             = "Managed by Terraform"
      + force_destroy       = false
      + id                  = (known after apply)
      + name                = "demo.itwonderlab.local"
      + name_servers        = (known after apply)
      + primary_name_server = (known after apply)
      + tags                = {
          + "Name" = "ditwl-r53-private"
        }
      + tags_all            = {
          + "Name"        = "ditwl-r53-private"
          + "cost_center" = "marketing-department"
          + "environment" = "pro"
          + "owner"       = "IT Wonder Lab"
        }
      + zone_id             = (known after apply)

      + vpc {
          + vpc_id     = "vpc-02b934f2426acc5f1"
          + vpc_region = (known after apply)
        }
    }

  # aws_route53_zone.ditwl-r53-public will be created
  + resource "aws_route53_zone" "ditwl-r53-public" {
...
    }

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

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

  Enter a value: yes

aws_route53_delegation_set.ditwl-r53ds-001: Creating...
aws_route53_zone.ditwl-r53-private: Creating...
aws_route53_delegation_set.ditwl-r53ds-001: Creation complete after 2s [id=N02856711FM6ZWNXWIFGS]
aws_route53_zone.ditwl-r53-public: Creating...
...
aws_route53_zone.ditwl-r53-public: Creation complete after 58s [id=Z059517510UUCSCEZSY0N]
aws_route53_record.ditwl-r53-public-front-end-001: Creating...
aws_route53_zone.ditwl-r53-private: Creation complete after 1m3s [id=Z1002722OPC6CMSA7FBT]
aws_route53_record.ditwl-r53-private-back-end-123: Creating...
aws_route53_record.ditwl-r53-private-rds-001: Creating...
aws_route53_record.ditwl-r53-private-front-end-001: Creating...
...
aws_route53_record.ditwl-r53-private-back-end-123: Creation complete after 12s [id=Z1002722OPC6CMSA7FBT_ditwl-ec-back-end-123_A]
...
aws_route53_record.ditwl-r53-private-front-end-001: Creation complete after 29s [id=Z1002722OPC6CMSA7FBT_ditwl-ec-front-end-001_A]
aws_route53_record.ditwl-r53-private-rds-001: Creation complete after 29s [id=Z1002722OPC6CMSA7FBT_ditwl-rds-001_CNAME]
...
aws_route53_record.ditwl-r53-public-front-end-001: Creation complete after 51s [id=Z059517510UUCSCEZSY0N_www_A]

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

Review the result, it should be 7 (resource) added, 0 changed, and 0 destroyed.

You can check that the DNS Zone and the Records have been created:

Navigate to AWS Console: Route 53: Hosted zones

The Console shows two DNS Zones, the selected public zone demo.itwonderlab.com has four authoritative name servers assigned:

Route 53 Console hosted zones

The Console shows the DNS Records for the private zone demo.itwonderlab.local, the record ditwl-rds-001.demo.itwonderlab.local is a CNAME (alias) for the AWS assigned FQDN for the RDS database instance access point ditwl-rds-001.crcp5q8td9pz.us-east-1.rds.amazonaws.com:

Route 53 private zone

Using DNS Records inside AWS #

Instances should use DNS records to reference other instances and databases. AWS will resolve the records to its IPs.

  • ditwl-ec-front-end-001: ditwl-ec-front-end-001.demo.itwonderlab.local
  • ditwl-ec-back-end-123: ditwl-ec-back-end-123.demo.itwonderlab.local
  • ditwl-rds-001: ditwl-rds-001.demo.itwonderlab.local CNAME ditwl-rds-001.crcp5q8td9pz.us-east-1.rds.amazonaws.com

Destroy the infrastructure using OpenTofu #

AWS will bill the time that the infrastructure is running. To reduce the cost during Terraform development or when the infrastructure is not needed anymore terraform destroy will be used.

Terraform destroy terminates all the resources created by the plan.

Run tofu destroy to generate and apply the destruction plan. OpenTofu will generate a new plan with the resources to terminate and ask for confirmation before applying the changes.

All data will be lost but you will be able to recreate the infrastructure when needed using tofu apply.

$ tofu destroy
....
aws_db_instance.ditwl-rds-001: Still destroying... [id=db-ACRNKG6LHOJHW34OBW3YBTGIVU, 4m10s elapsed]
aws_db_instance.ditwl-rds-001: Destruction complete after 4m12s
aws_db_subnet_group.ditwl-dbsng-zab-pro-pri: Destroying... [id=ditwl-dbsng-zab-pro-pri]
aws_kms_key.ditwl-kms-rds-001-key: Destroying... [id=a9925f60-c871-41bd-ba3f-e5a4066c58da]
aws_db_subnet_group.ditwl-dbsng-zab-pro-pri: Destruction complete after 1s
aws_subnet.ditwl-sn-za-pro-pri-02: Destroying... [id=subnet-06185d2fababe83a2]
aws_subnet.ditwl-sn-zb-pro-pri-06: Destroying... [id=subnet-033ae71558502ef32]
aws_kms_key.ditwl-kms-rds-001-key: Destruction complete after 1s
aws_subnet.ditwl-sn-zb-pro-pri-06: Destruction complete after 1s
aws_subnet.ditwl-sn-za-pro-pri-02: Destruction complete after 2s
aws_vpc.ditlw-vpc: Destroying... [id=vpc-02b934f2426acc5f1]
aws_vpc.ditlw-vpc: Destruction complete after 2s

Destroy complete! Resources: 36 destroyed.

AWS Route 53 Cost #

AWS charges a monthly fee for each hosted zone plus a fee per million queries to the zone (queries to alias records that point to AWS resources are free). See Amazon Route 53 pricing for details.

Common Questions About AWS Route 53 #

Can Terraform manage Route 53 health checks and failover configurations? #

Yes, Terraform supports managing Route 53 health checks and failover configurations using resources aws_route53_health_check and aws_route53_record with failover settings. Define health check settings and associate them with DNS records to enable failover functionality.

How do I update existing DNS records with Terraform without causing downtime? #

Terraform applies changes incrementally, so updating existing DNS records typically doesn’t cause downtime. When you make changes to your Terraform configuration and apply them, Terraform will update only the necessary resources without interrupting existing services. For complex migrations review and plan zone and record TTLs.

Should private records be stored in public Route 53 zones? #

Private records contain sensitive information related to internal resources within a network, and exposing them in a public DNS zone could pose security risks. Private hosted zones are specifically designed to manage DNS records for internal resources within a Virtual Private Cloud (VPC) or on-premises network connected to AWS using AWS Direct Connect or VPN. These private hosted zones ensure that DNS queries for internal resources are resolved within the private network and are not exposed to the public internet.

How can I use Terraform to configure Route 53 for domain registration and DNS hosting? #

Domain registration is a complex process involving different entities, requiring payment and other steps that are better done outside Terraform.

Next Steps #

Continue with AWS Auto Scaling, or see the full series index.

#AWS #AWS ROUTE 53 #AWS Terraform Tutorial #OpenTofu #Terraform