この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
コンサル部のとばち(@toda_kk)です。
Amazon EC2 Auto Scalingで管理しているEC2インスタンスについて、ライフサイクル状態をインスタンスメタデータサービス(IMDS)から取得できるようになりました。
EC2インスタンスのライフサイクルに応じた操作について、従来はAuto Scalingグループのライフサイクルフックを設定した上でEventBridgeなどと組み合わせることで実現可能でした。従来の方法については、下記の記事などが参考になるかと思います。
今回のアップデートによってライフサイクル状態の遷移をEC2インスタンス上から取得できるようになり、インスタンスメタデータサービスをポーリングしておくことで、EventBridgeなどを利用したイベント検知を設定しなくてもライフサイクル状態に応じた特定の操作をEC2インスタンス上から実行できるようになります。
ドキュメントの確認
インスタンスメタデータのカテゴリーのドキュメントに、ライフサイクルの項目 autoscaling/target-lifecycle-state
が追加されています。
取得できるステータスの値は、下記の通りです。このうち Warmed:
と付くものは、ウォームプールを利用した際の値となります。
- InService
- Terminated
- Detached
- Standby
- Warmed:Hibernated
- Warmed:Running
- Warmed:Stopped
- Warmed:Terminated
また、EC2 Auto Scalingのドキュメントにも、インスタンスメタデータからライフサイクル状態を取得する方法についてページが追加されています。
実際に取得する際のコマンドが記載されています。
IMDSv1
curl http://169.254.169.254/latest/meta-data/autoscaling/target-lifecycle-state
IMDSv2
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/autoscaling/target-lifecycle-state
ちなみに上記のURLは、EC2インスタンスがAuto Scalingによって起動している場合にのみ有効なようで、Auto Scalingグループで管理していないEC2インスタンスからリクエストすると404エラーが返ってきました。
Auto Scalingグループで管理していないEC2インスタンスから実行
$ curl http://169.254.169.254/latest/meta-data/autoscaling/target-lifecycle-state
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>404 - Not Found</title>
</head>
<body>
<h1>404 - Not Found</h1>
</body>
</html>
チュートリアルのドキュメントが用意されている
加えて、ユーザーデータを用いてインスタンスメタデータからライフサイクル状態を取得するためのチュートリアルのドキュメントも用意されていました。
チュートリアルでは、下記のスクリプトを実行するユーザーデータを起動テンプレートに設定しておき、Auto Scalingグループで管理するEC2インスタンスが起動した際にホスト名を変更する処理を実行しています。
ユーザーデータ
#!/bin/bash
function get_target_state {
echo $(curl -s http://169.254.169.254/latest/meta-data/autoscaling/target-lifecycle-state)
}
function get_instance_id {
echo $(curl -s http://169.254.169.254/latest/meta-data/instance-id)
}
function complete_lifecycle_action {
instance_id=$(get_instance_id)
group_name='TestAutoScalingEvent-group'
region='us-west-2'
echo $instance_id
echo $region
echo $(aws autoscaling complete-lifecycle-action \
--lifecycle-hook-name TestAutoScalingEvent-hook \
--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
# Change hostname
export new_hostname="${group_name}-$instance_id"
hostname $new_hostname
# Send callback
complete_lifecycle_action
fi
echo $target_state
sleep 5
done
}
main
このスクリプトは、下記のような内容となっています。
- インスタンスメタデータから、インスタンスのライフサイクル状態およびインスタンスIDを取得する
- ライフサイクルの状態が
InService
に変わるまで繰り返し取得する - ライフサイクルの状態が
InService
の場合、インスタンスのホスト名を、Auto Scalingグループの名前を先頭に付けたインスタンスIDに変更する - AWS CLIで
complete-lifecycle-action
コマンドを実行してコールバックを送信し、EC2 Auto Scalingに対して起動を継続させるよう通知して、ライフサイクルアクションを完了させる
工夫次第ではライフサイクルに応じたイベント処理がEC2インスタンス上で完結できそう
今回のアップデートによって、工夫次第ではライフサイクルに応じたイベント処理がEC2インスタンス上で完結できるようになりました。
ただし、インスタンスメタデータサービスをポーリングしておく必要があるなど、ある程度の制約はありそうです。
上手くいかない場合には、EventBridgeなどを利用した従来の方法も代替案としてご検討いただくのがよろしいかと思います。
以上、コンサル部のとばち(@toda_kk)でした。