見出し画像

インフラコスト削減ステップ ~ダイニーのGCP Projectを例として~

ダイニーの @urahiroshi です。
この記事では、ダイニーで行なっているインフラのコスト削減プロセスを例として、コスト削減をどのように進めていくと良いか解説したいと思います。フィードバック等あればぜひご連絡ください!

コスト削減ステップ1. コストレポートの作成

これまでに大規模なコスト削減に手をつけていない場合や、しばらくコスト削減を行なっていない場合、まずは全体像の把握が必要です。組織が管理しているインフラのすべてのコスト情報を参照し、コストの要因を分析したコストレポートを作成しましょう。コストレポートを作成して社内に公開することで、他のメンバーも状況を把握でき、今後同じようなコスト調査をする際により効率的に調査できるようになります。
コストレポートの作成手順は以下のようになります。

  1. 組織が契約しているインフラのサービスごとに、請求書ベースでのコスト情報を取得します。ダッシュボード等により請求額が確認できるサービスであれば参照したURLも記載します。コスト情報は直近の数ヶ月分以上の期間にわたって取得し、コストの推移も確認できるようにします。

  2. すべてのサービスのコストを合算し、コストの累計額の推移を記載します。

  3. ある程度コストがかかっているサービスについては、どういった要因でコストがかかっているか、どういったコスト削減策が考えられるかを調べて記載します。コスト削減策については、実際に実施するかどうかは後で判断するとして、思いついた削減策はすべて記載すると良いでしょう。

例として、Cloud Storage のコストレポートを以下に掲載します。

Google Cloud Storage に対するコストレポートの例

このレポートを記載するにあたって、まず Cloud Storage の SKU (Stock Keeping Unit) を参照し、Standard Storage Asia Multi-region と Network Traffic Egress GCP Replication within Asia にコストがかかっているとわかりました。そこで Cloud Storage の各バケットの利用サイズと送受信データを確認し、どのバケットにコストがかかっているかを特定しました。さらに、そのバケットが何のために利用されているかを調査した結果、そのバケットのデータは削除しても良いことがわかりました。そういった情報をコストレポートに記載しています。

コスト削減ステップ2. コスト削減の実行

コストレポートの作成後(もしくは作成と並行して)、コスト削減を実施します。
例えば少量のリクエストを処理するのに固定課金型のサービスを利用しており、従量課金型に変えることでコスト削減できた、などであれば話は単純ですが、ある程度適切なアーキテクチャを利用している状態であれば、ほとんどのアプローチはコストを削減できる一方で何かしらネガティブな影響をもたらすトレードオフがあります。適切なトレードオフの判断を行うために、個々のアクションでどれだけコストが削減できるのかは可能な限り高い精度で見積もり、コスト削減を実施するかどうかの判断を行いましょう。
ダイニーのコスト削減においては、以下の4つのトレードオフによりコスト削減を実施することができました。

  • 機能

  • 複雑性

  • 品質

  • 自由度・柔軟度

それぞれのコスト削減のアクションについて詳細を記載します。

機能とのトレードオフによるコスト削減 ⇒ 費用対効果が見合わない機能を削除

ダイニーでまずコストの詳細を調査したところ、 Cloud Firestore Read Ops Japan というSKUに多額のコストがかかっていました。最初は「Firestoreの読み取り回数が多いからコストがかかっているのかな?」と考えていましたたが、Metrics Explorer 上で Firestore の読み取り回数 ( Document reads ) の値を参照しても請求金額に達していませんでした。
そこで更にFirestore関連の処理を調べて行ったところ、Firestoreのドキュメントを Cloud Storage にエクスポートしている処理がありました。エクスポートの処理で読み取られたデータは Document reads のメトリクス上に反映されていませんでしたが、このエクスポートで Firestore から読み込まれていたドキュメント数とエクスポートの回数を乗算すると、 これが Cloud Firestore Read のコストの多くを占めていたことがわかりました。
このエクスポート処理は、Firestore のデータを何か問題があった場合の調査のために残しておくためのものでしたが、これまでそのデータを利用したことはなく、明らかに費用対効果が釣り合っっていないものと判断できました。そのため、エクスポート処理自体を削除しました。
これにより、 Cloud Firestore Read Ops Japan のコストは80%以上削減することができました。

Cloud Firestore Read Ops Japanのコスト推移

実はこのエクスポート処理は、上のコストレポートで記載している Cloud Storage のバケットをエクスポート先としており、Cloud Storage に対するコストも90%以上削減することができました。

Cloud Storage のコスト推移

複雑性とのトレードオフによるコスト削減 ⇒ キャッシュの導入

Cloud Firestore Read Ops Japan のコストについて、エクスポート処理の削除によりコスト削減は実施できましたが、それでもまだ一定のコストはかかっていました。

Firestore の読み込み処理はどこで使われているのでしょうか? ダイニーでは、モバイルオーダーなどのプロダクトからメニューの注文があった左に、キッチンプリンタから注文情報が印刷されるような処理を実装しています。こういった印刷情報を Firestore に保存しており、プリンタが定期的にサーバに対して問い合わせを行い、対象となる印刷情報があれば印刷するような仕組みになっているため、この問い合わせのたびに Firestore への読み込みが走っています。

変更前の印刷処理(簡易化しています)

「プリンタが定期的にサーバに対して問い合わせをする」というのが曲者で、これは飲食店の営業時間に関わらず、プリンタの電源がついていれば問い合わせのリクエストが届きます。そのため、飲食店1店あたりのリクエストの中でも、プリンタからのリクエスト数は群を抜いていました。
大部分のリクエストでは印刷対象がないという結果だけが返っているため、印刷対象の有無をキャッシュとして保存しておけば、大部分のリクエストで Firestore への読み込みを減らすことができます (また、リクエストのレイテンシも減らすことができます) 。そのため、Cloud Memorystore を導入して印刷対象の有無をキャッシュとして保存し、Firestore の読み込みを減らす事にしました。

変更後の印刷処理 (印刷情報なし)
変更後の印刷処理 (印刷情報あり)

キャッシュを導入した結果、 Cloud Firestore Read Ops Japan のコストはさらに90%以上減り、エクスポート処理の削除と合わせると98%以上のコスト削減となりました。
(なお、Cloud Memorystore のコスト増分はコスト減分の10%程度でした)

Cloud Firestore Read Ops Japanのコスト推移

ただし、キャッシュの導入は常にリスクがあるということは意識しておく必要があります。キャッシュを導入する事で、この印刷関連の処理で「キャッシュがある場合」「キャッシュがない場合」の条件分岐が生まれ、システムとしての複雑性は上がります。
今回のキャッシュ導入においても、Firestore 上で印刷情報を更新しているのに関わらず、キャッシュ上は印刷情報を読み込む必要がないという不整合が生じるリスクは今後の機能拡張でも常にケアしなければなりません。この影響はキャッシュ導入時の初期実装コストだけでなく、導入後の運用コストや信頼性にも影響します。
今回のキャッシュ導入においてもかなり悩みましたが、コスト削減効果が大きく、プロダクトのスケールによってコスト削減量は増加していく見込みもあったため、最終的に導入に踏み切りました。

品質とのトレードオフによるコスト削減 ⇒ 開発環境への低品質のインフラの利用

ちょうどコスト削減の計画を立てているときに、ダイニーが利用しているAlloyDBで basic instance を利用できるようになりました (https://cloud.google.com/alloydb/docs/basic-instance)。
AlloyDBはデフォルトで Active/Standby の構成を持っていたため、割り当てているマシンリソースに対して2倍のコストがかかっていたのですが、開発環境では高可用性の必要性が薄いため、basic instanceにすることでコストを削減できました。
似たようなパターンとして、GCEやGKEであれば可用性の低い Spot VM を利用することでコストを削減することができます。ダイニーの場合はCloud Runの環境を利用していたため、こちらの方法は適用できませんでした。

自由度・柔軟性とのトレードオフによるコスト削減 ⇒ リソース使用量のコミットメントによる割引適用

GCPには 確定利用割引 (CUD) があり、一定の使用量を確約することで割引を受けることができます。対象のプロダクトは限られますが、1年間はそのプロダクトを利用し、利用量の予測ができる場合は有効に活用できるかと思います。
他のコスト削減のアプローチにより使用量自体が減る可能性もあるので、コスト削減のアクションを一通り実施した後にコミットメントを行うと良いでしょう。
その他にも、例えばBigQueryでオンデマンドではなく容量ベースの課金モデルを利用する (https://cloud.google.com/bigquery/docs/reservations-workload-management) なども自由度・柔軟性とのトレードオフによるコスト削減と言えるでしょう。利用しているサービスの課金モデルや、乗り換えが検討できる競合サービスの課金モデルを確認できると良いでしょう。

コスト削減ステップ3. コストのモニタリング

これまでに挙げたような「コストの全体像を把握してレポートを作り、コスト削減のアクションを実施する」こと(以下、コストの全体調査と呼びます)は定期的に行えると良いでしょう。しかし、これには一定の労力がかかるうえ、あまり短期間で繰り返し実施してもレポートの内容があまり変わらないことが予想されます。そのため、コストの全体調査は1年に1回などある程度間隔を空けて実施しつつも、それに加えてより細かい頻度(毎月、毎週など)でコストの変化量をモニタリングすることをお勧めします。
コストの変化量をモニタリングする際は、単にコストの絶対値だけを見るのではなく、サービスの利用量と照らし合わせて計算すると良いです。通常、サービスの利用量が増えることに従ってコストの合計額も増えていくため、サービスの利用量に対するコストの変化を見ることで、毎月のコストの変化が妥当かどうか判断できます。

利用量には何を基準にすれば良いでしょうか?以下のようなものが考えられます:

  • クリティカルユーザージャーニーにおけるアクション

  • サービスのユーザー数 or 契約数

  • GMV

ダイニーの場合はSaaSのビジネスモデルのため、1契約あたりのコストを出せると原価率のように扱えるためわかりやすいです。一方で、季節要因による利用量の変動も大きいため、利用量とより連動性の高い注文数、GMVに対するコストも計算し、コストの妥当性を判断しています。
以下、コストのモニタリング情報のサンプルになります。

コストの月次モニタリング(サンプル)

コストに予期せぬ上昇が見られた場合は、増加要因を調査します。細かい頻度でコストをモニタリングしていることで、その期間に行われた変更は把握しやすく、コスト増加要因の特定は容易になります。
ただ、このようにコストの増加をモニタリングすることの負の側面として、コストが増加するような変化を過度に避けようとする意識が生まれがちです。
個人的な観点を述べると、サービスが1→10, 10→100のようにスケールしていくと、コストに対するスケールメリットが効きやすくなるので、上に挙げたコミットメントによるコスト削減やキャッシュによるコスト削減などの選択肢が生まれ、1契約あたりに必要最低限のインフラコストは安くできます。一方で、サービスが成長するとインシデントによるインパクトも相対的に大きくなるため、安定性やセキュリティにはより投資する必要が生じます。また、組織の拡大によるコミュニケーションコストの上昇やコードベースの拡大による認知負荷の増大への対策として、生産性向上のための投資も必要になります。スケールメリットによるコスト削減分により、安定性・セキュリティ・生産性向上によるコスト上昇分が相殺できるようなバランスが適切だと考えています。
そのため、過度にコストの増加を避けるのではなく、コスト全体のバランスを見つつも組織の成長に必要な投資は積極的に実施できると良いでしょう。

(最後に宣伝です)
ダイニーでは、このようなコスト管理は Platform Team というチームが担当しています。Platform Team はインフラの専門部隊というわけではなく、個々のメンバーの強みを活かしながらフルスタックにアーキテクチャからインフラまで幅広く改善を行っています。もしダイニーのエンジニア組織に関心があれば、ぜひカジュアル面談でお話ししましょう!


この記事が気に入ったらサポートをしてみませんか?