按分は一回だけ、集計は何度でも - GCPコスト按分機構の設計進化
本記事はUbie Tech Advent Calendar 2025の14日目の記事となります。
こんにちは、ユビーでSRE/FinOpsまわりを担当しているdekokunです。今年FinOpsに出会ってから、めっちゃ大好きになりました。I love FinOps!!!
現在ユビーではプロダクト基盤としてGoogle Cloud(GCP)を広く利用しており、クラウドコストの把握・按分は事業運営上の重要テーマになっています。
この記事では、ユビーで運用しているGCPコスト按分の仕組みについて、
現在地:
- コスト按分そのものはBilling Exportのレコード単位まで作り切った
- 現在、その上に「経営企画が見たい粒度」と「マイクロサービス単位で見たい粒度」の階層構造を統合する取り組みを進めている
という状況と、その間を一気通貫でつなごうとしている取り組みを紹介します。
究極的には、経営とエンジニアの間に「コスト」という共通言語を作り、同じ数字を見ながら意思決定できる状態を目指しています。
その前提として、本記事でいう「コスト按分」は、CUD(Committed Use Discounts = 費用ベースの確約利用割引)や共通インフラのような「まとめて発生するコスト / 割引」を、どの事業・どのサービスがどれだけ便益を受けたかに応じて割り振ること、くらいの意味で使っています。
やりたいことはざっくり二つあります。
- 経営企画には事業別(ざっくりと書くとtoB/toCなど)のクラウドコストを、費用収益対応の原則に沿った形で見せたい
- 開発チームには、オーナーシップを持って思い切ってスピードを出せるように、マイクロサービスごとのコストを見せたい
裏側にある考え方を一言でまとめるなら、
- 経営から見るときは、売上や事業の単位で費用を対応させたい
- 現場から見るときは、コストと品質、開発速度のトレードオフを自分たちでとれる状態を作ることで、開発速度が上がる世界にしたい
その両方を、できるだけ一つのコストモデルで支えたい、という話です。
ユビーのGCPコスト管理と二つの視点
まずは、ユビーのクラウドコスト管理の全体像と、「誰のためにどんな数字を出しているか」をざっくり整理します。
経営企画の視点:費用収益対応の原則
経営企画の視点から見ると、やりたいことはかなり教科書的です。
どの事業がどれくらいの売上や利益を出しているのか。その単位でクラウドコストを対応させる。
つまり、会計でいう「費用収益対応の原則」を、クラウドコストにもちゃんと持ち込む、ということです。
そのために、ユビーではざっくりいうと次のような構成でコストを集計しています。
- GCPのBilling ExportをBigQueryに出力
- dbtで変換・集計
- 事業カテゴリ × GCPサービス × プロジェクト といった粒度で、経営企画向けレポートを作成
このレイヤーでは、例として
- 「toB事業のクラウドコスト」
- 「toC事業のクラウドコスト」
といった世界が主役です。マイクロサービスやチームの話は、まだ出てきません。
開発チームの視点:オーナーシップとスピード
一方で、開発チームの関心は少し違います。
- 自分たちのマイクロサービスがどれくらいのコストを生んでいるのかを、ニアリアルタイム(1日ごとなど)で知りたい
- そのうえで、性能・信頼性・コストのトレードオフを、なるべく自分たちで判断することで開発速度を上げたい
ここで効いてくるのがまさにオーナーシップで、その中身は「ガードレールの中で開発スピードを買う」という発想だと思っています。
例えば、こういう世界を目指しています。
- 「この構成、ちょっとお金かかりそうだけど、いったん出してみよう」
- 「ちゃんとモニタリングしておいて、コストとメトリクスを見ながら後からチューニングしよう」
- 「これは高すぎるからやめよう」「ここは速度を優先して高くても続けよう」を、現場で決めていける
もちろん、以前から「マイクロサービスごとのコストを見たい」という話はありましたが、その頃は
SREがBigQueryに対してアドホックなクエリを書き、プロジェクトやSKU、タグなどを駆使して 「この期間、このサービスのコストはこれくらいです」と都度出す
という、職人芸的な運用にかなり頼っていました。
それを、仕組みとして提供したい。
誰かに「ちょっとこのサービスのコスト出して」とお願いしなくても、チーム自身がダッシュボードや SQL一発で自分たちのコストを見に行けるようにしたい。
そのための土台が、この記事で話すコスト按分の話です。
一気通貫でドリルダウンしたい
もう少し欲を出すと、本当にやりたいのはこういう世界です。
- 一番大きな粒度では、経営企画に見せる事業別の数字(toB / toC など)
- その途中の粒度では、プロダクト / ドメイン / チーム / マイクロサービス単位の数字
- さらに細かいところまで行けば、GKE の namespace や個々のリソース単位の数字
といったものを、同じコストデータの上で、上から順にドリルダウンして見ていける状態です。具体的には、
- 事業カテゴリ
- → プロダクト
- → マイクロサービス
- → リソース(プロジェクト / タグ / namespace)
- → マイクロサービス
- → プロダクト
という階層を、途中でテーブルを変えずに一気通貫で追いかけたい。
つまり、
- 「なぜこの事業のコストが上がっているのか?」という問いに対して、そのまま素直に下の階層へ潜っていける構造にしたい
- 「このマイクロサービスのコストが上がりそう」というときに、そのまま素直に「経営企画的にはどの事業のどのカテゴリに効いてくるのか?」が即時に分かる世界にしたい
そのために設計を作り直している、というのが今回のテーマです。
現在、コスト按分そのものはレコード単位まで落ちていて、経営企画向けの集計もマイクロサービス向けの集計も、同じファクトテーブルを起点にできています(詳細は後述します)。
一方で、経営企画側で使っている事業カテゴリとマイクロサービスがまたいでいるドメインやプロダクトの対応関係については、現在対応関係の再設計・アップデートを進めています。
ユビーにおけるコスト可視化の変遷
最初はもっと話はシンプルで、「まずは経営企画に見せる数字を出す」という世界です。
プロジェクトとGCPサービスで、なんとかしていた頃
初期の要件は、ざっくりいうとこんな感じでした。
- toB/toCなどの大きな事業カテゴリごとのクラウドコストが分かれば、とりあえず十分
プロジェクト構成はそこまで単純ではなく、
- 各サービスごとのプロジェクトはすでに大量に存在していた
- さらに、DB や Compute などをまとめた共通インフラ用のプロジェクトもあった
という状態でした。
そのうえで、
- 各サービスごとのプロジェクトには「これはtoB側」「これはtoC側」といったカテゴリを割り当てる
- 共通のプロジェクトについては、「toB : toC = X : Y」といった固定割合で按分する
- 必要に応じて、その固定割合はたまに手で見直す
という運用でなんとかしていました。
今から振り返ると、だいぶ素朴なやり方ですが、当時の目的(事業別のざっくりしたコストが分かること)にはそこそこフィットしていました。
プロジェクト分離と CUD 按分で、経営企画向けビューはいったん完成した
そこから少しずつ仕組みをよくしていきます。
- toB/toCごとにGCPプロジェクトをより明確に分離していく
- CUDを、ビジネスカテゴリに応じて動的な比率で按分するように改善
CUDは、GCPの長期利用割引(ざっくりAWSのSavings Plans/RI的なもの)です。
以前から購入はしていましたが、当初は「割引」という大きな塊として扱われていて、どのカテゴリにどれくらい効いているかまでは見ていない、という状態でした。
そこに対して、CUDに関連するSKUごとの割引額を集計しビジネスカテゴリ単位でCUDを按分するロジックを足しました。
ここで「CUD をどこに載せるか?」について少しだけ触れておきます。
考え方としては大きく分けて、例えばこんなパターンがありえます。
- プラットフォーム(インフラ)部門のコストセンターにまとめて載せる
- 実際にリソースを使っているサービス / プロジェクト側に割り振る(= 便益を受けた側に載せる)
どれが「絶対に正しい」というものではなく、組織として一貫して説明できることの方が大事です。
ユビーでは、クラウドコストにもできるだけ「費用収益対応の原則」を当てはめたいと考えています。
つまり、売上や価値を生んでいる事業・サービスの側に、それに対応するクラウドコストを載せたい。
あわせて、各チームが「自分たちのサービスが生んでいる“全部込み”のコスト」を見ながら判断できる状態にしたい。
こうした理由から、基本的には 2. の便益を受けた側(事業・サービス側)に、できるだけ素直に割り振る方針を取っています。
この記事では、この前提に立って CUD の按分を組み立てています。
このあたりで、「事業別のコストにCUDのコストを正しく反映できる」という意味では、かなり満足度の高い状態になっていました。
経営企画だけを見ていれば、「ここで一旦完成」と言ってよかったと思います。
開発チームのスピードを支える(支えたい)可視化
この「経営企画向けにはだいたいできた」世界の上に、もう一段やりたいことが出てきました。
マイクロサービスごとのコストを見えるようにすることです。
理由は前述のとおりで、
- オーナーシップを推進したい
- FinOpsをメインで推進している自分自身も、さっと確認できるようになりたい
という両方があります。
仕組みを整え速度を上げる
マイクロサービスごとのコストを見たい、というニーズ自体は昔からありました。
ただ以前は、SREがBigQueryに対してアドホックなクエリを書いて、プロジェクトやSKU、タグなどを駆使して「この期間、このサービスのコストはこれくらいです」と都度出す
という運用でやりくりしていました。これは実行できる人が限られることで、毎回待ち時間が発生しスピードが落ちるという問題があります。
ガードレールの中で開発スピードを買う、という観点では、「多少コストがかかってもいったん出してみよう。後でちゃんと数字を見て判断しよう」と気軽に言える状況を作りたい。
そのためには、「コストを見る」部分を職人芸から仕組みに落とす必要があります。
リソース / タグ / プロジェクト / namespace を使ったマイクロサービス別コスト
マイクロサービス別コストを仕組みとして出すために、ユビーではインフラ側を次のように整えています。
- DB / Redis
- 実態としてはタグベース
- Terraform moduleでDBやRedisを作成するときに、マイクロサービスに対応するタグを付与しておく
- 課金データからこのタグをたどることで、どのマイクロサービス向けの DB / Redis かが分かる
- Cloud Run
- アプリケーション構築のための標準的な仕組み(詳細は こちら の「解決策: ubieform による自動生成」を参照)があり、その単位がそのままマイクロサービスに対応
- Cloud Runのサービス名をそのままマイクロサービス名として扱える
- その他の多くのリソース(例えば LLM 関連など)
- 基本的に「1 マイクロサービス = 1 プロジェクト」という構成
- プロジェクト単位でマイクロサービスのコストがほぼ拾える
- GKE
- マイクロサービスの粒度で設計されている namespace 単位でコストを出せるようにしている
これらを集計してできたマイクロサービスごとのコストに対して、CUD コスト・割引額の按分を組み合わせることで、「このマイクロサービスのインフラコストは、だいたいこのくらいです」というビューを日常的に出せるようになりました。嬉しいですね。
ただ、この設計には大きな問題がありました。
当時の按分ロジックは、「CUD などの共通コストを事業カテゴリごと、マイクロサービスごとなど、それぞれの切り口ごとに按分するロジックを書く」という仕組みになっていました。これにより、
- 切り口が増えるたびに按分ロジックを増築する必要がある
- 大きなカテゴリからドリルダウンして細かいカテゴリのコストを見ることができない
というスケールのさせづらさがありました。
この問題をどう埋めるか、というところで、按分の設計を進化させることにしました。
設計転換:レコード単位で一回だけ按分する
このギャップをどう埋めるか考えていたタイミングで、2025年6月のFinOps X Day Tokyoで、Google Cloudの方と話す機会がありました。
そのときの会話をかなり意訳すると、こんな示唆がありました。
- SKU ごとに按分した後の金額を持っておくのが楽
この言葉で、カテゴリ単位ではなく「Billing Export のレコード単位で按分を済ませてしまう」という発想にたどり着きました。
コンセプトは「按分は一回だけ、集計は何度でも」
新しい設計のコンセプトはシンプルです。
- Billing Exportのレコードを、クラウドコストの源泉として扱う
- CUDや共通サービスなどの共通コスト/割引はSKU単位で集計し、そのコストをレコード単位で一回だけ按分する
- そのうえで、好きな軸で集計して見るだけにする
例えば:- 経営企画向けレポートは
GROUP BY business_category - 開発向けダッシュボードは
GROUP BY microservice, environment - 将来のチーム別ビューは
GROUP BY team, microservice, environment
(カラム名は実際のものとは異なります)
- 経営企画向けレポートは
一言でまとめると、「按分は一回だけ、集計は何度でも」という設計に振り切った、ということになります。
CUD をレコード単位に落とすイメージ
実装の細かい部分は別の記事レベルになるので、ここではイメージだけ書きます。
- CUD対象のSKUごとに、オンデマンド相当の利用額を集計する
- 同じ期間のCUDコミット費用と割引額の合計を集計する
- 1 と 2 を使って、SKUごとの按分比率を計算する
- そのSKUを使っている Billing Export の各レコードに、この比率をJOINして「1 レコードあたりのCUDコスト」を載せる
こうすると、結果的に、プロジェクト別に見ても事業カテゴリ別に見てもその他ありとあらゆる切り口で見ても「その期間、そのリソースがCUDの恩恵をどれくらい受けたか」を、自然な形で説明できるようになります。
ポイントは、カテゴリ単位でCUDを按分するのではなく、CUDをレコード単位で一回だけ按分するという発想です。
これでようやく、事業から見ても横(マイクロサービス)から見ても同じファクトテーブルを違う角度から眺めているだけ、という状態に一歩近づきました。
GCP の進化と「どこまで自前でやるか」問題
ここまで頑張ってCUD按分の仕組みを作り込んできたところで、GCP側でもCUD周りの進化が続いています。
特に、Spend-based CUDを調べる過程で、CUDを少なくともプロジェクトごとに利用額に比例して配分する仕組みがあることがわかってきました。
具体的には proportional attribution を使うと、Cloud Billing アカウント配下のプロジェクト間で、CUDのコスト / 割引額を各プロジェクトのCUD対象利用額に比例して自動で分配してくれるようになります。
そのため、「どのプロジェクトがどれだけCUDの恩恵を受けたか?」という問いについては、かなりの部分をGCP側の機構に任せられそうです。
一方で、本当に知りたいのは、プロジェクトの内側・外側の軸(事業カテゴリ / マイクロサービス / チーム / その他ありとあらゆる軸)で見たときのコストです。これらについて、GCPがどこまでいい感じに配分してくれるのかは、現在検証しているところです。
まとめ:レコード単位按分は、二つの目的の土台
最後に、この記事で伝えたかったことをもう一度整理します。
- 経営企画の目的は、費用収益対応の原則に沿って、事業別にクラウドコストをきちんと対応させること
- 開発チームの目的は、ガードレールの中でスピードを出すために、マイクロサービスごとのコストをいつでも見に行けるようにすること
この二つはまったく違う目的ですが、同じコストデータの上で両立できると強いです。
そのためにユビーでは、カテゴリ単位での按分から、Billing Exportのレコード単位で一回だけ按分する設計へと舵を切りました。
この設計にしておくと、
- 上から見るときは、事業別コストの世界で費用収益対応の原則を満たしつつ
- 横から見るときは、開発チームがコストにオーナーシップを持つことで開発スピードを支える
という二つのゴールを、同じファクトテーブルから支えやすくなります。
ここまで紹介した「レコード単位按分」の仕組みにより、経営企画向けの報告は既に安定運用できています。今後の発展の方向としては、例えばこんなものがあります。
- チーム別配賦をどうデザインするか
- 複数チームが触るモジュラモノリスなマイクロサービスをどう扱うか
- 共通系コストの、コスト関連情報以外を使った動的な配賦
- 例えば、複数の事業にまたがって使われるマイクロサービスのコストを、各マイクロサービスからのリクエスト数に応じて各事業により適切に分配するなど
- Google Cloud以外のコストを、このモデルにどのように統合していくか
- 本来は開発など関係なしに、すべてのコストを同じモデルで扱えるはず
レコード単位按分は、あくまで今後のさらなる発展のための一つの土台でしかなく、ユビーのFinOpsの進化は、まさに今も続いている途中です。
この記事が、どこかの現場で同じように悩んでいる人のヒントになればうれしいです。
というか語り合いたい!!!! 一緒にご飯食べに行こうぜ!!!! 連絡ください!!!
X (Twitter) で @dekokun までぜひ。
Discussion