はじめに
とあるシステムがありました。概要図は下記です。
- ALB: Application Load Balancer
- AP1, AP2: アプリケーションインスタンス
- DB: データベースインスタンス
- ASG: Auto Scaling Group
課題
APインスタンスはASGに含まれていますが、負荷に応じたスケールイン・スケールは行わず、インスタンスの台数の指定のみでした。
これでは従量課金制によるコスト最適化というクラウドのメリットを活かせません。
現状、セッションをAPインスタンスの中に保持しているため、スケールインを行うと、シャットダウンされるインスタンスに割り振られていたユーザは急にログアウトされてしまうことになります。
これはユーザが入力していた内容が消えてしまうことや再ログインの不便に繋がるため許容できません。
また、アプリケーションは別チームが管理しているため、セッションを分離してAPインスタンス外に保存するようにするのとは別に何か方法が無いか調査することにしました。
※一度ログインしたら同じインスタンスにリクエストが割り振られるようにするため、スティッキーセッションを使っています
調べたこと
予想
シャットダウンする前に指定時間待つようにするための、deregistration delayというターゲットグループの機能によって、次のようなことが実現可能なのではと考えました。
- スケールイン対象のインスタンスには、
- 新規セッションを割り当てない
- 既存セッションが切れるくらい待ってからシャットダウンする
- これによって、スケールイン時にセッションが切れることを予防する(一定時間後にログアウトしてしまうのは許容する)
現実
ASGのサイズを手動で増減させて実験を行いました。
その結果、スケールイン対象になったインスタンスには新規セッションだけでなく既存セッションも割り振られないので、スケールインが始まったタイミングで問答無用でログアウトされてしまうということが分かりました。残念
deregistration delayはリクエストを返す前にシャットダウンしてしまってエラーになることを防ぐための機能なので仕方ないですね。
結論
素直にセッションをAPインスタンス外に保存するようにしてからスケールイン・アウトを実装することになりました
ベストプラクティスには従えということですね
おわりに
アドベントカレンダー始まりましたね。去年に引き続きトップバッターを務めました。
去年はポエムっぽい記事でしたが今回は技術記事にしました。
去年の記事↓
参考
図を描く時の参考にしました
おまけ
Auto Scalingによってスケールイン・アウトを実現するときに使えそうなものをメモしたものをこちらにも残しておきます。
誰かの助けになれば幸いです。
料金
- ASG自体は無料
- CloudWatchやEC2インスタンスやロードバランサなどの料金がかかるだけ
ターゲット追跡スケーリング(Target tracking scaling)
- メトリクスによって動的にスケーリングするための機能
- 複数は指定できない
予測スケーリング(Predictive scaling)
- 「過去 14 日間の CloudWatch メトリクスデータのパターンを検出して、次の 48 時間の時間ごとの予測を作成します。」と書いてあるので、月初め・終わりにリクエストが増減するワークロードは学習してくれない模様
- 平日だけリクエストが多いようなワークロードには使えそう
- 予測のみモードにすると、予測の結果によってはスケーリングしない
- 予測の結果はグラフで見れる
- 予測と実際の値のデータをグラフで比較できる
- これによって、予測の結果を確認して使えそうだったら予測の結果でスケーリングするように設定、みたいなことが可能
- ベストプラクティス
スケジュールされたスケーリング(Scheduled Scaling)
予測スケーリングで対応できない、月初め・終わりにリクエストが増減するワークロードはこっちで対応すると良さそう
warm up
- 起動時のメトリクスの変化によってスケーリングが実施されないようにするためのもの
- 例: 起動時にCPU使用率が上がってスケールアウトされるのは意図と異なる挙動。warm up時間を設定すれば回避可能
- リクエスト数でスケーリングする場合は関係なかった
スティッキーセッション
- アプリのCookieを使うか、ALBのCookieを使うか選べる
- セッションのタイムアウト時間を設定可能
Termination Policy(終了ポリシー)
- どのインスタンスからシャットダウンするかを決めるポリシー
- 複数のポリシーを順番を決めて指定し、順番通りに評価する
- 気になったポリシーのみメモ
- OldestInstance
- 最も古いインスタンスからシャットダウンする
- 本番環境で使えそう
- NewestInstance
- 最も新しいインスタンスからシャットダウンする
- テスト時に使えそう
- OldestLaunchTemplate
- 最も古い起動テンプレートを使用しているインスタンスからシャットダウンする
- OldestInstanceとの違いがよく分からない。組み合わせて使うもの?
- OldestInstance