# AWS Route 53, AMI Lookup and EC2 Creation with Terraform (3/5)

> Tutorial and source code explaining how to manage AWS Route 53 DNS Service, create and register EC2 instances and find an AMI with Terraform.

- Source: https://www.itwonderlab.com/terraform-route-53-ami-lookup/
- Published: 2020-06-26
- Updated: 2026-10-05
- Author: Javier Ruiz Jiménez (https://www.javierruizjimenez.com/)
- Site: IT Wonder Lab (https://www.itwonderlab.com/)

---

## Route 53 and AMI Lookup

This is the continuation of a **Terraform and Ansible demo** to create a VPC in AWS with an EC2 instance connected to the MariaDB database running in RDS using a single Terraform plan.

> [!NOTE]
> This is one of the original IT Wonder Lab tutorials, written for Terraform 0.12 (2018-2020) with the AWS provider of that time. The ideas and the structure are still valid, but some arguments and versions have changed. For a current, step-by-step version see [AWS with Terraform: The Essential Guide](https://www.itwonderlab.com/aws-terraform-tutorial-terraform-basics/), and use OpenTofu or a recent Terraform with the commands `tofu` or `terraform`.

### Prerequisites and full source code are available

-   [Terraform Setup and VPC Subnet Creation (1/5)](https://www.itwonderlab.com/terraform-ansible-aws-howto/)
-   [VPC Subnet Routing and Internet Access (2/5)](https://www.itwonderlab.com/using-terraform-to-create-an-aws-vpc-with-an-ec2-instance-and-a-mariadb-rds-data-base-ii/)

### AWS DNS Server, Route 53 Service with Terraform

The Route 53 service provides DNS service with advanced options, see [AWS Route 53](https://www.itwonderlab.com/aws-route-53/) and [AWS Basic VPC Elements](https://www.itwonderlab.com/aws-naming-best-practices/).

Route 53 configuration is done in **terraform.tfvars**. The configuration shown is basic and does not include MX records for e-mail or any other service.

```json title="terraform.tfvars"
#------------------------
# ROUTE53
#------------------------

  #------------------------
  # PUBLIC - PRO
  #------------------------

  aws_route53_delegation_set_reference_name = "ditwl-r53-del"

  aws_route53_public = {
    name          = "demo.itwonderlab.com"
    comment       = "ditwl - Public DNS"
    tags_environment   = "pro"
  }
```

aws\_route53.tf creates an AWS Route 53 delegation set and the DNS hosted zone.

All domain zones hosted at route 53 get a random set of authoritative name servers, the registrar of the domain (AWS or other) has to be informed of the authoritative name servers that will be used to resolve addresses for the domain.

**Best Practice**: Don’t change the authoritative name servers. Having a fixed set of authoritative name servers that don’t change over time (as long as the set is not destroyed) is recommended.

Changing authoritative name servers can be problematic as it has to be planned ahead of time and to avoid service interruption the new and old name servers have to overlap during some hours or even days. Be aware that some caching DNS servers don’t honor configured TTL.

As long as the delegation set created in the module aws\_route53\_delegation\_set is not destroyed, we can recreate the DNS service from the module aws\_route53\_public.

```json title="aws_route53.tf"
  #------------------------
  # Public
  #------------------------

  module "aws_route53_delegation_set" {
    source  = "./modules/aws/route53/delegation_set"
    reference_name    = var.aws_route53_delegation_set_reference_name
  }

  module "aws_route53_public" {
    source  = "./modules/aws/route53/public_zone"
    name    = var.aws_route53_public["name"]
    delegation_set_id = module.aws_route53_delegation_set.id

    comment = var.aws_route53_public["comment"]

    #TAGS
    tags_environment = var.aws_route53_public["tags_environment"]
    
  }
```

In this example a single DNS Service is created, it will be used for the public and private lookup of services.

In a real production infrastructure, a private zone should be created to resolve names for the internal servers, for example, backends should not be registered in the public DNS as its clients are inside the VPC, not outside.

EC2 instances get the DNS to use as a DHCP option on startup, if a VPC has private and public zones, AWS will first query the DNS on the private zone.

### Creating an EC2 Instance with Terraform

For the creation and registration of the EC2 instance a module is used, the module takes care of registering the new machine in the DNS server as well.

The AWS Route 53 domain zone created before is used to create an A record for all the EC2 instances created in the demo.

**Best Practice**: Do a basic registration of EC2 instances in Route 53.  
It is recommended to do a “basic” registration inside the EC2 module that creates the virtual machines. This way we make sure that each AWS EC2 instance is registered in Route 53 and that it follows a pattern. It is possible to do the registration outside the EC2 instance module, but if we create many EC2 instances in different Terraform files and later decide to change the registration standard, then every file will need to be modified. Having a separate registration process is prone to errors.

Example of EC2 creation and registration in file **aws\_ec2\_pro\_wp.tf**

```json title="aws_ec2_pro_wp.tf"
  # Create WP instance
  module "aws_ec2_pro_wp" {
    source            = "./modules/aws/ec2/instance/add"
    name              = var.aws_ec2_pro_wp["name"]
    ...
    register_dns_private = true
    route53_private_zone_id = module.aws_route53_public.id

    register_dns_public = true
    route53_public_zone_id = module.aws_route53_public.id
    ...
}
```

### Finding the Right AMI with Terraform

AWS assigns an ID to each [AMI](https://www.itwonderlab.com/aws-ami/) that is uploaded to AWS, the assigned AMI ID differs in each region.

The aws\_ds\_aws\_ami.tf file uses a data provider to find the AMI ID based on filters for an Ubuntu 16.04 HVM image using EBS SSD, two filters are shown:

-   **name** is like “ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-\*”
-   **virtualization**\-type is HVM (commented out as it is redundant)

As we want to use the official image from Canonical, the owners’ property is used with 099720109477 the ID assigned by AWS to Canonical.

```json title="aws_ds_aws_ami.tf"
#--------------------------------------------------------
# Ubuntu AMI
#--------------------------------------------------------
# Use this data source to get the ID of the latests AMI for selected OS
# "${data.aws_ami.NAME.id}"

  # Ubuntu 16.04 HVM using EBS SSD
  # registered AMI for use in other resources.

  #----------------------
  # Ubuntu AMI 16.04 LTS
  #----------------------

  data "aws_ami" "ubuntu1604" {
      most_recent = true

      filter {
          name   = "name"
          values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"]
      }

      # filter {
      #     name   = "virtualization-type"
      #     values = ["hvm"]
      # }

      owners = ["099720109477"] # Canonical
  }
```

The AMI ID can be used when creating an EC2 instance to use the latest available AMI by requesting the ID from the data source “${data.aws\_ami.ubuntu1604.id}”.

Since the AMI ID changes as Canonical uploads new releases of the “Ubuntu 16.04 HVM image using EBS SSD”, the module accepts a list of properties in **ignore\_changes** variable that will not trigger an instance destroy/create for changes in the provided list, in our case a change in AMI will not recreate the instance.

```json title="aws_ec2_pro_wp.tf"
  # Create WP instance
  module "aws_ec2_pro_wp" {
    source            = "./modules/aws/ec2/instance/add"
    name              = var.aws_ec2_pro_wp["name"]
    ami                 = data.aws_ami.ubuntu1604.id
    instance_type     = var.aws_ec2_pro_wp["instance_type"]
    ...
    ignore_changes = ["ami"]
}
```

### Next Steps

-   [AWS Terraform Essential Guide, a comprehensive tutorial that guides you step-by-step through creating infrastructure in AWS using Terraform](https://www.itwonderlab.com/tag/aws-terraform-essential-guide/)
-   Terraform AWS Tutorials
    -   [Terraform Setup and AWS VPC Subnet Creation (1/5)](https://www.itwonderlab.com/terraform-ansible-aws-howto/)
    -   [VPC Subnet Routing and Internet Access with Terraform (2/5)](https://www.itwonderlab.com/using-terraform-to-create-an-aws-vpc-with-an-ec2-instance-and-a-mariadb-rds-data-base-ii/)
    -   [AWS Route 53, AMI Lookup and EC2 Creation with Terraform (3/5)](https://www.itwonderlab.com/terraform-route-53-ami-lookup/)
    -   [AWS RDS MariaDB Database and Resource Tags with Terraform (4/5)](https://www.itwonderlab.com/terraform-aws-mariadb-rds-database/)
    -   [EC2 Instances and Resource Security with Terraform (5/5)](https://www.itwonderlab.com/terraform-aws-ec2-security-rules/)
-   Ansible Tutorials
    -   [Using Ansible for Terraform Managed AWS Infrastructure](https://www.itwonderlab.com/terraform-aws-ansible/)
