はじめに
世の中にはすごいエンジニアや、よりよい物を作ろうと工夫しているエンジニアがたくさんいます。しかもその工夫や苦労をネットに公開してくれていることさえあります。
本になっているわけではないので体系的に学ぶことはできないのですが、そこで考えた工夫やエッセンス、調査内容は必ず誰かの糧になると思います。この記事では私が「読む価値がある!」と思った記事を引用しながら、自分の考えを追加して理解を深めていこうというものです。
今回紹介する記事
素晴らしい記事をありがとうございます!
記事を読んで考えたこと
記事を読んでいて構成要素が多いなあと感じました。(記事に書かれていない要件があったりするのかもしれないですが)
そこで、自分だったらどうやって設計するだろうということを考えてみましたので以下にまとめていこうと思います。
要件の整理
- スパイクスケーリング
- 常時スパイクをさばけるリソースは確保せず10倍以上にスケールさせる
- スパイクはプッシュ通知をトリガーにして発生する
- プッシュ通知は人力で行われており、そのタイミングでリソースを追加する
- リソースの拡張は即時性が求められる
- スケジュールスケーリング
- 定期的なトラフィック増に対応するために指定の日時でリソースを調整する
- スパイクスケールによるリソース拡張実施時(数十分)は、スケジュールスケールよりスパイクで設定した内容を優先させる
アーキテクチャ
動作を説明します。
スパイクスケーリング
- Push基盤からDB(DynamoDBを想定)に対して宣言したいminReplica数と更新日時を書き込む
- Pod(HPA Controller)はDBを定期的にポーリングしminReplica数を常時取得
- Pod(HPA Controller)は取得したminReplica数を使ってHPAに対して変更を適用
スケジュールスケーリング
- Cronjobは実行時にDBから日時情報の取得する
- 現在時刻と日時情報の差がN分(スパイクスケーリングで決めた分数)を超えていれば、Cronjobから宣言したいminReplica数をDBに書き込む
- Pod(HPA Controller)はDBを定期的にポーリングしminReplica数を常時取得
- Pod(HPA Controller)は取得したminReplica数を使ってHPAに対して変更を適用
変更点とポイント
大きな違いは以下の通りです。
- minReplica数をDBで宣言することであるべき状態を管理する(=k8sの宣言的記法を採用)
- コンポーネント数を最小限とすることで価格や運用コストを低減(Lambda/SNS)
- Redisを使用しないシステムでも導入可能
またこの方法であれば対象のサービスが増えた場合でも、テーブルのカラムにサービス名を追加し、PodやCronjobを追加すれば簡単に横展開することが可能です。
懸念点としてはスパイクスケーリング時の即時性の要件です。ここはPodのポーリング間隔をどの程度にするのか?に準拠します。DBの読み込みコストが読み出し要求ユニット 100 万あたり 0.25USDのため、毎秒ポーリングをしてDBを読み込んだところで260万回/月で対した金額ではないかなと思います。
まあただPush基盤 -> DynamoDBのところどうしようかね?っていうのはありますね。直接書き込みさせるのもなあ。環境違うだろうし面倒いかもしれませんね。
ちなみにこんなのもあり?
Push基盤にどこまでやらせるんだって話ですが、Push基盤がGit(GitHubとか)にminReplica数を書いたHPAのmanifestをPushして、ArgoCDなどのGitopsツールでウォッチ->HPAの変更という流れです。
これなら管理するものはもっと減りますし、すでにGitHub/ArgoCDを使っていれば追加コストほぼないですね。Push基盤->GitHubをどうするのか?とcronjobがスパイクのフラグをどう引っ張るのかはちょっと考えないといけないですが。。。