A few weeks ago, I worked on a use case to create an Amazon EC2 instance from an Amazon Machine Image 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 Amazon EC2 instance. The approach, although, was the same, (i) use a data source to identify the AMI uniquely, and (ii) create an Amazon 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 the 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 the 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 Amazon 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?
3 thoughts on “Create an Amazon EC2 instance from an Amazon Machine Image (AMI) using Terraform”
how to provide 3 ami in terraform for 3 instances. I got interview questions
LikeLiked by 1 person
Hi Ram. Thanks for asking the question. You can create three data sources for the ami and create `aws_instance` out of those ami. You can read about data sources at https://developer.hashicorp.com/terraform/language/data-sources. Let me know if that helps or if you have any questions.