Create EC2 instance from an AWS AMI using Terraform

A few weeks ago, I worked on a use case to create an AWS EC2 instance from an AWS AMI using Terraform. I had worked on that concept without automation, and my approach was to (i) identify an AMI and (ii) create an instance out of that AMI. I’ll cover the network bits to host the VM in a separate note.

To manually create an EC2 using the AWS console, (a) navigate to EC2 (under Services) -> Images -> AMIs, (b) set the filter to Pubic images (default is Owned by me ), (c) add a filter for the AMI Name: <enter image name> or <enter some keyword that uniquely identifies the image> for e.g. “AMI Name: Windows”. A list of all images that match the AMI Name criteria is displayed with the AMI ID. The other option is to select the AMI from the EC2 dashboard -> Instances – Click on “Launch Instances” and then select the AMI as part of creating a virtual machine. Under either option, I could access the AMI and use it to launch an EC2 instance.

However, I was required to use Terraform to create an EC2 instance. The approach, although, was the same, (i) use a data source to identify the AMI uniquely, and (ii) create an AWS EC2 instance using the AMI.
Using the “data source,” the idea was to filter out a particular AMI. But how would I know what value to fill under the name filter such that the result is only one AMI?
Enter AWS CLI.
My objective was to access the name of an AWS AMI. The command is aws ec2 describe-images. More info at AWS-Docs.
I knew my requirement was a Windows Server, and hence I started with the following command: aws ec2 describe-images --owners amazon --region us-east-2 --filters "Name=name,Values=*Windows*" --query 'Images[*].[Name]' --output text
The output was a long list of AWS AMI image names. But that gave me some leads to work on. I saw the pattern of the name was Windows_Server-YYYY in the list and so at the next run, I updated the command to: aws ec2 describe-images --owners amazon --region us-east-2 --filters "Name=name,Values=*Windows_Server-2019*" --query 'Images[*].[Name]' --output text
The output was shorter than that of the previous run. And hence, with each iteration of running the command, I updated the Name value such that the output was down to multiple versions of the same instance; the last version of the command was: aws ec2 describe-images --owners amazon --region us-east-2 --filters "Name=name,Values=Windows_Server-2019-English-Full-Base-2021*" --query 'Images[*].[Name]' --output text
Note: I could have gone specific on the “values” and removed the “*” from the name, but since I was using the most_recent = true flag in the data "aws_ami" "windows-ami" source block, it was fine. The AWS CLI helped me identify the value that would go into the name filter. With that information, the data source block looked as below.
And the EC2 instance block was as below—nothing fancy there. I was using the AMI that I selected from the data source above.
I hope you found this helpful note. Are you aware of an efficient way to identify the AMI name without going through the AWS CLI? Would you mind sharing that in the comments, please?

One thought on “Create EC2 instance from an AWS AMI using Terraform

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s