話題の記事

【新機能】Auto Scalingのインスタンス起動/破棄時に初期処理/終了処理を追加 – LifeCycleHook機能のご紹介

2014.08.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、せーのです。

Auto Scalingの新機能についてはこれまでStandby StateDetach Instanceとご紹介してきましたが、実はもう一つ新機能があります。それが今回ご紹介する「LifeCycleHook」機能です。読んで字のごとく、Auto Scalingにおけるインスタンスのライフサイクルをフックする、という機能です。それでは詳しく見ていきましょう。

Auto Scalingにおけるインスタンスのライフサイクル

Auto Scalingのインスタンスの「ライフサイクル」、つまりインスタンスが生まれてから死ぬまでの状態遷移はどのようなものでしょう。
インスタンスが起動し始めてからAuto Scaling Groupに追加するまでの状態を「Pending」といいます。
pending Auto Scalingが縮退して、要らなくなったインスタンスが破棄される際も、Auto Scaling Groupから除外された後、実際に破棄されるまでの間の状態が存在します。これを「Terminating」といいます。
つまりAuto Scalingにおけるインスタンスのライフサイクルは インスタンス起動(Pending)→Auto Scaling Groupに追加(Pending)→起動完了(running)→Auto Scaling Groupから除外(Terminating)→インスタンス破棄(Terminating)→破棄完了(Terminated)→削除
となります。
LifeCycleHookはこの「Pending」「Terminating」の状態の時にユーザーが制御処理をフックして独自の処理、例えばソフトウェアのインストールや初期化などを行う機能です。

LifeCycleHookの仕組み

Pending時

pendingaction

LifeCycleHookを使用するには具体的にはどうするのでしょう。まずはPending時の動きを見てみます。
LifeCycleHookを使うには

  • 1.SNSのTopicかSQSのQueueを作る
  • 2.AutoScaling Notification AccessというIAM Roleを作る
  • 3.LifeCycleHookを作る

というステップを踏みます。
LifeCycleHook機能を使うと、インスタンスがPendingになった時に1で作成したSNSやSQSに通知が飛びます。この通知を飛ばすための権限を作っているのが2のIAM Roleの作成なんですね。
通知が飛ぶとLifeCycleはHookされ、状態が「Pending:Wait」という状態になります。ユーザーが何か処理するのを「待つ」という状態ですね。この間にユーザーは初期処理を済ませます。
ユーザーが初期処理を済ませると後に紹介するCompleteLifecycleActionというコマンドをコールします。これによりAuto Scaling Groupはユーザーが処理を済ませた事を知り、状態を「Pending:Proceed」に進めます。後はいつも通り待っていればインスタンスの起動が終了します。
今までは全部入りのAMIを用意したり、User Dataを使用したりして工夫していたAuto Scaling時のデプロイ処理もこの機能を使えば、例えばSNSからの通知を受けてChef Serverをキックするようなワークステーション用のEC2を作っておいてエレガントに自動化、なんてこともできますね!

Terminating時

terminateaction

Terminating時も動きはPending時と変わりません。まずSQSかSNSに向けて通知が行われ、状態が「Terminating:Wait」に変わって「待ち」状態になります。その間にユーザーは終了処理、例えばログを保管したり、何かしらの障害でインスタンスが除外された場合は、その原因を分析したりします。
その後CompleteLifecycleActionをコールして状態を「Termination:Proceed」に動かしてインスタンスを破棄します。

LifeCycleHookのコマンド

LifeCycleHookは現在AWS CLIもしくはAuto Scaling APIから動かすことができます。ではLifeCycleHookに関わる3つのコマンドを見ていきましょう。

PutLifecycleHook

パラメータ

  • AutoScalingGroupName : 対象となるAuto Scaling Group名(必須)
  • DefaultResult : hookがタイムアウト、または障害時の処理(CONTINUE / ABANDON)。デフォルトはABANDON
  • HeartbeatTimeout : Heartbeat(後述)のタイムアウト時間の設定。デフォルトは3600(1時間)
  • LifecycleHookName : LifeCycleHook名(必須)
  • LifecycleTransition : Pending時のhook(autoscaling:EC2_INSTANCE_LAUNCHING)かTerminating時のhook(autoscaling:EC2_INSTANCE_TERMINATING)か
    ※新規登録時は必須。アップデート時にはオプション。
  • NotificationMetadata : hookの通知時に送りたいメタデータ
  • NotificationTargetARN : 通知用のSNS/SQSのARN
    ※新規登録時は必須。アップデート時にはオプション。
  • RoleARN : 通知に使うIAM RoleのARN
    ※新規登録時は必須。アップデート時にはオプション。

まずLifeCycleHookのコアとなるコマンド、PutLifecycleHookです。上にあった「3.LifeCycleHookを作る。」は具体的にはこのコマンドをコールすることを言います。
Heartbeatについて説明します。LifeCycleHookが作成されて状態がWaitになるのは60分間です。60分を過ぎるとDefaultResultで指定された方法に従って破棄されるか、起動されるか自動的に選択されます。初期処理が60分に収まらない場合には後述するRecordLifecycleActionHeartbeatコマンドをコールして待ち時間を延長します。HeartbeatTimeoutとは、その延長する待ち時間をどれくらいにするかを指定するものです。

CompleteLifecycleAction

パラメータ

  • AutoScalingGroupName : 対象となるAuto Scaling Group名(必須)
  • LifecycleActionResult : コール後のインスタンスの処理(CONTINUE / ABANDON)。(必須)
  • LifecycleActionToken : hookがSNS/SQSに通知した際に入っているUUID。同じ名前で入ってくる。(必須)
  • LifecycleHookName : LifeCycleHook名(必須)

CompleteLifecycleActionはユーザーが初期処理/終了処理が終わった際にLifeCycleHookに対して「終わったよ―」とお知らせして、対象インスタンスの状態をProceedに進めてもらうためにコールするコマンドです。
ここで重要なのはLifecycleActionTokenです。上にあるPutLifecycleHookでhookを作ると、Auto ScalingにPending状態、またはTerminating状態のインスタンスが出来るとARNを登録してあるSNS/SQSに通知が飛びます。例えばSNSのTopicをメール通知にしているとメールが飛んでくるわけです。LifecycleActionTokenはそのメールの文面やTopicに入っているUUIDのことなのです。 
ここにはその通知先に書かれているUUIDを指定することで、どのhookでPending:Wait/Terminating:Waitが起きたかを特定します。

RecordLifecycleActionHeartbeat

パラメータ

  • AutoScalingGroupName : 対象となるAuto Scaling Group名(必須)
  • LifecycleActionToken : hookがSNS/SQSに通知した際に入っているUUID。同じ名前で入ってくる。(必須)
  • LifecycleHookName : LifeCycleHook名(必須)

RecordLifecycleActionHeartbeatはPutLifecycleHookで説明した60分の待機時間では間に合わない場合に更にタイムアウトを延ばすためのアクションです。Auto Scaling Group、通知されたUUID、対象のLifeCycleHook名がパラメータです。UUIDが必要だ、ということは順番的にはPutLifecycleHookを叩いてレスポンスが返って来てから叩く、ということですね。

やってみよう

では実際にやってみたいと思います。手順が色々あるので、順を追って1つずつご紹介致しますね。

Auto Scaling Groupを作る

ここは至って普通です。デフォルトとしてAZ-a,AZ-cに1台ずつ作ります。

createAutoScalingGroup

SNSのTopicを作る

次にhookを通知するSNSを作ります。これはSQSのqueueでも構いません。今回は簡単にメール通知させたいと思います。

hookNotification

後で使うので作ったらARNを確認しておきましょう。

IAM Roleを作る

SNSへのアクセスができる権限を持ったIAM Roleを作ります。名前はなんでも良いのですが今回は「notificationAccessRole」としました。
ポイントはサービスとして「AutoScaling Notification Access」というサービスを選ぶことです。

notificationAccess

IAM Roleを作った後は、こちらも後で使うのでARNを確認しておきます。

IAM_ARN

PutLifecycleHookでLifeCycleHookを作る

いよいよ本命、LifeCycleHookを作ります。今回はAWS CLIから PutLifecycleHookコマンドを叩きます。

aws autoscaling put-lifecycle-hook \
> --lifecycle-hook-name hookTest \
> --auto-scaling-group-name autoscaling \
> --lifecycle-transition autoscaling:EC2_INSTANCE_LAUNCHING \
> --notification-target-arn arn:aws:sns:ap-northeast-1:887464593869:notificationHookTest \
> --role-arn arn:aws:iam::887464593869:role/notificationAccessRole

Auto Scaleさせてみる

次にAuto Scaleさせてみます。Auto Scaling Groupからmaxを8に、desireを4に変更します。

editAutoScalingGroup

そうするとAuto Scaleが開始します。LifeCycleHookが効いているとここでnotificationが飛んできます。今回はメールを設定したのでメールが飛んでくることになります。

notificationMail

このメールのLifecycleActionTokenを後で使うわけです。

インスタンスの状態を見てみましょう。

pending_wait

「Pending:Wait」になっている事が確認できますでしょうか。この状態でInstances上はrunningになっているのでSSH接続ができます。Chef等で初期設定をしてみましょう。

初期設定が終わったらcomplete-lifecycle-actionでPendingの状態を進めます。

aws autoscaling complete-lifecycle-action \
> --lifecycle-hook-name hookTest \
> --auto-scaling-group-name autoscaling \
> --lifecycle-action-token b6a9c4c7-d249-4247-8e4a-f4ee26ff5946 \
> --lifecycle-action-result CONTINUE

インスタンスの状態を見てみましょう。コマンドを流した1つのインスタンスの状態が「Pending:Proceed」に進みました。このまま少し待っていると「InService」に進みます。

pending_proceed

ちなみにもう一つのインスタンスのlifecycle-action-resultをABANDONにするとインスタンスの状態は「Terminating」になります。

terminating

Heartbeatさせてみる

最後にHeartbeatを登録してみます。

aws autoscaling record-lifecycle-action-heartbeat \
> --auto-scaling-group-name autoscaling \
> --lifecycle-action-token 21d9dc8e-1db4-4982-a636-1e3d7f88f4d4 \
> --lifecycle-hook-name hookTest

これで60分過ぎても延長されます。

まとめ

いかがでしたか。思ったより書くことが多くて長くなってしまいました。ここまで読んで頂いてありがとうございます。
計画的にAuto Scaleさせたり拡張時のログを縮退前に取得する時に是非お使いください。