Get latest AMI ID for AWS instance

14,077

Solution 1

A little-known recent feature is the ability to Query for the latest Amazon Linux AMI IDs using AWS Systems Manager Parameter Store | AWS Compute Blog.

The namespace is made up of two parts:

  • Parameter Store Prefix (tree): /aws/service/ami-amazon-linux-latest/
  • AMI name alias: (example) amzn-ami-hvm-x86_64-gp2

These:

aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn*" --query 'sort_by(Images, &CreationDate)[].Name'

Get-EC2ImageByName -Name amzn* | Sort-Object CreationDate | Select-Object Name

can be changed into:

aws ssm get-parameters --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --region us-east-1 

Get-SSMParameter -Name /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 -region us-east-1

Plus, it can be used in a CloudFormation template:

# Use public Systems Manager Parameter
 Parameters :
 LatestAmiId :
 Type : 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
 Default: ‘/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2’

Resources :
 Instance :
 Type : 'AWS::EC2::Instance'
 Properties :
 ImageId : !Ref LatestAmiId

Solution 2

AWS CLI

A way to filter the output and get the only the required attributes is using a combination of filters,queries on the aws describe-images command as below:

aws ec2 describe-images \ 
--owners 'amazon' \
--filters 'Name=description,Values=Amazon Linux AMI*' \
--query 'sort_by(Images, &CreationDate)[-1].[ImageId]' \
--output 'text'

Command Explanation:

  • owners : For images by amazon, use 'amazon'. To query your own images, use 'self'
  • filters : You can use a list of filters to filter out the instance that you are looking for. I prefer description because I found the name filter missing for some images. Values support wildcards. More on filters
  • query : Query can be used to filter only what is required from the output. You can also sort on fields that would be present in the output. I have sorted on the images and the creation date to get the last created image and filtered the ImageId
  • output : Output can be json or text based on the way you plan to consume it.

Using Python

You can do the same using the below python script:

import boto3
from operator import itemgetter

client = boto3.client('ec2')
response = client.describe_images(
    Filters=[
        {
            'Name': 'description',
            'Values': [
                'Amazon Linux AMI*',
            ]
        },
    ],
    Owners=[
        'amazon'
    ]
)
# Sort on Creation date Desc
image_details = sorted(response['Images'],key=itemgetter('CreationDate'),reverse=True)
ami_id = image_details[0]['ImageId']

Update:

You can use fine-grain filters to get a quicker response. The filters mentioned in @Jack's answer work.

filters = [ {
    'Name': 'name',
    'Values': ['amzn-ami-hvm-*']
},{
    'Name': 'description',
    'Values': ['Amazon Linux AMI*']
},{
    'Name': 'architecture',
    'Values': ['x86_64']
},{
    'Name': 'owner-alias',
    'Values': ['amazon']
},{
    'Name': 'owner-id',
    'Values': ['137112412989']
},{
    'Name': 'state',
    'Values': ['available']
},{
    'Name': 'root-device-type',
    'Values': ['ebs']
},{
    'Name': 'virtualization-type',
    'Values': ['hvm']
},{
    'Name': 'hypervisor',
    'Values': ['xen']
},{
    'Name': 'image-type',
    'Values': ['machine']
} ]

# Use above filters 
response = client.describe_images(
  Filters=filters,
  Owners=[
      'amazon'
  ]
)

Solution 3

The answers by Vaulstein and John Rotenstein helped me understand this solution. Thank you!

In my case, we have a lot of private AMIs posted by different owners (there are 2-3) and there is a mix of their custom private AMIs created using CentOS or AmazonLinux2 as the base. The task is to find the latest AMI which works on the x86 architecture and is based on AmazonLinux2.

Note that I am not using --owner because in my case the AMIs are posted by different teams and have different Owner IDs. But if you have a single owner/team which posts these, this is a recommended option to include to filter out all other AMIs that you don't want.

This is what worked for us:

aws ec2 describe-images \
--query 'sort_by(Images, &CreationDate)[-1].Name' \
--region eu-west-1 \
--no-include-deprecated \
--executable-users self \
--output text \
--filters "Name=name,Values=here-ami-amzn2-*" \
    "Name=architecture,Values=x86_64" \
    "Name=image-type,Values=machine" \
    "Name=state,Values=available" \
    "Name=virtualization-type,Values=hvm" \
    "Name=root-device-type,Values=ebs" 

Explanation: What we are doing here is:

This gets the results sorted by CreationDate. We are grabbing the -1 (last/latest) item's name from the result.

--query 'sort_by(Images, &CreationDate)[-1].Name'

Note that the available AMIs may vary by region, so be sure to specify the region where you intend to instantiate it.

--region eu-west-1 \

To avoid deprecated AMIs, if any. We didn't have any but decided to be future safe.

--no-include-deprecated \

To ensure that the fetched AMI is actually usable by you.

--executable-users self \

This is optional. If its text, the AMI name is returned without the double quotes

--output text \

Filters are used to narrow down results and to exclude unwanted results. Fortunately, our organization had named the AMIs in a way easy to differentiate with wither amzn2 or CentOS in the AMI name. We wanted the Amazon Linux 2 AMI

--filters "Name=name,Values=org-name-ami-amzn2-*" \

We have both ARM as well as x86_64 versions of AMIs, and my team's code has only been tested on X86_64. So choose that:

"Name=architecture,Values=x86_64" \

This could have different values, I think for most people this will be machine

"Name=image-type,Values=machine" \

Choose only the AMIs in the available state:

"Name=state,Values=available" \

This is the way virtualization is implemented. Most people can safely choose hvm:

"Name=virtualization-type,Values=hvm" \

Choose AMIs with root volume being an EBS

"Name=root-device-type,Values=ebs" 

Solution 4

I saw a similar script here

https://github.com/bwood/latest-ami/blob/master/latest-ami.py

however for some reason this when run, i get errors

Solution 5

From Ref:

https://aws.amazon.com/blogs/compute/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/

For AWS CloudFormation Specifically:

# Use public Systems Manager Parameter
Parameters:
  LatestAmiId:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'

Resources:
 Instance:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: !Ref LatestAmiId

From AWS CLI:

aws ssm get-parameters-by-path --path "/aws/service/ami-amazon-linux-latest" --region us-east-1

Powershell:

Get-SSMParametersByPath -Path "/aws/service/ami-amazon-linux-latest" -region us-east-1
Share:
14,077
Vaulstein
Author by

Vaulstein

I consider myself as a nascent programmer, technological enthusiast, fascinated by constantly changing technology. Why nascent? Because I am constantly overwhelmed by the immense knowledge that is to gain in the field of technology and this has been the driving force that has motivated me to keep learning.

Updated on August 02, 2022

Comments

  • Vaulstein
    Vaulstein almost 2 years

    I wanted to fetch the latest ami id for AWS Linux machine while creating an ec2 instance for an autoscaling architecture.

    I was trying the aws cli to get the images types, but it would print out a lot of information if I used the describe-images command.

    My requirement was to get only the image id, so that I could use it to create a launch configuration or launch an instance with the latest ami-id.