IMDS(V2)の利用
お久しぶりです。H.Uでございます。
今回は以外に便利なIMDS(インスタンスメタデータサービス)についてご紹介した後、実際に利用していきたいと思います。
IMDS(インスタンスメタデータサービス)について
先ずは簡単にIMDSについてのご紹介です。
IMDSはインスタンスに関係する情報を内部から curl コマンドを利用して取得できるサービスです。
文章だけでは伝わりにくいの実際にEC2インスタンスを立ち上げて確認してみます。
注意事項としては、インスタンス立ち上げ時の際に「高度な詳細」設定にてアクセス可能なメタデータを有効化しておく必要があります。これだけで大元の設定は完了です。今回はセキュリティ面を考慮してV2のみ(トークン必須)にします。
それでは実際にどのように情報が取得できるか確認してみましょう。
[root@ip-10-0-3-100 ~]# TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 56 100 56 0 0 56000 0 --:--:-- --:--:-- --:--:-- 56000
[root@ip-10-0-3-100 ~]# echo $(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id)
i-0f79c69c60b85fb2b
[root@ip-10-0-3-100 ~]# echo $(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/placement/region)
ap-northeast-1
インスタンスIDとリージョン(ap-northeast-1)がともに一致しており、取得できていることがわかります。
詳細は省きますが、V2になってからTOKEN(セッショントークン)はセキュリティ対策として推奨されておりますので、今後は上記のようにTOKEN発行するのがオススメです。
全てのインスタンスメタデータをここではご紹介できませんが、参考に一覧が載っている公式ドキュメントのURLを貼りますので、興味がある方はご参照ください。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instancedata-data-categories.html
IMDS(V2)の利用
これだけでは何の面白味も無いので、ここからは少し応用していきましょう。
上記公式ドキュメントを確認してみると、「autoscaling/target-lifecycle-state」の箇所、Auto Scaling のスケールアウト(またはイン)するインスタンスのライフサイクル状態を取得することが可能です。
これの何が良いかというと、ライフサイクルの遷移状態をトリガーにして特定の処理を実行することが可能なのです。これも実際に確認してみます。
今回はインスタンス起動時に対象インスタンスのhostnameを変更するような設定を考えてみます。
これ自体は単純ですが、発展させればかなり応用が利きます。
ライフサイクルアクション設定
それでは、以下の①~④の手順に沿って確認していきます。
①ライフサイクルアクションを完了するための許可ロール作成
IAMのポリシー作成から [JSON] タブ を利用して、下記の許可ポリシーを作成します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:CompleteLifecycleAction"
],
"Resource": "arn:aws:autoscaling:*:「アカウントID」:autoScalingGroup:*:autoScalingGroupName/「任意のAuto Scaling グループ名」"
}
]
}
次にこの作成したポリシーを付与するロールを作成します。
信頼されたエンティティタイプ「AWS のサービス」→ ユースケース「EC2」を選択し、先ほど作成したポリシーを付与します。
②起動テンプレートを作成 + ロールとユーザーデータスクリプトの設定
起動テンプレートを作成していきます。
基本は通常の起動テンプレートと同じで問題無いです。
「高度な詳細」設定内の「IAM インスタンスプロフィール」は手順の①で作成したポリシーを設定することと、スケールアウト時にホストネームが変更されるように下記のユーザデータを作成する、この2つの設定のみ実施してください。(※確認用にSSH接続用の設定は必要です。)
#!/bin/bash
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
function get_target_state {
echo $(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/autoscaling/target-lifecycle-state)
}
function get_instance_id {
echo $(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id)
}
function get_region {
echo $(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/placement/region)
}
group_name='「任意のAuto Scaling グループ名(※①の時と同じ)」'
instance_id=$(get_instance_id)
region=$(get_region)
function complete_lifecycle_action {
echo $(aws autoscaling complete-lifecycle-action \
--lifecycle-hook-name 「後ほど作成する(④)任意のライフサイクルフック名」\
--auto-scaling-group-name $group_name \
--lifecycle-action-result CONTINUE \
--instance-id $instance_id \
--region $region)
}
function main {
while true
do
target_state=$(get_target_state)
if [ "$target_state" = "InService" ]; then
instance_id=$(get_instance_id)
# Change hostname
export new_hostname="$group_name-$instance_id"
echo $new_hostname
hostname $new_hostname
# Send callback
complete_lifecycle_action
break
fi
echo $target_state
sleep 5
done
}
main
このユーザデータは、下記のような内容です。
- IMDSを呼び出して、ライフサイクル状態とインスタンス ID 、リージョン情報を取得
- ライフサイクル状態が
InService
に変更されるまで、状態を繰り返し取得 -
InService
になると、ホスト名を Auto Scaling グループの名前が先頭に付加されたインスタンス ID に変更 - complete-lifecycle-action CLI コマンドを呼び出し、EC2 起動プロセスを続行
あくまでもサンプルのため、適宜環境に合わせて変更してください。
これで起動テンプレートは設定完了です。
③Auto Scaling グループ作成
この箇所も通常のAuto Scaling グループと同じで問題無いです。
名前は「任意のAuto Scaling グループ名(※①、②の時と同じ)」で、起動テンプレートは②で作成したものだけ設定してください。
④ライフサイクルフックの作成
「ライフサイクルフック」とは、ライフサイクル状態の遷移(起動/終了)が発生したとき、完了までの状態を一時的に制御することが可能な設定です。今回は一時的にライフサイクルアクションを実行するので、300秒ほど待機状態を作り、もし失敗していたい場合はタイムアウトするように設定します。
上記のように設定します。画像にある通り、ライフサイクルフック名は②の時に設定した名称にしてください。
設定は以上です。お疲れ様でした。
後は手動または自動で立ち上げたインスタンスに接続して確認だけしてみましょう。
[root@netassist-IMDSv2-autoscale-i-0a42244623c187d73 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
link/ether 06:2f:b5:b5:85:f3 brd ff:ff:ff:ff:ff:ff
altname enX0
inet 10.0.2.40/20 brd 10.0.15.255 scope global dynamic noprefixroute eth0
valid_lft 3583sec preferred_lft 3583sec
inet6 fe80::42f:b5ff:feb5:85f3/64 scope link
valid_lft forever preferred_lft forever
[root@netassist-IMDSv2-autoscale-i-0a42244623c187d73 ~]# uname -n
netassist-IMDSv2-autoscale-i-0a42244623c187d73
確かに起動時にホストネームが変更されています。
まとめ
今回はご紹介から単純な応用例まででしたが、実際にはもう少々複雑なものを設定できます。
弊社ではこれを用いて、スケールイン時にログ取得などでよく利用しています。
まだまだ利用法は思いつきそうですが、今回はここまで。
最後まで読んでいただき、ありがとうございました。
H.Uでした。