【AWS】Auto Scalingまとめ


どうも、iron千葉です。
Auto Scalingについて、ユーザガイドを見てポイントをまとめました。
ポイントだけ確認したい人、ざっと全体を見たい人におすすめです。

# Auto Scalingとは
* インスタンスの数を自動で増減できる
* インスタンスの数は最少、最大を指定する
* 増減のトリガーはCloudWatchのメトリックスを指定できる
* 増減のトリガーは時間を指定できる

# Auto Scalingのコンポーネント
* Auto Scaling Groups
    * オートスケール対象のEC2インスタンスグループの管理単位
    * EC2インスタンスの最少数、最大数、希望する数を指定
* Launch Configurations
    * Auto Scaling時に起動するEC2インスタンスを定義する
    * AMI ID、インスタンスタイプ、ディスクサイズ、キーペア、セキュリティグループ等を指定（EC2インスタンス作成に指定する項目とニアイコール）
* スケーリングプラン
    * Auto Scalingをいつ、どのタイミングで実施するかの条件を指定
    * CloudWatchメトリックス（CPU使用率等）、スケジュール、現在のインスタンス数を維持、手動でのスケーリングでの指定が可能

# Auto Scalingの利用効果
* 耐障害性の向上。インスタンス異常時を検出し、インスタンスを終了、新しいインスタンスを起動できる
* 可用性の向上。複数のAZでAuto Scalingを設定することにより、１つのAZが利用できなくなっても別AZで新しいインスタンスを起動できる
* コスト効率の向上。EC2インスタンスをオンデマンドで必要な時に、必要なだけを自動で追加・削除できる。リソースが不要な期間はリソースを利用しないことにより、コスト効率が向上する。※オンプレミスでは、ピーク時に合わせたリソースを用意する必要がありましたが、AWSはピーク時リソースを自動で増やすことができます。

# Auto ScalingでのAZ分散方式
* AZで均等にインスタンスを配置できる（偏らない）、地理的冗長化
* Auto Scalingの挙動
    * インスタンスが最も少ないAZでインスタンスを起動する
    * インスタンス起動が失敗した場合は、起動が成功するまで別AZで起動する
* Auto Scalingグループのバランスが崩れた場合（不均等）の挙動
    * 再分散のトリガー
        * グループのAZを変更
        * グループが不均等になった原因のインスタンスを停止
        * リソースが不足していた（インスタンスを起動できるリソースない）AZが利用できるようになった
    * 再分散時にの挙動
        * アプリのパフォーマンスの低下が発生しないように、古いインスタンスを終了する前に新しいインスタンスを起動する
        * Auto Scaleで指定した最大容量に近づくと、再分散の処理が遅くなったり、完全に停止する可能性がある
        * この問題を回避するために、一時的に最大容量を増やす（最大容量の10%または+1）

# Auto Scalingのライフサイクル
* Auto Scaling Group作成
* CloudWatchまたはスケジュールをトリガーにスケールアウト
* Launch Configurationsでしたインスタンスを起動
* Auto Scaling groupにインスタンスをアタッチ
* CloudWatchまたはスケジュールをトリガーにスケールイン
* Auto Scaling groupの中のインスタンスをターミネート
* Auto Scaling groupからデタッチ
* ステータスの遷移
    * Pending State：インスタンス作成中
    * InService State：グループにインスタンスを追加（利用できる状態
    * Terminating State：インスタンス削除中
    * Terminated State：インスタンス削除完了

# ユーザアクションの実行（インスタンス追加時）
* インスタンス起動（Pending） → インスタンス起動完了（Pending Wait） → ユーザアクション → ユーザアクション完了（Pending Proceed）
* 上記のユーザアクションで、インスタンスへのソフトウェアのインストール、アプリのデプロイ等を行える

# ユーザアクションの実行（インスタンス終了時）
* ヘルスチェック失敗（Terminating） → インスタンス削除待ち（Terminating Wait） → ユーザアクション → ユーザアクション完了（Terminating Proceed） → インスタンス削除完了（Terminated）
* 上記のユーザアクションで、インスタンスを分析、ログ採取などを行える

# Auto ScalingでのInService状態が別ステートになるタイミング
* スケールイベントが発生し、グループのサイズが減少する
* ユーザーがインスタンスをStandby状態にする
* ユーザがグループからインスタンスをデタッチする
* インスタンスのヘルスチェックに失敗（Unhelty状態になる）

# Auto Scalingの設計考慮ポイント
* サーバの起動と設定に要する時間を確認→スケール時にかかる時間を考慮した閾値を設定する
* どのメトリクスをスケールのトリガーとするか、CPU使用率？それともスケジュール？緊急時は手動での対応？
* どのインスタンスをAuto Scalingグループにの対象にするするか？既存インスタンス？既存AMI？それとも新規作成？
* 高可用性として複数AZ配置する
* Auto Scaling利用の目的は、キャパシティを増やすのか、常に一定の台数を確保（オートヒーリング）なのか？
* スケールするインスタンスをどうやって最新に保つか（アプリの自動デプロイ、自動パッケージアップデート）

# 複数のスケーリングポリシーの適用
* 通常スケールアウトとスケールインの２つのポリシーを適用することを推奨
* 複数のポリシーで同時にスケールアウトが実施された場合、影響が大きい（スケールアウトする数が多い方）が優先される
* 例えばCPU使用率80%以上の場合インスタンスを１つ増やす、SQSのキューが一定上の場合インスタンスを２つ増やすというポリシーが同時に発動した場合はSQSのポリシーが適用され、インスタンスが２つ追加される

# クールダウン
* 新しいインスタンスが追加されるまでの待ち時間（新しいインスタンスの処理が開始されるまでの待ち時間）
* なぜクールダウンが必要か？
    * 例えば、新しいインスタンスが起動して処理を開始するまでに2分かかるとする。
    * CPUが80%を超えたため新しいインスタンスが追加される
    * しかしクールダウンがない場合、インスタンス追加後2分は処理が開始できないためCPUが80%を超えた状態が2分以上続く
    * 80%を超えているためインスタンスがさらに追加される
    * ここでクールダウンを3分とすると、スケール後3分はスケールしない時間となる
    * 3分後にCPUが80%以下だとスケールしない。依然80%だったらスケールする
* クールダウンの種類
    * デフォルトのクールダウン：Auto Scalingグループ作成時に指定（全体に適用される）
    * スケーリング固有のクールダウン：スケーリングポリーに個別に指定する
    * 例へば、スケールアウトとスケールインを別々にしたい場合は固有のクールダウンを設定する（デフォルトのクールダウンを上書き）
* 複数のインスタンスが起動する場合は、最後のインスタンスの起動後にクールダウンが開始される
* ユーザアクション中は、スケールアウトが中断される。また、ユーザーアクション完了後にクールダウンが適用される
* スポットインスタンスの場合は、入札が成功後にクールダウンが適用される

# Auto Scalingグループの終了ポリシー
* スケールインする最初のインスタンス（終了させるインスタンス）を指定できる
* デフォルトの終了ポリシー(AZに均一に配置されるように設定されている)
    * 削除対象のAZを選択
        * 複数のAZにインスタンスがあるか確認
        * 一番多いインスタンスが配置されているAZのインスタンスを削除
        * 全AZで同数のインスタンスが配置されている場合は、ランダムでAZを選択
    * AZの中で削除するインスタンスを選択
        * Launch Configurationが一番古いインスタンスを削除
        * 古いLaunch Configurationインスタンスが複数ある場合は、次の課金発生が短いインスタンスを削除
        * 次の課金時間に近いインスタンスが複数ある場合は、ランダムで削除
* 終了ポリシーのカスタマイズ
    * カスタムポリシーの挙動
        * 複数のAZのインスタンス数を確認
        * インスタンス数が一番多いAZを選択
        * 選択したAZのカスタムポリシーに従い削除
        * AZで数が均一の場合は、カスタムポリシーに従い削除
    * カスタムポリシーの種類
        * OldestInstance：一番作成日が古いインスタンスを削除
        * NewestInstance：一番作成日が新しいインスタンスを削除
        * OldestLaunchConfiguration：一番古いLaunch Configurationのインスタンスを削除
        * ClosestToNextInstanceHour：次の課金が最も短いインスタンスを削除
        * デフォルト

# インスタンス数の固定
* Auto Scalingグループを作成すると、指定した最小のインスタンス数で起動
* スケーリング条件が指定されない場合、常にこのインスタンス数を維持する
* インスタンスのヘルスチェック
    * インスタンスのヘルスチェック（起動状態：running以外の場合異常、システムステータス：impairedの場合異常）
    * ELB利用時は、インスタンスヘルスチェクに加えてELBでのヘルスチェックにて確認される
    * ヘルスチェックを独自にカスタマイズできる
* 異常が発生したインスタンスの置き換え
    * ヘルスチェックが失敗を検知すると、新しいインスタンスが追加される
    * ヘルスチェックに失敗したサーバが自動的に正常となることはない
    * SetInstanceHealthで手動で正常にできるが、インスタンスが終了している場合はエラーがかえる
    * EIP、EBSは新しいインスタンスに手動でアタッチする必要がある
　
# 手動スケーリング
* 手動でインスタンス数を変える場合は、Desiredの値を変更する

# 動的スケーリング
## スケーリングポリシー
* スケーリングポリシーに設定した数だけ、スケール時にインスタンス数が変更される
* インスタンスの増減は、数または数の割合で指定
* スケーリングポリシー作成時に指定する項目
    * ポリシー名
    * 関連付けをするAuto Scaling groupの名前
    * スケールするインスタンス数
    * 調整タイプ
* 調整タイプには以下のものがある
    * ChangeInCapacity：既存の容量を増減する。現在の容量3でChangeInCapacityを5でポリシーを作成すると3+5で8インスタンスとなる
    * ExactCapacity：指定した値に現在の容量を変更。現在の容量3でExactCapacityを5でポリシーを作成すると5インスタンスとなる
    * PercentChangeInCapacity：割合で容量を増減。現在の容量10でPercentChangeInCapacityを10(10%の意味)でポリシーを作成すると11インスタンスとなる
        * 12.7の場合は12
        * 0から1の間の場合は、1
        * 0から-1の間の場合は、-1
        * -6.67は-6
* アラーム作成時にスケーリングポリシーを関連付ける
* 動的スケーリング設定の大きな流れ
    * Launch Configurationを行い、スケール時に起動するインスタンスの設定を行う
    * 最大値、最小値、現在のインスタンス数(Desire)を定義し、Auto Scalingグループを作成
    * CloudWatchアラームを作成
    * スケールアウト、スケールインのポリシーを作成し、ポリシーをアラームに関連付ける
    * スケーリングポリシーをAuto Scalingグループに関連付ける

## スケーリングのトリガー
    * CloudWatchのアラーム
    * スケジューリング（１回のみ、または定期的なスケジュールを設定可能）※マネジメントコンソールで設定不可。CLIから設定する
    * SQSに基づくスケーリング

# ライフサイクルフックの導入
* インスタンス起動→フックアクション→グループ追加。フックアクションの例
    * ソフトのインストール
    * EBS作成、初期化、アタッチ
    * メッセージキューへの接続
* グループから削除→フックアクション→インスタンス削除。フックアクションの例
    * EBSスナップショットの実行
    * ログをS3へ退避
    * インスタンスのデバッグ
* フックアクション時の動作（CLIからの操作のみ）
    * ライフサイクルフックを作成し、グループに割り当てる
    * フックアクション時にSNSまたはSQSへPending:WaitまたはTerminating:Waitが通知される→アプリ側処理を開始
    * PendingまたはTerminatingに入った場合、アプリケーションには処理時間として60分与えられる（デフォルト）
    * 60分を超える場合は、アプリ側でハートビートを発行することにより、処理時間を延長できる
    * （所定の処理時間を超過した場合は、インスタンスが削除される（デフォルト））
    * フック処理完了時に、アプリケーションで「CompleteLifecycleAction」を発行し、ELB側に処理を戻す
* 注意事項
    * Pending:WaitまたはTerminating:Wait中は、スケーリングアクションが中断される
    * Pending:WaitまたはTerminating:Wait後に、さらにクールダウン期間待つ
    * スケールが開始されるタイミングに遅延が発生しないように考慮する

* Abandon または Continue
* インスタンスの準備が完了したときに、CompleteLifecycleActionにAbandon または Continueを指定できる
* Abandonを指定した場合は、フックアクションが失敗とみなして
    * スケールアウト時は、インスタンスを削除し、再度作成処理が走る
    * スケールイン時は、残りのアクション（他のライフサイクルフック等）を停止し、インスタンスを直ち停止する

# Auto Scalingグループのインスタンスへのタグ付け
* プロジェクトや、どのAuto Scalingグループインスタンスなのかを判別するためにインスタンスにタグをつけられる

# Auto Scaling グループでのスポットインスタンス
* アプリケーションを実行する時間に柔軟性がある。またはアプリケーションを中断できる場合はスポットインスタンスを利用できる
* スポットインスタンス利用時のポイント
    * 入札価格を設定する：Launch Configurationでスポットインスタンスを指定します（オンデマンドとスポットインスタンスを両方指定できない）
    * 入札価格を変更する：新しい入札価格でLaunch Configurationを再作成
    * インスタンスの終了：入札価格がスポットインスタンス市場価格を上回るとインスタンスは終了します
    * スポットインスタンスの維持：Auto Scalingは希望の容量を維持するために、インスタンス起動を試行し続ける。入札価格が市場価格を上回った場合は起動が行われる。市場価格を下回る場合は、何度も起動を試みる

# Auto Scalingグループの利用方法

## Auto Scaling グループのロードバランシング
* Auto ScalingグループのインスタンスをELBでバランシングする(他のロードバランサと連携も可能)
* Auto Scalingで追加・削除されるインスタンスを、ELBに自動でアタッチ・デタッチできる
* 利用方法
    * ELBを作成
    * Auto ScalingグループにELBを登録
* 1つのAuto Scalingグループに複数のELBを登録できる
* ELBのメトリックス（リクエストレイテンシーやリクエスト数など）をスケールのトリガーにできる
* デフォルトでは、EC2インスタンスのヘルスチェックを実施する
* ELBを利用する場合は、ELBからのインスタンスヘルスチェックも利用できる
* Connection Drainingを有効にすることで、実行中のリクエストが完了するか最大制限時によって、スケールイベントを実施できる（利用中のユーザの操作に影響しないようにできる）
* EC2インスタンスをAZ配置を均等に分散できる

## Auto Scaling グループに既存のインスタンスをアタッチ
* EC2インスタンスを起動し、設定してからAuto Scalingグループに追加できる。特にテストする場合に便利

## Auto Scaling グループのインスタンスをデタッチ
* グループの中のインスタンスをAuto Scalingグループから外せる。別のAuto Scalingグループへの移動、不要なインスタンスを外す場合に便利

## 複数のアベイラビリティーゾーンの Auto Scaling グループをマージ
* 複数のAuto Scalingグループを、1つのAuto Scalingグループにマージする

## 一時的に Auto Scaling グループからインスタンスを削除
* 稼働状態になっているインスタンスをスタンバイ状態に移行できる
* スタンバイ状態のインスタンスは、Auto Scalingグループの一部として動作する
* スタンバイ状態のインスタンスは、アプリケーショントラフィックを処理しない（ELBから切り離される）
* 例用例：インスタンスのトラブルシューティング時にスタンバイ状態にして調査する
* インスタンスを Standby 状態にする場合は、Auto Scalingで代わりのインスタンスを起動するかどうかを設定する
    * 代わりのインスタンスを起動させない場合：希望する容量減らしてから、インスタンスをスタンバイへ変更する。組み込むときは、希望する容量を増やしてから追加する。
    * 代わりのインスタンスを起動させる場合：希望する容量減らしてから、インスタンスをスタンバイへ変更する
* Auto Scalingグループのインスタンスを更新(パッチ適用等)する
    * 対象のインスタンスをスタンバイ状態にする
    * インスタンスを更新する
    * インサービスを状態にする

## Auto Scaling グループを停止してから再開する
* Auto Scalingグループを一時的に停止できる。停止→調査・復旧→再開のような使い方ができる
* 起動を繰り返し実施し、24時間失敗し続けると、Amazon側で停止を行う場合がある。管理上の理由より。

## Auto Scaling グループをシャットダウンする
* Auto Scalingグループの削除→グループの中に実行中のインスタンスが存在しないこと
* 起動設定の削除
* ロードバランサーの削除
* CloudWatchアラームの削除

# Auto Scaling インスタンスのモニタリング
* SNSを登録し、Auto Scalingグループ変更時（インスタンス追加・削除等）の通知を得られる
* CloudTrailでAPI呼び出しの監査を行える

# Auto Scaling のトラブルシューティング
* コマンドラインまたはAPIにて、エラーメッセージを取得できる