本文へスキップ
Starone

クラウド・インフラ

エンジニアリング規律としてのクラウドコスト最適化

クラウド費用はアーキテクチャと運用上の判断が生み出す結果であり、四半期に一度片付ける財務の問題ではありません。私たちはコストをレイテンシと同じように扱います。作業単位あたりで計測し、発生させているチームが責任を持ち、設計段階で予算を割り当てます。

· 5分で読めます · Starone エンジニアリング

コスト削減の取り組みは、たいてい同じ経過をたどります。請求額がある閾値を超え、誰かが削減を命じられ、アイドル状態のインスタンスがいくつか削除され、コミットメントが購入され、その後の数か月で数字は元に戻っていきます。うまくいかないのは、コストをシステムの特性としてではなく請求書として扱っているからです。

私たちの立場は、コストはレイテンシや可用性と同じ分類に属するというものです。予算があり、継続的に計測され、それを発生させているコンポーネントに帰属させ、システムが稼働した後ではなく設計図を描く段階で考慮します。

総額ではなくユニットエコノミクスから始める

月次の総額だけでは、システムが効率的かどうかは分かりません。トラフィックが3倍になって請求額が2倍になったのであれば良い結果ですし、利用が減っているのに請求額が横ばいであれば悪い結果です。役に立つ数字は作業単位あたりのコストです。1,000リクエストあたり、アクティブテナントあたり、処理済みトランザクションあたり、取り込み1ギガバイトあたりといった指標です。

どの単位を選ぶかはエンジニアリング上の判断です。負荷を左右する要因に連動していなければならないからです。単位が決まれば、それは他のサービスレベル指標と同じように振る舞います。デプロイと重ねてグラフ化でき、リグレッションが起こり、そのリグレッションを特定の変更までたどれます。リクエストごとにマネージドサービスへの同期呼び出しを追加する機能は、リリース当日にリクエストあたりコストの段差として現れます。その時点が、最も安く疑問を投げかけられるタイミングです。

最適化の前にコストの帰属を明確にする

オーナーがいないものは最適化できません。私たちの標準では、すべてのリソースに所有チーム、サービス、環境、コストセンターのタグを付与し、そのタグは慣習ではなくInfrastructure as Codeのモジュールによって適用します。パイプライン上のポリシーでタグのないリソースを拒否します。記憶に頼るタグ付けの規律は数週間で崩れるからです。

共有プラットフォームにはタグだけでは足りません。Kubernetesクラスターや共有データベースは請求書上では1行にしかならないため、そのコストはNamespaceごとのリソース要求量、クエリ時間、ストレージ消費量などで按分する必要があります。按分は完全にはなりません。それでも、チームが目にできるおおむね公平なモデルのほうが、手を打つには遅すぎる精密なモデルよりはるかに有用です。

まずライトサイジング、コミットメントはその後

順序が重要です。本来の2倍の規模になっているフリートに対して1年や3年のキャパシティをコミットすると、無駄を固定化してしまいます。私たちは代表的な期間に観測した使用率をもとにライトサイジングを行い、CPUとメモリについて平均ではなく高パーセンタイルを見て、実際に飽和しているリソースを確認します。メモリが制約になっているサービスは、CPUの割り当てを増やしても何も得られません。

そのうえで、リザーブドキャパシティやSavings Plansのようなコミットメントは、安定したベースライン、つまり週の中で最も静かな時間帯にも存在する負荷に適用する財務上の手段となります。ピークまでコミットメントでカバーすると、アイドル時間に対して支払うことになります。中断可能なキャパシティは、停止を許容できる処理に向いています。バッチジョブ、CIランナー、キューの背後にあるステートレスなワーカーなどです。プライマリデータベースや、復旧時間が中断通知の猶予より長いものには向きません。

アーキテクチャが生み出す請求項目

コンピュートは請求書の中で目に見える部分であり、多くの場合もっとも理解しやすい項目です。チームを驚かせる請求項目は設計上の判断によって生まれるもので、インスタンスをいくらチューニングしても消えません。

  • データ転送:アベイラビリティゾーンをまたいで頻繁に通信するサービスは、ゾーン間の呼び出しのたびに課金され、NATゲートウェイ経由でパブリックエンドポイントへ向かうトラフィックは処理したギガバイト単位で課金されます。プライベートエンドポイントやゾーンを考慮したルーティングは設計上の選択であり、チューニングではありません。
  • ストレージ階層:ライフサイクルルールのないオブジェクトストレージは、すべてを最も高価なクラスにいつまでも置き続けます。コールドな階層は保持コストが低い一方、取り出しと最小保存期間に料金がかかるため、ほとんど読まれないデータに向いています。
  • オブザーバビリティ:デバッグレベルのログ、高カーディナリティのメトリクスラベル、無期限の保持は、それが記述しているワークロードよりも高くつくことがあります。サンプリングと保持期間は、オーナーを伴う意思決定です。
  • 孤立リソース:アタッチされていないボリューム、古いスナップショット、アイドル状態のロードバランサー、忘れられた非本番環境は、定期的に削除する仕組みがない限り蓄積していきます。

オートスケーリングは制御ループであり、チューニングが必要

オートスケーリングがコストを下げるのは、需要に追従するシグナルでスケールし、スケールアップと同じくらい速やかにスケールダウンする場合に限られます。I/O待ちが中心のワーカーにとってCPUは不適切なシグナルで、キューの深さやインスタンスあたりの処理中リクエスト数のほうがたいてい実態に近くなります。起動が遅いと大きなバッファが必要になるため、イメージサイズとウォームアップ処理の削減はコスト対策そのものです。

Kubernetesでは、スケジューラーはPodを使用量ではなくリソース要求量にもとづいて配置します。要求量が水増しされていると、ノードは満杯に見えながら大半がアイドルのままになります。要求量を実際の使用量と照らして見直すほうが、ノードプールのどんな変更よりも多くのキャパシティを取り戻せることがよくあります。業務時間外にゼロまでスケールする非本番環境は、コードから確実に再作成できることを条件に、もっとも手軽に得られる削減策です。

最適化すべきでない場合

コスト効率は他の特性と競合し、ときには譲るべきものです。トラフィックの急増やゾーンの喪失を吸収するのはヘッドルームであり、非常に高い使用率で稼働しているシステムは、請求額を小さくする代わりにレジリエンスを手放しています。このトレードオフは、攻めたスケーリングポリシーの偶然の産物ではなく、明示的に決め、テストしておくべきものです。

エンジニアリングの時間もコストです。請求額が小さく、市場がまだ検証されていない初期のプロダクトでは、インフラ費用を削るために費やす1週間は、たいてい配分を誤った1週間です。単位あたりの費用が高いマネージドサービスは、運用作業をなくしてくれるという点で正しい選択になります。私たちが主張する規律は、最初から計測とオーナーシップを確立し、最適化の労力はユニットコストが回収できると示す箇所に投じることです。

  • 最適化する:ユニットコストが利用量より速く上昇しているとき、または明確な理由なく単一の請求項目が大半を占めているとき
  • 先送りする:請求額がチームの時間に比べて小さく、アーキテクチャがまだ変化しているとき
  • 却下する:その削減が、可用性目標の前提となる冗長性やヘッドルームを取り除いてしまうとき

同様の課題に取り組んでいる方へ

ぜひ意見を交換させてください。この記事を書いたエンジニアが直接お話しします。