Auto ScalingでEC2インスタンスを削除するとき、デフォルト設定では即座に終了処理が始まります。
HTTPリクエストを受け付けているインスタンスが突然消えると、クライアントにエラーが返ります。コネクションを安全にドレインさせる猶予を挟む仕組みが「ライフサイクルフック」です。
この記事では、aws autoscaling put-lifecycle-hookコマンドでスケールイン時のプロセス監視を設計する方法を解説します。接続ドレインの確認スクリプトと、complete-lifecycle-actionによる完了通知の手順まで取り上げます。
Amazon Linux 2023とAWS CLI v2を想定環境として説明します。
この記事のポイント
・ aws autoscaling put-lifecycle-hookでTerminatingフックを作成できる
・ heartbeat-timeoutでドレインの猶予時間を秒単位で指定する
・ ss -tnで確立済み接続数を確認してからcomplete-lifecycle-actionを呼ぶ
・ IAMロールにCompleteLifecycleAction権限がないとエラーになる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜライフサイクルフックが必要なのか
Auto Scalingは、CPUや接続数のメトリクスに応じてEC2インスタンスの台数を自動で増減させます。スケールアウトはインスタンスを追加するため問題は少ないですが、スケールインでは稼働中のインスタンスを削除します。
デフォルト動作では、削除対象になったインスタンスはすぐに「Terminating」状態に遷移し、プロセスが終了します。
HTTPSの通信中にインスタンスが消えると、クライアントはエラーを受け取ります。
ライフサイクルフックを使うと、「Terminating:Wait」という待機状態を挟めます。この猶予時間の間に、プロセスの終了確認やコネクションのドレインを実行できます。
ライフサイクルフックには2種類あります。
・ INSTANCE_LAUNCHING: インスタンスがサービスイン前の準備に使う
・ INSTANCE_TERMINATING: インスタンス削除前の終了処理に使う
プロセス監視の文脈では「INSTANCE_TERMINATING」を使います。
ライフサイクルフックを設定する(put-lifecycle-hook)
1. Terminatingフックを作成する
Auto ScalingグループにTerminatingフックを設定するコマンドを確認してください。# Terminatingライフサイクルフックを作成する aws autoscaling put-lifecycle-hook \ --lifecycle-hook-name drain-hook \ --auto-scaling-group-name my-asg \ --lifecycle-transition autoscaling:EC2_INSTANCE_TERMINATING \ --heartbeat-timeout 300 \ --default-result CONTINUE
・ --lifecycle-hook-name: フック名(同じASG内で一意にする)
・ --lifecycle-transition: トリガーのタイミング(LAUNCHING or TERMINATING)
・ --heartbeat-timeout: 待機の最大秒数(デフォルト3600秒。300秒が一般的)
・ --default-result: タイムアウト時の動作(CONTINUEで終了処理を続行。ABANDONは中断)
2. 設定内容を確認する
作成したフックは次のコマンドで確認できます。# ライフサイクルフックの一覧を取得する aws autoscaling describe-lifecycle-hooks \ --auto-scaling-group-name my-asg
{ "LifecycleHooks": [ { "LifecycleHookName": "drain-hook", "AutoScalingGroupName": "my-asg", "LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", "HeartbeatTimeout": 300, "GlobalTimeout": 7200, "DefaultResult": "CONTINUE" } ] }
プロセス監視スクリプトの設計
ライフサイクルフックが発火すると、設定済みのSNSトピックかSQSキューに通知が届きます。その通知を受けて、インスタンス上でドレインスクリプトを実行し、完了後にcomplete-lifecycle-actionを呼び出します。
1. SQSキューへ通知先を設定する
フックとSQSを連携させるには、put-lifecycle-hookに通知先のARNを追加します。# SQSキューを通知先に指定する aws autoscaling put-lifecycle-hook \ --lifecycle-hook-name drain-hook \ --auto-scaling-group-name my-asg \ --lifecycle-transition autoscaling:EC2_INSTANCE_TERMINATING \ --heartbeat-timeout 300 \ --default-result CONTINUE \ --notification-target-arn arn:aws:sqs:ap-northeast-1:123456789012:lifecycle-queue \ --role-arn arn:aws:iam::123456789012:role/AutoScalingNotificationRole
2. 接続ドレインを確認するスクリプト
インスタンス上で動作するドレインスクリプトの例を示します。ssコマンドで確立済みの接続数を確認し、ゼロになったら完了通知を送ります。ssコマンドを使ったポート確認の基本についてはLinux ポート確認の全コマンドで詳しく解説しています。
#!/bin/bash # ライフサイクルフック用ドレインスクリプト # 保存先例: /usr/local/bin/lifecycle-drain.sh HOOK_NAME="drain-hook" ASG_NAME="my-asg" INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) MAX_WAIT=240 ELAPSED=0 # 確立済みのTCP接続数を確認する(最大MAX_WAIT秒待機する) while [ "$ELAPSED" -lt "$MAX_WAIT" ]; do CONN=$(ss -tn state established | grep -E ':80|:443' | wc -l) if [ "$CONN" -eq 0 ]; then break fi sleep 5 ELAPSED=$((ELAPSED + 5)) done # ライフサイクルアクションを完了する aws autoscaling complete-lifecycle-action \ --lifecycle-hook-name "$HOOK_NAME" \ --auto-scaling-group-name "$ASG_NAME" \ --lifecycle-action-result CONTINUE \ --instance-id "$INSTANCE_ID"
・ ss -tn state established: 確立済みのTCPコネクションを取得する
・ MAX_WAIT: heartbeat-timeout(300秒)より短くして完了通知が遅れないようにする
・ complete-lifecycle-action --lifecycle-action-result CONTINUE: 終了処理を続行する
3. complete-lifecycle-actionで完了を通知する
ドレインが完了したら、必ずcomplete-lifecycle-actionを呼ぶ必要があります。呼ばない場合はheartbeat-timeoutが経過し、default-resultの設定に従います。
# CONTINUE: インスタンス終了を続行する aws autoscaling complete-lifecycle-action \ --lifecycle-hook-name drain-hook \ --auto-scaling-group-name my-asg \ --lifecycle-action-result CONTINUE \ --instance-id i-0abc12345678defgh # ABANDON: ライフサイクルアクションを中断する(緊急停止やデバッグ時に使う) aws autoscaling complete-lifecycle-action \ --lifecycle-hook-name drain-hook \ --auto-scaling-group-name my-asg \ --lifecycle-action-result ABANDON \ --instance-id i-0abc12345678defgh
AWSセミナーでの実践的な構成パターンについて
大規模な構成では、SNSとEventBridgeを組み合わせる設計が使われます。SNSトピックを経由してLambdaがSSM Run Commandを呼び出し、インスタンス上でドレインスクリプトを実行するパターンが代表的です。
SQSポーリング方式(先に紹介した方法)と比較すると、次の違いがあります。
・ SQSポーリング方式: インスタンス自身がキューを監視する。シンプルな構成に向く
・ SNS + Lambda方式: 中央管理のLambdaがドレイン処理を制御する。複数ASGを一元管理できる
AWSの実践的な構成設計についてはAWSセミナー(Amazon Linux対応)でも取り上げています。
よくある問題と対処法
1. heartbeat-timeoutが切れてインスタンスが強制終了する
ドレインスクリプトの実行時間がheartbeat-timeoutを超えると、default-resultに従って処理が進みます。CONTINUEに設定している場合はインスタンスが終了します。長時間のドレインが予想される場合は、ハートビートを延長してください。
# ハートビートを延長する(GlobalTimeoutまで繰り返し延長できる) aws autoscaling record-lifecycle-action-heartbeat \ --lifecycle-hook-name drain-hook \ --auto-scaling-group-name my-asg \ --instance-id i-0abc12345678defgh
2. complete-lifecycle-actionでIAM権限エラーになる
EC2インスタンスのIAMロールに次の権限が必要です。・ autoscaling:CompleteLifecycleAction
・ autoscaling:RecordLifecycleActionHeartbeat
インスタンスプロファイルに上記のアクションを追加してください。
本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| Terminatingフックを作成する | aws autoscaling put-lifecycle-hook --lifecycle-transition autoscaling:EC2_INSTANCE_TERMINATING |
| フック設定を確認する | aws autoscaling describe-lifecycle-hooks --auto-scaling-group-name 名前 |
| フック完了を通知する | aws autoscaling complete-lifecycle-action --lifecycle-action-result CONTINUE |
| ハートビートを延長する | aws autoscaling record-lifecycle-action-heartbeat --lifecycle-hook-name フック名 |
| 確立済みTCP接続数を確認する | ss -tn state established | grep -E ':80|:443' | wc -l |
>>AWSセミナー(Amazon Linux対応)の詳細と申し込み
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Traffic MirroringによるAWSネットワーク監視設計|マルチAZ構成でのパケットキャプチャ配置
- この記事の属するカテゴリ:AWS(Amazon Linux)へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます