2016年8月6日土曜日

[AWS] SNS(SQS) を使用せずに AutoScaling のライフサイクルフックを使う


AutoScaling でスケールインするとき、ライフサイクルフックを試してターミネートを制御してみます。

面倒なので、今回は、SNSやSQSを使用しません。


1.AutoScalingグループを用意する


AWSコンソールで作成し、用意したAutoScalingグループは以下のとおり。
この時点では、EC2インスタンスは 0 にしています。あとは、ほとんどデフォルト設定です。
[root@localhost ~]# aws autoscaling describe-auto-scaling-groups  --auto-scaling-group-name WebGroup
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|                                                                        DescribeAutoScalingGroups                                                                       |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
||                                                                           AutoScalingGroups                                                                          ||
|+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+|
||  AutoScalingGroupARN             |  arn:aws:autoscaling:us-east-1:xxx:autoScalingGroupName/WebGroup                                                                  ||
||  AutoScalingGroupName            |  WebGroup                                                                                                                         ||
||  CreatedTime                     |  2016-07-23T23:55:45.798Z                                                                                                         ||
||  DefaultCooldown                 |  300                                                                                                                              ||
||  DesiredCapacity                 |  0                                                                                                                                ||
||  HealthCheckGracePeriod          |  300                                                                                                                              ||
||  HealthCheckType                 |  EC2                                                                                                                              ||
||  LaunchConfigurationName         |  web01-002                                                                                                                        ||
||  MaxSize                         |  1                                                                                                                                ||
||  MinSize                         |  0                                                                                                                                ||
||  NewInstancesProtectedFromScaleIn|  False                                                                                                                            ||
||  VPCZoneIdentifier               |  subnet-f528a2ad                                                                                                                  ||
|+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+|
|||                                                                          AvailabilityZones                                                                         |||
||+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+||
|||  us-east-1b                                                                                                                                                        |||
||+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+||
|||                                                                                Tags                                                                                |||
||+-------------------------------------------------------------------------------+------------------------------------------------------------------------------------+||
|||  Key                                                                          |  Name                                                                              |||
|||  PropagateAtLaunch                                                            |  True                                                                              |||
|||  ResourceId                                                                   |  WebGroup                                                                          |||
|||  ResourceType                                                                 |  auto-scaling-group                                                                |||
|||  Value                                                                        |  WebGroup                                                                          |||
||+-------------------------------------------------------------------------------+------------------------------------------------------------------------------------+||
|||                                                                         TerminationPolicies                                                                        |||
||+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+||
|||  Default                                                                                                                                                           |||
||+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+||


2.ライフサイクルフックを作成する


スケールイン用のライフサイクルフックを作成して、パラメータを確認します。
[root@localhost ~]# aws autoscaling put-lifecycle-hook --lifecycle-hook-name terminate-hook --auto-scaling-group-name WebGroup --lifecycle-transition autoscaling:EC2_INSTANCE_TERMINATING
[root@localhost ~]# aws autoscaling describe-lifecycle-hooks --auto-scaling-group-name WebGroup
-----------------------------------------------------------------------------------------------------------------------------------------------
|                                                           DescribeLifecycleHooks                                                            |
+---------------------------------------------------------------------------------------------------------------------------------------------+
||                                                              LifecycleHooks                                                               ||
|+----------------------+----------------+----------------+-------------------+--------------------+-----------------------------------------+|
|| AutoScalingGroupName | DefaultResult  | GlobalTimeout  | HeartbeatTimeout  | LifecycleHookName  |           LifecycleTransition           ||
|+----------------------+----------------+----------------+-------------------+--------------------+-----------------------------------------+|
||  WebGroup            |  ABANDON       |  172800        |  3600             |  terminate-hook    |  autoscaling:EC2_INSTANCE_TERMINATING   ||
|+----------------------+----------------+----------------+-------------------+--------------------+-----------------------------------------+|

ちなみに、ライフサイクルフックを削除したい場合は、以下のコマンドです。
aws autoscaling delete-lifecycle-hook --lifecycle-hook-name terminate-hook --auto-scaling-group-name WebGroup


3.ライフサイクルフックの動作確認


これで、ライフサイクルフックが使えます。
スケールインしたときに、ターミネートが止まるか確認してみます。

まず、スケールアウトしてEC2インスタンスを1台起動します。
[root@localhost ~]# aws autoscaling update-auto-scaling-group --auto-scaling-group-name WebGroup --desired-capacity 1 --min-size 1

アクティビティ履歴で、起動完了を確認します。 "i-15c9ff85" が起動されたEC2インスタンスです。
[root@localhost ~]# aws autoscaling describe-scaling-activities --auto-scaling-group-name WebGroup --query "Activities[].[StartTime,Description,StatusCode]"
----------------------------------------------------------------------------------------
|                               DescribeScalingActivities                              |
+---------------------------+--------------------------------------------+-------------+
|  2016-08-06T03:28:36.720Z |  Launching a new EC2 instance: i-15c9ff85  |  Successful |
|  2016-08-06T02:56:34.931Z |  Terminating EC2 instance: i-96dbed06      |  Successful |
|  2016-08-06T02:55:07.365Z |  Launching a new EC2 instance: i-96dbed06  |  Successful |
|  2016-08-06T02:38:21.331Z |  Terminating EC2 instance: i-e7d4e277      |  Successful |
|  2016-08-06T02:33:56.376Z |  Launching a new EC2 instance: i-e7d4e277  |  Successful |
|  2016-07-24T00:08:09.846Z |  Terminating EC2 instance: i-f80d4868      |  Successful |
|  2016-07-24T00:04:38.938Z |  Launching a new EC2 instance: i-f80d4868  |  Successful |
|  2016-07-24T00:04:06.533Z |  Terminating EC2 instance: i-40c5bfd0      |  Successful |
|  2016-07-23T23:56:02.592Z |  Launching a new EC2 instance: i-40c5bfd0  |  Successful |
+---------------------------+--------------------------------------------+-------------+

こんどは、スケールインしてみます。
[root@localhost ~]# aws autoscaling update-auto-scaling-group --auto-scaling-group-name WebGroup --desired-capacity 0 --min-size 0

しばらくして、アクティビティ履歴を確認すると、スケールインしたEC2インスタンスが、"MidTerminatingLifecycleAction" と表示されています。
この表示になったときには、ライフサイクルフックでターミネートが一時停止しています。
[root@localhost ~]# aws autoscaling describe-scaling-activities --auto-scaling-group-name WebGroup --query "Activities[].[StartTime,Description,StatusCode]"
-----------------------------------------------------------------------------------------------------------
|                                        DescribeScalingActivities                                        |
+--------------------------+--------------------------------------------+---------------------------------+
|  2016-08-06T03:36:57.926Z|  Terminating EC2 instance: i-15c9ff85      |  MidTerminatingLifecycleAction  |
|  2016-08-06T03:28:36.720Z|  Launching a new EC2 instance: i-15c9ff85  |  Successful                     |
|  2016-08-06T02:56:34.931Z|  Terminating EC2 instance: i-96dbed06      |  Successful                     |
|  2016-08-06T02:55:07.365Z|  Launching a new EC2 instance: i-96dbed06  |  Successful                     |
|  2016-08-06T02:38:21.331Z|  Terminating EC2 instance: i-e7d4e277      |  Successful                     |
|  2016-08-06T02:33:56.376Z|  Launching a new EC2 instance: i-e7d4e277  |  Successful                     |
|  2016-07-24T00:08:09.846Z|  Terminating EC2 instance: i-f80d4868      |  Successful                     |
|  2016-07-24T00:04:38.938Z|  Launching a new EC2 instance: i-f80d4868  |  Successful                     |
|  2016-07-24T00:04:06.533Z|  Terminating EC2 instance: i-40c5bfd0      |  Successful                     |
|  2016-07-23T23:56:02.592Z|  Launching a new EC2 instance: i-40c5bfd0  |  Successful                     |
+--------------------------+--------------------------------------------+---------------------------------+

このまま放置すると、デフォルトでは60分でタイムアウトして、ターミネートの一時停止が解除されます。

タイムアウトを待たずに、解除したい場合は、インスタンスIDを指定して、以下のコマンドを実行します。
[root@localhost ~]# aws autoscaling complete-lifecycle-action --lifecycle-hook-name terminate-hook --auto-scaling-group-name WebGroup --lifecycle-action-result CONTINUE --instance-id i-15c9ff85

ターミネートの一時停止を解除してから、しばらくして、アクティビティ履歴を確認すると、ターミネートが完了しているのがわかります。
[root@localhost ~]# aws autoscaling describe-scaling-activities --auto-scaling-group-name WebGroup --query "Activities[].[StartTime,Description,StatusCode]"
----------------------------------------------------------------------------------------
|                               DescribeScalingActivities                              |
+---------------------------+--------------------------------------------+-------------+
|  2016-08-06T03:36:57.926Z |  Terminating EC2 instance: i-15c9ff85      |  Successful |
|  2016-08-06T03:28:36.720Z |  Launching a new EC2 instance: i-15c9ff85  |  Successful |
|  2016-08-06T02:56:34.931Z |  Terminating EC2 instance: i-96dbed06      |  Successful |
|  2016-08-06T02:55:07.365Z |  Launching a new EC2 instance: i-96dbed06  |  Successful |
|  2016-08-06T02:38:21.331Z |  Terminating EC2 instance: i-e7d4e277      |  Successful |
|  2016-08-06T02:33:56.376Z |  Launching a new EC2 instance: i-e7d4e277  |  Successful |
|  2016-07-24T00:08:09.846Z |  Terminating EC2 instance: i-f80d4868      |  Successful |
|  2016-07-24T00:04:38.938Z |  Launching a new EC2 instance: i-f80d4868  |  Successful |
|  2016-07-24T00:04:06.533Z |  Terminating EC2 instance: i-40c5bfd0      |  Successful |
|  2016-07-23T23:56:02.592Z |  Launching a new EC2 instance: i-40c5bfd0  |  Successful |
+---------------------------+--------------------------------------------+-------------+

ライフサイクルフックで、ターミネートが一時停止するのは、OSがシャットダウンする前です。
なので、SSHでログインできるし、crontab も動いてます。

小規模環境で、SNS(SQS)をつかわず、手軽にライフサイクルフックを使用したい場合もあります。

crontab で定期的に「アクティビティ履歴」をチェックするスクリプトを、AutoScalingで使用するAMIに仕込んでおけば、スケールイン時にライフサイクルフックの発動を検知して「終了処理」を実行し、「終了処理」が完了してから、ターミネートを続行させることができます。