ちばのてっく

積極的にアウトプット

AWS CLIで最新の無料利用対象AMI IDを出力してみた

TerraformでEC2インスタンスを作成しようとしたときに、AMI IDが必要となる。EC2コンソールから確認する方法はタイプミスも起こりうるし手間なので、AWS CLIを使って最新かつ無料利用対象のAMIを取得してみる。

はじめに結論

入力

aws ec2 describe-images --owners amazon --filters 'Name=name,Values=al2023-ami-2*' --query 'sort_by(Images,&CreationDate)[-1].[ImageId]' --output text

出力

ami-034c9ca2bdde7b472

やってみた

準備運動

AWS CLIのリファレンスを参考にいろいろ試してみる。

まずは、オプションなしで実行してみる。

aws ec2 describe-images

json形式で情報が出力された。なお、ページネーションされており、出力された情報はここに転記した限りのものではない。なお、全件取得しているから、出力されるまでにちょい時間もかかった。

{
    "Images": [
        {
            "Architecture": "arm64",
            "CreationDate": "2022-10-26T08:50:11.000Z",
            "ImageId": "ami-0783825db772157e8",
            "ImageLocation": "aws-marketplace/ARM_Docs_Enterprise_Edition_100-322bee60-8ff7-4367-bce6-0c3d414e7c2f",
            "ImageType": "machine",
            "Public": true,
            "OwnerId": "679593333241",
            "PlatformDetails": "Linux/UNIX",
            "UsageOperation": "RunInstances",
            "ProductCodes": [
                {
                    "ProductCodeId": "2yxhenxqx8xwfnu96mclbi2i7",
                    "ProductCodeType": "marketplace"
                }
            ],
            "State": "available",
            "BlockDeviceMappings": [
                {
                    "DeviceName": "/dev/sda1",
                    "Ebs": {
                        "DeleteOnTermination": true,
                        "SnapshotId": "snap-022658c8e17e00925",
                        "VolumeSize": 50,
                        "VolumeType": "gp2",
                        "Encrypted": false
                    }
                },
:

次は、AWS公式ドキュメントにあるサンプル通りに実行してみる。

aws ec2 describe-images --owners self amazon

--owners self amazonを追加したため、自身およびAWSが所有するAMIの情報が出力された。

{
    "Images": [
        {
            "Architecture": "arm64",
            "CreationDate": "2022-09-11T18:43:34.000Z",
            "ImageId": "ami-072fd2ac175987855",
            "ImageLocation": "amazon/debian-11-arm64-20220911-1135",
            "ImageType": "machine",
            "Public": true,
            "OwnerId": "136693071363",
            "PlatformDetails": "Linux/UNIX",
            "UsageOperation": "RunInstances",
            "State": "available",
            "BlockDeviceMappings": [
                {
                    "DeviceName": "/dev/xvda",
                    "Ebs": {
                        "DeleteOnTermination": true,
                        "SnapshotId": "snap-049f8f94068975a38",
                        "VolumeSize": 8,
                        "VolumeType": "gp2",
                        "Encrypted": false
                    }
                }
            ],
            "Description": "Debian 11 (20220911-1135)",
            "EnaSupport": true,
            "Hypervisor": "xen",
            "ImageOwnerAlias": "amazon",
            "Name": "debian-11-arm64-20220911-1135",
            "RootDeviceName": "/dev/xvda",
:

ようやく本題

--query

JSON形式でずらっと表示する必要はなく、AMI IDだけがわかればよいため、--queryオプションを使って出力結果を絞る。直前の出力結果から、Images配下のImageIdにAMI IDが格納されていることがわかったため、以下のようなコマンドを発行する。

aws ec2 describe-images --owners amazon --query 'Images[].[ImageId]'

AMI IDだけが出力されるようになった。

[
    [
        "ami-07f84aef74d43e3f6"
    ],
    [
        "ami-077b3ac4f90ca037d"
    ],
    [
        "ami-0c3be11bbde86acc9"
    ],
    [
        "ami-0536b4ea4c52f3de7"
    ],
    [
        "ami-00f135819964ee6d4"
:

JSON形式だと見づらいため、--outputオプションを用いてtext形式で出力されるようにする。

aws ec2 describe-images --owners amazon --query 'Images[].[ImageId]' --output text

text形式になり、みやすくなった。

ami-096260c2e6846d8cc
ami-03d1ed1b9fd997201
ami-0abede41b16d742a4
ami-0eb19f14e6cd47620
ami-06e2e2f7191df1cff
ami-0e0b03b0858b9c598
ami-07259a121c2c3b64e
ami-0deb2dde49a4fbfc5
ami-01f8e82710fa38050
ami-089caded1bdbfbe5c
ami-066623c10b1002216
ami-0b2a4d3ca2a8dee16
ami-0d49ed3d0db984485
ami-0725760eac0602582
ami-019501f824222b0ce
:

最新のAMI IDのみ出力すればよいため、--queryオプションをさらに修正する。 クエリではJMESPathなる、JSONのクエリ言語を扱える。

クエリでは、JMESPath 構文を使用して、出力をフィルタリングするための式を作成します

引用:AWS CLI の出力をフィルタリングする https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-usage-filter.html#cli-usage-filter-client-side

まずは、JMESPathの組み込み関数であるsort_byを利用して、出力結果をソートする。ソートキーには、CreationDateを使うこととする。なお、sort_byは昇順ソートのため、末尾のAMI IDを取得する。

aws ec2 describe-images --owners amazon --query 'sort_by(Images,&CreationDate)[-1].[ImageId]' --output text

あるいはJMESPathの組み込み関数であるreverseを組み合わせて、降順にソートしたうえで、先頭のデータを取得する。

aws ec2 describe-images --owners amazon --query 'reverse(sort_by(Images,&CreationDate))[0].[ImageId]' --output text

すると、最新の1件のAMI IDが取得できた。

ami-08667f7205cd9a3f0
--filters

次に、--filtersオプションで、AmazonLinux2023が出力されるようにフィルタリングする。なお、AmazonLinux2023のAMI IDは、al2023-ami-で始まることをEC2コンソールから確認した。

なお、--filtersは、Name=hoge,Values=fugaを指定する。Nameの値はAWS CLI Command Referenceを参照。また、Valuesの値には*や?といったワイルドカードが使える。

aws ec2 describe-images --owners amazon --filters 'Name=name,Values=al2023-ami-*' --query 'sort_by(Images,&CreationDate)[-1].[ImageId]' --output text

お目当てのAMI IDを取得できたと思ったが、よくみるとEC2コンソールで確認したAMI IDと違った。

ami-092ee79bf91da299e

そこで、それぞれのAMIの情報を比較してみた。

aws ec2 describe-images --owners amazon --filters 'Name=image-id,Values=ami-092ee79bf91da299e' > ami-092ee79bf91da299e.txt
aws ec2 describe-images --owners amazon --filters 'Name=image-id,Values=ami-034c9ca2bdde7b472' > ami-034c9ca2bdde7b472.txt
diff ami-092ee79bf91da299e.txt ami-034c9ca2bdde7b472.txt

すると、Nameに有意な差がみられた。EC2コンソールで確認した無料利用対象のNameには、minimalという文字列が含まれていなかった。

5,7c5,7
<             "CreationDate": "2024-03-13T02:25:01.000Z",
<             "ImageId": "ami-092ee79bf91da299e",
<             "ImageLocation": "amazon/al2023-ami-minimal-2023.3.20240312.0-kernel-6.1-x86_64",
---
>             "CreationDate": "2024-03-13T02:16:23.000Z",
>             "ImageId": "ami-034c9ca2bdde7b472",
>             "ImageLocation": "amazon/al2023-ami-2023.3.20240312.0-kernel-6.1-x86_64",
20c20
<                         "SnapshotId": "snap-0b64bb669a51ba903",
---
>                         "SnapshotId": "snap-0a53ae1296688c3dc",
28c28
<             "Description": "Amazon Linux 2023 AMI 2023.3.20240312.0 x86_64 Minimal HVM kernel-6.1",
---
>             "Description": "Amazon Linux 2023 AMI 2023.3.20240312.0 x86_64 HVM kernel-6.1",
32c32
<             "Name": "al2023-ami-minimal-2023.3.20240312.0-kernel-6.1-x86_64",
---
>             "Name": "al2023-ami-2023.3.20240312.0-kernel-6.1-x86_64",
38c38
<             "DeprecationTime": "2024-06-11T02:25:00.000Z",
---
>             "DeprecationTime": "2024-06-11T02:16:00.000Z",

ので、--filtersの引数を修正した。

aws ec2 describe-images --owners amazon --filters 'Name=name,Values=al2023-ami-2*' --query 'sort_by(Images,&CreationDate)[-1].[ImageId]' --output text

無事、無料利用対象の最新AMI IDを取得できた。

ami-034c9ca2bdde7b472

残課題

今回のように近しい命名規則のAMIが追加された場合や、AWS側でNameの命名規則を変えた場合に、期待通りの出力結果が得られなくなる可能性がある。無料利用対象という条件で絞り込むような、スマートな方法があるのかもしれない。