
Auto ScalingのTermination Policyを使いこなそう
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、虎塚です。
先日、「Auto Scalingがスケールインする時には、最も古いインスタンスから削除されますよね?」というお問合せをいただきました。じつは、スケールイン時にどのインスタンスが終了されるかは、Auto ScalingのTermination Policyをどのように設定したかによって変わります。
今回は、Termination Protectionの種類と動作についてご紹介します。
Auto ScalingのTermination Policyとは
Termination Policyとは、Auto Scalingでスケールインが発生した時に、どのインスタンスを終了させるかを決めるものです。Termination Policyを明示的に指定しない場合は、デフォルトのTermination Policyが使われます。
どのインスタンスを残して、どのインスタンスを消すかは、スケールアウト/スケールインの利用目的によって異なります。Termination Policyを使うと、終了させるインスタンスを柔軟に選定できるので、Auto Scalingをさらに便利に使えるでしょう。
デフォルトのTermination Policy
デフォルトのTermination Policyで終了するインスタンスがどのように選ばれるかを、次の図に示します。

- インスタンスが複数のAvailability Zone (以下、AZ) にある場合、より多くのインスタンスがあり、スケールインから保護されていないインスタンス1が1個以上あるAZを選びます。もし当てはまるAZが複数あったり、インスタンスが単独のAZにあったりする場合は、最も古いLaunch Configurationを使用しているインスタンスがあるAZを選びます。
- 1で選んだAZの中で、スケールインから保護されていなくて、最も古いLaunch Configurationを使用しているインスタンスが1個かを確認します。もしそうなら、そのインスタンスを終了します。
- スケールインから保護されていなくて、最も古いLaunch Configurationを使用しているインスタンスが複数ある場合は、次回の請求時間に最も近いインスタンスを選びます(この方針で選択した場合、ユーザのインスタンス使用期間を最大化しつつ、請求対象になる利用時間を最小化できます)。当てはまるインスタンスが1個であれば、そのインスタンスを終了します。
- スケールインから保護されていなくて、最も古いLaunch Configurationを使用していて、かつ次の請求開始時間まで最も近いインスタンスが2個以上ある場合は、ランダムに1個のインスタンスを終了します。
カスタムのTermination Policy
サポートされているTermination Policyを、AWS CLIで取得できます。
aws autoscaling describe-termination-policy-types
{
    "TerminationPolicyTypes": [
        "ClosestToNextInstanceHour",
        "Default",
        "NewestInstance",
        "OldestInstance",
        "OldestLaunchConfiguration"
    ]
}
上の実行結果は、2016年7月7日時点のものです。それぞれのTermination Policyの詳細を次の表に示します。
| ポリシー | 振る舞い | どんな時に便利か | 
|---|---|---|
| OldestInstance | 最も古いインスタンスを終了する | インスタンスタイプを変更する時 | 
| NewestInstance | 最も新しいインスタンスを終了する | 新しいlaunch configurationをテストしたい(が本番環境として使い続けたくはない)時 | 
| OldestLaunchConfiguration | 最も古いlaunch configurationを使用しているインスタンスを終了する | Auto Scaling groupをアップデートして、以前のlaunch configurationを利用するインスタンスを置き換えたい時 | 
| ClosestToNextInstanceHour | 次の請求時間に最も近いインスタンスを終了する | インスタンスの利用量を最大化しつつコストを抑えたい時 | 
| Default | 上の図を参照 | Auto Scaling groupに1個以上のスケーリングポリシーを関連づけている時 | 
カスタムTermination Policyを使用した場合も、最初に評価されるのはAZ間の均衡であることに注意してください。ほかのAZよりもインスタンス数が多いAZがある場合、カスタムのTermination Policyは、まずそのAZに対して適用されます。
実験: インスタンス数が均衡/不均衡な状態でNewestInstanceポリシーを適用
少し長くなりますが、カスタムTermination Policyを適用した時の動作を確認してみましょう。
1. Launch Configurationの作成
t2.microのAmazon Linuxを起動するLaunch Configuration (lc20160707) を作成します。
aws autoscaling create-launch-configuration --cli-input-json file://lc20160707.json
{
    "LaunchConfigurationName": "lc20160707",
    "ImageId": "ami-374db956",
    "KeyName": "sample-key",
    "SecurityGroups": [
        "sg-00000000", "sg-11111111"
    ],
    "InstanceType": "t2.micro",
    "BlockDeviceMappings": [
        {
            "DeviceName": "/dev/xvda",
            "Ebs": {
                "VolumeSize": 8,
                "VolumeType": "gp2",
                "DeleteOnTermination": true
            }
        }
    ],
    "InstanceMonitoring": {
        "Enabled": false
    },
    "IamInstanceProfile": "sample-role",
    "EbsOptimized": false,
    "AssociatePublicIpAddress": true
}
2. Auto Scaling groupの作成
ステップ1で作成したLaunch Configurationを使って、VPC内で最大3台・最小3台のインスタンスをMuti-AZで起動するAuto Scaling group (asg20160707) を作成します。
aws autoscaling create-auto-scaling-group --cli-input-json file://asg20160707.json
{
    "AutoScalingGroupName": "asg20160707",
    "LaunchConfigurationName": "lc20160707",
    "MinSize": 3,
    "MaxSize": 3,
    "AvailabilityZones": [
        "ap-northeast-1a", "ap-northeast-1c"
    ],
    "HealthCheckType": "EC2",
    "HealthCheckGracePeriod": 180,
    "VPCZoneIdentifier": "subnet-00000000,subnet-11111111",
    "NewInstancesProtectedFromScaleIn": false,
    "Tags": [
        {
            "ResourceId": "asg20160707",
            "ResourceType": "auto-scaling-group",
            "Key": "Name",
            "Value": "termination-policy-test",
            "PropagateAtLaunch": true
        }
    ]
}
上では、Auto Scaling groupを作る際に、Termination Policyを明示的に与えていません。DefaultのTermination Policyが使われていることを確認しておきます。
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names asg20160707 | jq '.AutoScalingGroups[].TerminationPolicies' [ "Default" ]
3. 起動したインスタンスの確認
ステップ2で作ったAuto Scaling group内で、インスタンスが自動的に起動します。起動したインスタンスがどのAZにあるかを確認します。
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names asg20160707 | jq '.AutoScalingGroups[].Instances[] | .AvailabilityZone, .InstanceId' "ap-northeast-1a" "i-0d5f1992" "ap-northeast-1a" "i-0e5f1991" "ap-northeast-1c" "i-91fdc11e"
ap-northeast-1aに2台、ap-northeast-1cに1台のインスタンスがあります。
4. インスタンス1台を入れ替え
以降の検証の準備として、インスタンスが1台だけあるAZで、インスタンスを停止します。
aws ec2 stop-instances --instance-ids i-91fdc11e
Auto Scalingのアクティビティを確認します。
aws autoscaling describe-scaling-activities --auto-scaling-group-name asg20160707 | jq '.Activities[].Description' "Launching a new EC2 instance: i-30fcc0bf" "Terminating EC2 instance: i-91fdc11e" "Launching a new EC2 instance: i-0e5f1991" "Launching a new EC2 instance: i-0d5f1992" "Launching a new EC2 instance: i-91fdc11e"
インスタンス (i-91fdc11e) を停止したためにヘルスチェックが通らなくなり、対象インスタンスがAuto Scalingによって終了されました。代わりに、新しいインスタンス (i-30fcc0bf) が起動しました。
新しいインスタンスがどのAZにあるかを確認します。たった今起動したインスタンスは、インスタンスが1個のAZのほうにあります。
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names asg20160707 | jq '.AutoScalingGroups[].Instances[] | .AvailabilityZone, .InstanceId' "ap-northeast-1c" "i-30fcc0bf" "ap-northeast-1a" "i-0d5f1992" "ap-northeast-1a" "i-0e5f1991"
5. Termination Policyの変更 (Default -> NewestInstance)
Termination PolicyをDefaultからNewestInstanceに変更します。NewestInstanceポリシーは、前掲の表のとおり最も新しいインスタンスを終了対象とします。
Termination Policyを変更するには、Auto Scaling groupをアップデートします。
aws autoscaling update-auto-scaling-group --auto-scaling-group-name asg20160707 --termination-policies "NewestInstance"
新しいカスタムTermination Policyが適用されたことを確認します。
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names asg20160707 | jq '.AutoScalingGroups[].TerminationPolicies' [ "NewestInstance" ]
6. インスタンス数が不均衡な状態でのスケールイン
Auto Scaling groupをシュリンクさせて、どのインスタンスが終了されるかを確認しましょう。
aws autoscaling update-auto-scaling-group --auto-scaling-group-name asg20160707 --min-size 2 --max-size 2
NewestInstanceポリシーを適用したので、ap-northeast-1cの最も新しいインスタンス (i-30fcc0bf) が終了されるのでしょうか?
aws autoscaling describe-scaling-activities --auto-scaling-group-name asg20160707 | jq '.Activities[].Description' "Terminating EC2 instance: i-0d5f1992" "Launching a new EC2 instance: i-30fcc0bf" # ap-northeast-1c "Terminating EC2 instance: i-91fdc11e" "Launching a new EC2 instance: i-0e5f1991" # ap-northeast-1a "Launching a new EC2 instance: i-0d5f1992" # ap-northeast-1a "Launching a new EC2 instance: i-91fdc11e"
もちろん、違います。複数AZ間でインスタンス数が不均衡な状態なので、台数が多いほうのAZ (ap-northeast-1a) で、最も新しいインスタンス (i-0d5f1992) が終了されました。
7. Auto Scaling groupのキャパシティを4に変更
以降の検証にそなえて、Auto Scaling groupを最大4台・最小4台のキャパシティに変更します。
aws autoscaling update-auto-scaling-group --auto-scaling-group-name asg20160707 --min-size 4 --max-size 4
新しいインスタンスが自動的に起動します。Auto Scalingのアクティビティを確認しましょう。
aws autoscaling describe-scaling-activities --auto-scaling-group-name asg20160707 | jq '.Activities[].Description' "Launching a new EC2 instance: i-2d5d1bb2" "Launching a new EC2 instance: i-54fec2db" "Terminating EC2 instance: i-0d5f1992" "Launching a new EC2 instance: i-30fcc0bf" # ap-northeast-1c "Terminating EC2 instance: i-91fdc11e" "Launching a new EC2 instance: i-0e5f1991" # ap-northeast-1a "Launching a new EC2 instance: i-0d5f1992" "Launching a new EC2 instance: i-91fdc11e"
新しく起動したインスタンスとAZの関連を確認しておきます。
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names asg20160707 | jq '.AutoScalingGroups[].Instances[] | .AvailabilityZone, .InstanceId' "ap-northeast-1a" "i-0e5f1991" "ap-northeast-1a" "i-2d5d1bb2" "ap-northeast-1c" "i-30fcc0bf" "ap-northeast-1c" "i-54fec2db"
ap-northeast-1aに2台、ap-northeast-1cに2台、合計4台のインスタンスが起動しています。
8. インスタンス数が均衡している状態でのスケールイン
Auto Scaling groupをふたたび変更して、最大3台・最小3台の設定に戻します。つまり、現在起動しているインスタンスのうち、どれか1台が終了されることになります。
aws autoscaling update-auto-scaling-group --auto-scaling-group-name asg20160707 --min-size 3 --max-size 3
Auto Scalingのアクティビティで、どのインスタンスが終了されたかを確認しますしょう。
aws autoscaling describe-scaling-activities --auto-scaling-group-name asg20160707 | jq '.Activities[].Description' "Terminating EC2 instance: i-2d5d1bb2" "Launching a new EC2 instance: i-2d5d1bb2" # ap-northeast-1a "Launching a new EC2 instance: i-54fec2db" # ap-northeast-1c "Terminating EC2 instance: i-0d5f1992" "Launching a new EC2 instance: i-30fcc0bf" # ap-northeast-1c "Terminating EC2 instance: i-91fdc11e" "Launching a new EC2 instance: i-0e5f1991" # ap-northeast-1a "Launching a new EC2 instance: i-0d5f1992" "Launching a new EC2 instance: i-91fdc11e"
AZ間でインスタンス数が均衡を保っている状態では、NewestInsntanceというポリシー名どおり、最も新しいインスタンス (i-2d5d1bb2) が削除されました。
おわりに
カスタムTermination Policyの表にあるように、それぞれのポリシーには使いどころがあります。目的にあわせてTermination Policyを設定し、Auto Scalingをもっと便利に使いましょう。
それでは、また。











