labunix's blog

labunixのラボUnix

AWSのEC2イメージを調査して、最新のAMIイメージIDを取得してみた。

■AWSのEC2イメージを調査して、最新のAMIイメージIDを取得してみた。
 以下でAmazon Linux 2の最新のAMIイメージIDを取得する。

$ wget https://raw.githubusercontent.com/labunix/aws/main/aws-new-amzn2-amiget
$ chmod +x aws-new-amzn2-amiget 

$ ./aws-new-amzn2-amiget 
ami-01aab85a5e4a5a0fe

■lsecを使う方は以下もPATHの通ったディレクトリに配置して下さい。

$ wget https://raw.githubusercontent.com/labunix/lsec/master/lsec
$ chmod +x lsec

■最初のコーヒーブレイク。全情報採取。ここから検索で使うキーと値を探す。

$ aws ec2 describe-images > aws_ec2_describe-images.txt
$ du -h aws_ec2_describe-images.txt
111M	aws_ec2_describe-images.txt

■選択肢は以下。

 ImageOwnerAliasがamazonかaws-marketplace
 Stateがavailableだけど気にしなくて良さそう。
 VirtualizationTypeがhvm。
 Architectureはx86_64かarm64。あまりarm64を選ぶ機会は無いはず。
 gp2はルートボリュームの種別。

■Amazon Linux 2=「amzn2-ami」の
 所有者がselfかamazonの中で「hvm.*x86_64」で検索、
 日付の新しい順にソートして最新の1件だけのAMI-IDを抽出する。

$ aws ec2 describe-images --owners self amazon \
    --filters "Name=name,Values=amzn2-ami-hvm-*x86_64-gp2" \
    --query 'sort_by(Images[].{YMD:CreationDate,Name:Name,ImageId:ImageId,OwnerId:OwnerId},&YMD)|reverse(@) | [0].ImageId' \
    --output text
ami-01aab85a5e4a5a0fe

■旧版のAmazon Linux=「amzn-ami」の
 所有者がselfかamazonの中で「hvm.*x86_64」で検索、
 日付の新しい順にソートして最新の1件だけのAMI-IDを抽出する。

$ aws ec2 describe-images --owners self amazon \
    --filters "Name=name,Values=amzn-ami-hvm-*x86_64-gp2" \
    --query 'sort_by(Images[].{YMD:CreationDate,Name:Name,ImageId:ImageId,OwnerId:OwnerId},&YMD)|reverse(@) | [0].ImageId' \
    --output text
ami-0b7b24024613bd459

■「 | [0].ImageId」を外した、最新3件分の出力

$ aws ec2 describe-images --owners self amazon \
    --filters "Name=name,Values=amzn2-ami-hvm-*x86_64-gp2" \
    --query 'sort_by(Images[].{YMD:CreationDate,Name:Name,ImageId:ImageId,OwnerId:OwnerId},&YMD)|reverse(@)' \
    --output text | head -n 3
ami-01aab85a5e4a5a0fe	amzn2-ami-hvm-2.0.20210126.0-x86_64-gp2	137112412989	2021-01-26T07:39:01.000Z
ami-0a0ad6b70e61be944	amzn2-ami-hvm-2.0.20201218.1-x86_64-gp2	137112412989	2020-12-21T22:40:11.000Z
ami-09558250a3419e7d0	amzn2-ami-hvm-2.0.20201126.0-x86_64-gp2	137112412989	2020-11-26T04:15:49.000Z

$ aws ec2 describe-images --owners self amazon \
    --filters "Name=name,Values=amzn-ami-hvm-*x86_64-gp2" \
    --query 'sort_by(Images[].{YMD:CreationDate,Name:Name,ImageId:ImageId,OwnerId:OwnerId},&YMD)|reverse(@)' \
    --output text | head -n 3
ami-0b7b24024613bd459	amzn-ami-hvm-2018.03.0.20210126.1-x86_64-gp2	137112412989	2021-01-26T16:39:00.000Z
ami-04871f2244113b819	amzn-ami-hvm-2018.03.0.20201209.1-x86_64-gp2	137112412989	2020-12-22T07:12:38.000Z
ami-09191db56ce2e74ba	amzn-ami-hvm-2018.03.0.20201028.0-x86_64-gp2	137112412989	2020-10-29T23:47:47.000Z

■Amazon Linux、Amazon Linux 2のAMIを月別で集計してみる。
 実績として毎月03会の更新がある。

$ seq 1 12 | \
    awk '{for(a=2016;a<=2021;a++) \
         {if(a == "2016" && $1 > 6 || a == "2021" && $1 < 3 || a ~ /201[7-9]/) \
         {printf "%4d-%02d\n",a,$1 | "sort -uV"}}}' > year

$ aws ec2 describe-images --owners self amazon \
    --filters "Name=name,Values=amzn*-ami-hvm-*x86_64-gp2" \
    --query 'sort_by(Images[].{YMD:CreationDate,Name:Name,ImageId:ImageId,OwnerId:OwnerId},&YMD)|reverse(@)' \
    --output text | \
  awk '{a[substr($NF,1,7)" "substr($2,1,13)]+=1}END{for(n in a){print n,a[n] | "sort -Vr -k 2"}}' | \
  awk '{a[$1]=a[$1]" "$2" "$3}END{for(n in a){gsub("amzn-ami-hvm-","amzn-ami-hvm",a[n]);print n,a[n] | "sort -Vr"}}' | \
  awk '{if($0 ~ /  amzn2-ami-hvm/){print $1 "  -            - " $2,$3}else{print}}' > ami-list

$ sort -Vr year ami-list  | \
    awk '{a[$1]=a[$0]" "$0}END{for(n in a){print a[n],n}}' | \
    awk '{if($2 ~ /[0-9]-[0-9]/){print $1} \
     else{if($4 ~ /[0-9]-[0-9]/){printf "%7s %-13s %2s\n",$1,$2,$3} \
     else{printf "%7s %-13s %2s %13s %2s\n",$1,$2,$3,$4,$5}}}' | sort -uVr
2021-02
2021-01 amzn-ami-hvm   1 amzn2-ami-hvm  1
2020-12 amzn-ami-hvm   1 amzn2-ami-hvm  1
2020-11 -              - amzn2-ami-hvm  2
2020-10 amzn-ami-hvm   1                 
2020-10 amzn-ami-hvm   1
2020-09 amzn-ami-hvm   2 amzn2-ami-hvm  3
2020-08 amzn-ami-hvm   1                 
2020-08 amzn-ami-hvm   1
2020-07 amzn-ami-hvm   1 amzn2-ami-hvm  1
2020-06 amzn-ami-hvm   1 amzn2-ami-hvm  1
2020-05 amzn-ami-hvm   1 amzn2-ami-hvm  1
2020-04 amzn-ami-hvm   1 amzn2-ami-hvm  1
2020-03 amzn-ami-hvm   1 amzn2-ami-hvm  1
2020-02 amzn-ami-hvm   1 amzn2-ami-hvm  1
2019-12 amzn-ami-hvm   1 amzn2-ami-hvm  1
2019-11 -              - amzn2-ami-hvm  1
2019-10 -              - amzn2-ami-hvm  1
2019-09
2019-08 amzn-ami-hvm   1 amzn2-ami-hvm  1
2019-07
2019-06 amzn-ami-hvm   1 amzn2-ami-hvm  2
2019-05 amzn-ami-hvm   1 amzn2-ami-hvm  1
2019-04
2019-03 -              - amzn2-ami-hvm  1
2019-02 -              - amzn2-ami-hvm  2
2019-01 -              - amzn2-ami-hvm  2
2018-12
2018-11 amzn-ami-hvm   2 amzn2-ami-hvm  1
2018-10 -              - amzn2-ami-hvm  2
2018-09 -              - amzn2-ami-hvm  1
2018-08 amzn-ami-hvm   1 amzn2-ami-hvm  1
2018-07
2018-06 amzn-ami-hvm   1 amzn2-ami-hvm  1
2018-05 amzn-ami-hvm   1 amzn2-ami-hvm  1
2018-04 amzn-ami-hvm   1                 
2018-04 amzn-ami-hvm   1
2018-03 amzn-ami-hvm   2 amzn2-ami-hvm  1
2018-02
2018-01 amzn-ami-hvm   3 amzn2-ami-hvm  2
2017-12 -              - amzn2-ami-hvm  1
2017-11 amzn-ami-hvm   2                 
2017-11 amzn-ami-hvm   2
2017-10 amzn-ami-hvm   1                 
2017-10 amzn-ami-hvm   1
2017-09 amzn-ami-hvm   1                 
2017-09 amzn-ami-hvm   1
2017-08 amzn-ami-hvm   1                 
2017-08 amzn-ami-hvm   1
2017-07
2017-06 amzn-ami-hvm   2                 
2017-06 amzn-ami-hvm   2
2017-05
2017-04 amzn-ami-hvm   2                 
2017-04 amzn-ami-hvm   2
2017-03 amzn-ami-hvm   2                 
2017-03 amzn-ami-hvm   2
2017-02
2017-01 amzn-ami-hvm   1                 
2017-01 amzn-ami-hvm   1
2016-12 amzn-ami-hvm   1                 
2016-12 amzn-ami-hvm   1
2016-11
2016-10 amzn-ami-hvm   1                 
2016-10 amzn-ami-hvm   1
2016-09 amzn-ami-hvm   1                 
2016-09 amzn-ami-hvm   1
2016-08 amzn-ami-hvm   1                 
2016-08 amzn-ami-hvm   1
2016-07

#####これ以降は、上記の条件を導くための調査#####

■jsonの構造をチェックしてみる。

$ cat aws_ec2_describe-images.txt | jq -r '.Images[]' | \
  awk -F: -v sep="^  \042" 'BEGIN{f=0} \
    {if(NF>1){if($0 ~ sep){gsub("\042","",$1);f++;a[f]=$1}else{gsub("\042","",$1);if(a[f] !~ $1){a[f]=a[f]" "$1}}}}\
    END{for(n in a){gsub("  *"," ",a[n]);print a[n] | "sort -uV"}}'
 Architecture
 BlockDeviceMappings
 BlockDeviceMappings DeviceName Ebs DeleteOnTermination Iops SnapshotId VolumeSize VolumeType Encrypted
 BlockDeviceMappings DeviceName Ebs DeleteOnTermination Iops SnapshotId VolumeSize VolumeType Encrypted VirtualName
 BlockDeviceMappings DeviceName Ebs DeleteOnTermination SnapshotId VolumeSize VolumeType Encrypted
 BlockDeviceMappings DeviceName Ebs DeleteOnTermination SnapshotId VolumeSize VolumeType Encrypted Iops
 BlockDeviceMappings DeviceName Ebs DeleteOnTermination SnapshotId VolumeSize VolumeType Encrypted Iops VirtualName
 BlockDeviceMappings DeviceName Ebs DeleteOnTermination SnapshotId VolumeSize VolumeType Encrypted VirtualName
 BlockDeviceMappings DeviceName VirtualName
 CreationDate
 Description
 EnaSupport
 Hypervisor
 ImageId
 ImageLocation
 ImageOwnerAlias
 ImageType
 KernelId
 Name
 OwnerId
 Platform
 PlatformDetails
 ProductCodes ProductCodeId ProductCodeType
 Public
 RootDeviceName
 RootDeviceType
 SriovNetSupport
 State
 UsageOperation
 VirtualizationType

■Iopsの出現順序によって同じものが別ものとして扱われているのは、
 マーケットプレイスで順序の異なる書き方があるから。
 どうでもいいけど。

$ cat aws_ec2_describe-images.txt | jq -r '.Images[]' | lsec -sep '^{' ImageOwnerAlias.*amazon | \
    awk -F: -v sep="^  \042" 'BEGIN{f=0} \
      {if(NF>1){if($0 ~ sep){gsub("\042","",$1);f++;a[f]=$1}else{gsub("\042","",$1);if(a[f] !~ $1){a[f]=a[f]" "$1}}}}\
   END{for(n in a){gsub("  *"," ",a[n]);print a[n] | "sort -uV"}}' > amazon.txt

$ cat aws_ec2_describe-images.txt | jq -r '.Images[]' | lsec -sep '^{' ImageOwnerAlias.*aws-marketplace | \
    awk -F: -v sep="^  \042" 'BEGIN{f=0} \
      {if(NF>1){if($0 ~ sep){gsub("\042","",$1);f++;a[f]=$1}else{gsub("\042","",$1);if(a[f] !~ $1){a[f]=a[f]" "$1}}}}\
   END{for(n in a){gsub("  *"," ",a[n]);print a[n] | "sort -uV"}}' > aws-marketplace.txt

$ diff amazon.txt aws-marketplace.txt
2c2
<  BlockDeviceMappings
---
>  BlockDeviceMappings DeviceName Ebs DeleteOnTermination Iops SnapshotId VolumeSize VolumeType Encrypted
3a4,5
>  BlockDeviceMappings DeviceName Ebs DeleteOnTermination SnapshotId VolumeSize VolumeType Encrypted Iops
>  BlockDeviceMappings DeviceName Ebs DeleteOnTermination SnapshotId VolumeSize VolumeType Encrypted Iops VirtualName

■イメージの種類はamazonかaws-marketplace。

$ awk -F\: '/ImageOwnerAlias/{gsub("\042|,","",$NF);a[$NF]+=1}END{for(n in a){print a[n],n}}' aws_ec2_describe-images.txt 
6266  amazon
17250  aws-marketplace

■StateはImageOwnerAliasを持たないものもある。

$ cat aws_ec2_describe-images.txt | jq -r -c '.Images[] | [ .ImageOwnerAlias , .State ]' | \
    awk '{a[$0]+=1}END{for(n in a){print a[n],n | "sort -uV -k 2"}}'
44259 [null,"available"]
6266 ["amazon","available"]
17250 ["aws-marketplace","available"]

■32bit(i386)が生き残っているのは逆に気になる。
 アーキテクチャにmacがあるのは公式だけ。
 macが増えたことにawscliのhelpマニュアルが追いついてない様子。

$ cat aws_ec2_describe-images.txt | jq -r '.Images[]' | lsec -sep '^{' ImageOwnerAlias.*amazon | \
    awk -F'[:\042]' '/Architecture/{a[$(NF-1)]+=1}END{for(n in a){print a[n],n}}'
1 i386
6237 x86_64
7 x86_64_mac
305 arm64

$ cat aws_ec2_describe-images.txt | jq -r '.Images[]' | lsec -sep '^{' ImageOwnerAlias.*aws-marketplace | \
    awk -F'[:\042]' '/Architecture/{a[$(NF-1)]+=1}END{for(n in a){print a[n],n}}'
3 i386
17153 x86_64
94 arm64

$ cat aws_ec2_describe-images.txt | jq -r '.Images[]' | lsec -sep '^{' Architecture.*x86_64_mac | \
    jq -r -c '[ .PlatformDetails , .Hypervisor , .State , .CreationDate , .Name ]' | sort -t , -k 4
["Linux/UNIX","xen","available","2020-11-20T18:11:52.000Z","amzn-ec2-macos-10.14.6-20201119-161057"]
["Linux/UNIX","xen","available","2020-11-20T18:12:59.000Z","amzn-ec2-macos-10.15.7-20201119-085145"]
["Linux/UNIX","xen","available","2020-12-09T02:18:41.000Z","amzn-ec2-macos-10.14.6-20201204-234230"]
["Linux/UNIX","xen","available","2020-12-09T02:27:02.000Z","amzn-ec2-macos-10.15.7-20201204-234310"]
["Linux/UNIX","xen","available","2021-01-09T01:12:04.000Z","amzn-ec2-macos-10.15.7-20210106-130039"]
["Linux/UNIX","xen","available","2021-01-09T01:31:32.000Z","amzn-ec2-macos-10.14.6-20210106-130113"]
["Linux/UNIX","xen","available","2021-01-28T23:46:10.000Z","amzn-ec2-macos-10.14.6-20210122-183125"]

$ cat aws_ec2_describe-images.txt | jq -r '.Images[]' | lsec -sep '^{' Architecture.*i386 | \
    jq -r -c '[ .PlatformDetails , .Hypervisor , .State , .CreationDate , .Name ]' | sort -t , -k 4
["Windows","xen","available","2016-08-17T08:03:06.000Z","GCE665-03272014-100-e96e53f9-e1b0-455b-9aec-7f49d719991c-ami-915c4af8.2"]
["Windows","xen","available","2016-08-17T10:19:18.000Z","GCE1687-03112015-20-78b6754e-eae7-4f69-8fd6-168273e95436-ami-14d8ff7c.2"]
["Windows","xen","available","2016-08-17T10:22:05.000Z","GSP1687-03112015-20-c80f607e-e00f-4c49-9aa9-59bd42d91854-ami-f0466098.2"]
["Linux/UNIX","xen","available","2016-09-28T21:21:41.000Z","pv-grub-hd0_1.05-i386.gz"]
["Windows","xen","available","2016-10-20T03:20:16.000Z","Windows 2003 R2 x86 Recovery Instance CitrixXen"]
["Windows","xen","available","2016-10-20T03:20:49.000Z","Windows 2008 x86 Recovery Instance CitrixXen"]
["Linux/UNIX","xen","available","2016-10-31T17:34:24.000Z","Racemi-CentOS-5-i386-HVM-20141112085400"]
["Linux/UNIX","xen","available","2016-10-31T17:35:38.000Z","Racemi-CentOS-6-i386-HVM-20141112085400"]
["Windows","xen","available","2016-10-31T17:38:52.000Z","Racemi-Windows_Server-2003-R2_SP2-English-32Bit-Base-2015.12.31"]
["Windows","xen","available","2016-10-31T17:39:21.000Z","Racemi-Windows_Server-2008-SP2-English-32Bit-Base-2015.12.31"]
["Linux/UNIX","xen","available","2017-02-16T13:50:12.000Z","PBXWare-4.1"]
["Linux/UNIX","xen","available","2017-03-31T02:16:10.000Z","OL6.9-i386-HVM-2017-03-29"]
["Linux/UNIX","xen","available","2017-04-13T18:17:04.000Z","Racemi-CentOS-5-i386-HVM-20170412111500"]
["Linux/UNIX","xen","available","2017-11-29T03:06:52.000Z","Arcserve_UDP_Archiving_6_With_Update_1_AMI"]
["Windows","xen","available","2018-12-20T10:30:39.000Z","cohesity_win_i386_6.1"]

■公式(amazon)とマーケットプレイス(aws-marketplace)、nullのAMIを月別で集計してみる。

$ cat aws_ec2_describe-images.txt | jq -r -c '.Images[] | [ .ImageOwnerAlias , .CreationDate ]' | \
    awk -F, '{gsub("\042|\\[|\\]","",$0);a[$1" "substr($2,1,7)]+=1}END{for(n in a){print n,a[n] | "sort -V -k 1"}}' | \
    awk '{a[$2]=a[$2]" "$1" "$3}END{for(n in a){print n,a[n] | "sort -V"}}'
2016-07  amazon 2
2016-08  amazon 6 aws-marketplace 482
2016-09  amazon 28 aws-marketplace 99 null 6
2016-10  amazon 31 aws-marketplace 149 null 872
2016-11  amazon 11 aws-marketplace 186 null 216
2016-12  amazon 32 aws-marketplace 68 null 718
2017-01  amazon 31 aws-marketplace 71 null 452
2017-02  amazon 6 aws-marketplace 102 null 556
2017-03  amazon 41 aws-marketplace 71 null 470
2017-04  amazon 31 aws-marketplace 117 null 857
2017-05  amazon 27 aws-marketplace 138 null 501
2017-06  amazon 53 aws-marketplace 75 null 831
2017-07  amazon 30 aws-marketplace 93 null 472
2017-08  amazon 58 aws-marketplace 103 null 467
2017-09  amazon 32 aws-marketplace 93 null 390
2017-10  amazon 27 aws-marketplace 140 null 396
2017-11  amazon 54 aws-marketplace 168 null 521
2017-12  amazon 40 aws-marketplace 112 null 371
2018-01  amazon 117 aws-marketplace 147 null 605
2018-02  amazon 42 aws-marketplace 95 null 414
2018-03  amazon 54 aws-marketplace 134 null 586
2018-04  amazon 28 aws-marketplace 82 null 603
2018-05  amazon 54 aws-marketplace 121 null 544
2018-06  amazon 56 aws-marketplace 125 null 465
2018-07  amazon 38 aws-marketplace 153 null 451
2018-08  amazon 105 aws-marketplace 141 null 933
2018-09  amazon 83 aws-marketplace 84 null 493
2018-10  amazon 58 aws-marketplace 130 null 999
2018-11  amazon 106 aws-marketplace 113 null 766
2018-12  amazon 62 aws-marketplace 123 null 739
2019-01  amazon 75 aws-marketplace 133 null 853
2019-02  amazon 88 aws-marketplace 217 null 631
2019-03  amazon 94 aws-marketplace 236 null 828
2019-04  amazon 71 aws-marketplace 164 null 841
2019-05  amazon 69 aws-marketplace 211 null 1146
2019-06  amazon 156 aws-marketplace 259 null 1075
2019-07  amazon 64 aws-marketplace 278 null 908
2019-08  amazon 63 aws-marketplace 308 null 820
2019-09  amazon 85 aws-marketplace 315 null 893
2019-10  amazon 70 aws-marketplace 567 null 1218
2019-11  amazon 106 aws-marketplace 346 null 1257
2019-12  amazon 73 aws-marketplace 304 null 1145
2020-01  amazon 66 aws-marketplace 394 null 997
2020-02  amazon 158 aws-marketplace 360 null 946
2020-03  amazon 110 aws-marketplace 606 null 1023
2020-04  amazon 179 aws-marketplace 734 null 1203
2020-05  amazon 140 aws-marketplace 705 null 1384
2020-06  amazon 229 aws-marketplace 759 null 1847
2020-07  amazon 148 aws-marketplace 799 null 1212
2020-08  amazon 283 aws-marketplace 760 null 1224
2020-09  amazon 383 aws-marketplace 868 null 1065
2020-10  amazon 577 aws-marketplace 869 null 1249
2020-11  amazon 584 aws-marketplace 775 null 1243
2020-12  amazon 474 aws-marketplace 1126 null 1408
2021-01  amazon 553 aws-marketplace 1230 null 1788
2021-02  amazon 25 aws-marketplace 212 null 361