AWS
jq

【AWS】特定のタグを含むEC2インスタンスのAMIを一度に作るためのワンライナー【小ネタ】

やりたいこと

  • EC2インスタンスが数多く存在しているが、指定したタグ(Env=dev)を持つインスタンスのみフィルタしてAMIを作成したい。
  • ワンライナーでやることは、AWS CLIのコマンドを生成するところまで。実際の作成は出力結果をコピー&ペーストして実行する。
  • AMI名は、インスタンス名(Nameタグの値)と、日付8桁の文字列としたい。(例:api_20181011)
  • 出力結果は、インスタンス名(Nameタグ)でソートしたい。

作成したワンライナー

$ aws ec2 describe-instances --filters "Name=tag:Env,Values=dev" \
  | jq -r '.Reservations[].Instances[] | [.InstanceId, (.Tags[] | select (.Key == "Name").Value)] | @csv' \
  | sed 's/\"//g' | sort -t , -k 2 \
  | awk -F, '{image_name=$2 "_" strftime ("%Y%m%d"); print "aws ec2 create-image --no-reboot --instance-id", $1, "--name", image_name};'

実行するとこんな感じで結果が出力されます。

aws ec2 create-image --no-reboot --instance-id i-xxxxxxxxxxxxxxxxx --name api11_20181011
aws ec2 create-image --no-reboot --instance-id i-xxxxxxxxxxxxxxxxx --name api12_20181011
aws ec2 create-image --no-reboot --instance-id i-xxxxxxxxxxxxxxxxx --name web11_20181011
aws ec2 create-image --no-reboot --instance-id i-xxxxxxxxxxxxxxxxx --name web12_20181011

補足

ec2-describe-instancesの出力結果をフィルタする

まず、AWS API発行時点で、対象のインスタンスのみを抽出するよう、フィルタ条件を指定します。

$ aws ec2 describe-instances --filters "Name=tag:Env,Values=dev"

jqの結果をCSVとして出力する

下記を実行すると、インスタンスIDとNameタグの値をCSVとして出力します。

$ aws ec2 describe-instances --filters "Name=tag:Env,Values=dev" \
  | jq -r '.Reservations[].Instances[] | [.InstanceId, (.Tags[] | select (.Key == "Name").Value)] | @csv'

sortコマンドで指定の列を元に並べる・区切り文字として空白以外の文字を使う

sortコマンドは「-k」オプション(若しくは「--key=KEYDEF」オプション)を指定することで、ソート対象の列を指定することが出来ます。
また列の区切り文字は、デフォルトでは空白文字(white space/tab)ですが、
「-t」オプション(若しくは「--field-separator=SEP」オプション)で、任意の文字を指定することが可能です。

$ aws ec2 describe-instances --filters "Name=tag:Env,Values=dev" \
  | jq -r '.Reservations[].Instances[] | [.InstanceId, (.Tags[] | select (.Key == "Name").Value)] | @csv' \
  | sed 's/\"//g' | sort -t , -k 2 \

awkの中で時刻を取得する

シェルのコマンド置換を利用して、dateコマンドの出力結果を用いることもできますが、今回はawkスクリプトが少し長くなったので、strftimeを使いました。
フォーマット文字列は、dateコマンド等と恐らく一緒です、多分。(※未確認)

$ awk 'BEGIN {print strftime ("%Y%m%d")}'