エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

エムスリーでのクラウド費用監視

こんにちは!エンジニアリンググループ、コア SRE の平岡です。

この記事はエムスリー SRE がお届けするブログリレーの3日目です。

エムスリーでは現在、クラウドプラットフォームとして AWS と GCP を採用しています。プロダクトを開発している各チームには、そのプロダクトを適切に実装できるプラットフォームを自由に選んでもらっています。

そんな中、エムスリーではここ数年、 SRE の役割をプロダクト開発チームに分散・移譲する取り組みを進めています(リレーの前記事にあった「チームSRE」の体制づくりです)。その結果、プロダクトの開発に伴うインフラ構築・管理のほとんどが各チームに一任されるようになっています。

というわけでこの記事では、エムスリーでチームSREの体制づくりを推進する中での、クラウド利用における費用監視の仕組みについてご紹介します。

f:id:uhm3:20210113044732j:plain
中で何かが起きてそうな雲・・・

チームSREとクラウド費用監視

クラウドを利用していく中で、そこで発生する費用を無視することはできません。 適切に使えている限りは便利なクラウドですが、使い方を間違うとその費用が爆発して、いわゆる「クラウド破産」の状況に陥ってしまいます。それを避ける、あるいは軽減するために、日々の利用状況≒費用の監視は必須と言えるでしょう。

先に挙げた通り、エムスリーではここ数年、チームSREの体制づくりがすすめられています。 チームSREの原則に従うと、クラウドの費用監視もそれぞれの開発チームで実施してもらうことになります。これは開発メンバーにコスト意識を持ってもらう意味でメリットがある一方、チームでの費用監視に不備があると、クラウド破産の状況を見落としてしまう危険性があります。そしてひとたび事故が起きてしまうと、1つの開発チームはおろか、組織全体にダメージを与える事態に発展してしまう可能性もあるわけです。

これを避けるため、エムスリーではプロダクト開発チームでの費用監視とは別に、コアSREチームによる中央集権的な費用監視も実施しています。 別々の行動原理を持つ2チームで独立した監視を行うことで、異常事態を別個に検出し、相互に確認することが可能になります。端的に言えば、以下3つのメリットが得られます。

  • コアSREにとっては異常に見えるが、プロダクトチームにとっては想定内の状況(例えば、ビジネスとして予定されたスケールアウト)を正常とみなせる。
  • プロダクトチームにとっては異常に見えるが、コアSREにとっては想定内の状況(例えば、クラウドインフラの共通基盤のリソース増強に伴うコスト増)を正常とみなせる。
  • コアSREとプロダクトチームの両者にとって異常な状況が見つかった場合、至急で調査を開始する。

筆者はコアSREチームに所属しており、中央集権的な監視を行っている側にいます。そのため、今回の記事ではそちらの仕組みについてお話しようと思います。

クラウドの費用を監視する

『費用監視』という概念を一度分解して考えてみると、①費用情報を収集する、②収集した情報を(人・あるいは機械に)観測可能にする、③観測した費用情報が異常値であった場合に(人・あるいは機械に)通知する、という3つの要素を達成することが求められます。コアSREで実施しているクラウド(プラットフォーム)の費用監視の仕組みでは、これらを以下の方法で達成しています。

  • ①クラウドの費用情報を収集する
    ⇒ AWS & GCP から定期取得した費用情報を BigQuery に集約
  • ②収集した情報を(人・あるいは機械に)観測可能にする
    ⇒BigQuery をデータソースとしたダッシュボードを Redash で構築
  • ③観測した費用情報が異常値であった場合に(人・あるいは機械に)通知する
    ⇒ Redash のアラート機能で異常値を判定、 Slack の専用チャンネルに通知

今回の記事で①〜③の全てを取り扱うと長大になってしまいますので、ひとまずは①の費用情報を集める仕組みについてのみフォーカスし、残りはまた別の機会に紹介しようと思います。

クラウド費用情報の収集

エムスリーでは、クラウドプラットフォームとしてAWSとGCPを利用しています。そのうち GCP には、費用情報を BigQuery に定期エクスポートする機能があり、請求アカウントでその機能を有効化するだけで、指定の BigQuery データセットに時間単位の費用情報が格納されるようになります。この機能に便乗する形で AWS の費用情報を BigQuery に格納する仕組みを実現できれば、AWS と GCP の両方の費用情報を BigQuery 一箇所にまとめることができます。

AWS のクラウド費用情報を取得するにあたり、データの格納先となる BigQuery との接続性を考慮して GCP の CloudFunctions を中心に据えた仕組みを構築・運用しています。全体のアーキテクチャは下図のようになります。

f:id:uhm3:20210113014234p:plain
クラウド費用情報収集のアーキテクチャ

見ての通り、 AWS のマスターアカウントと GCP の請求アカウントのそれぞれから Organization 内の費用情報を取得し、 BigQuery の費用情報用データセットに投入しています。そのデータセットを Redash などの各種ツールから参照できるようにすることで、コア SRE が実装するアラートの仕組みに繋げるだけでなく、それぞれのチームからも自由に見ることができるようにしています。

以降では、 AWS からの費用情報の取得と、 BigQuery へのデータ投入について述べていきます。

AWS 費用情報のデータ取得

AWS の費用情報に関連するサービスには様々なものがあり、定期的に新機能がリリースされていますが、その中で代表的なものとして AWS CUR (Cost and Usage Report) と AWS CostExplorer API があります。CUR では詳細な費用レポートを取得してS3に格納させることができ、対する CostExplorer API では対話的に費用情報を問い合せることができます。

今回の目的(= BigQuery に費用情報を格納する)のためにはどちらでも問題ないと思われますが、 AWS からの情報取得〜BigQuery へのデータ投入のシーケンスをできるだけ単純にしたいと思い、 CloudFunctions から CostExplorer API を呼び出すようにしています。

なお、AWS のマスターアカウントに対して CostExplorer API を呼び出すための IAM の情報は、 CloudFunctions と同じ GCP プロジェクトの SecretManager に格納しています。

費用情報のテーブル構造 in BigQuery

AWS の費用情報データの格納先になる BigQuery 側には、事前に費用情報用のテーブルを用意しておきます。このテーブルは GCP の費用情報のスキーマ*1 と近いものにしたいので、以下の8フィールド(=カラム)としています。

  • 請求日
  • 請求の開始時刻(UTC)
  • 請求の終了時刻(UTC)
  • AWSアカウントのID
  • AWSアカウントの名前
  • AWSサービスの名前
  • 請求額(UnblendedCost)
  • 請求額の単位

ここで重要なことは、AWS費用情報のテーブルを パーティション分割テーブルとして作成し、分割フィールドに請求日のカラムを設定する ことです。

後に Redash で構築するダッシュボードでは、日次ベースで検索の範囲指定をするため、請求日でパーティションで分割しておくことで BigQuery の検索対象となるデータ容量=検索にかかる費用を制限することができます。費用監視のための仕組みで費用を浪費してしまうのは本末転倒です。

また、もう一つの(厄介な)理由として『 CostExplorer API で取得した費用情報は過去に遡ってデータが更新されることがあり得る』ということへの対処があります。これは筆者が経験的に気が付いた(だけなので公式情報があれば是非とも知りたい)のですが、例えば「毎月1日の費用として登録される Tax の料金はその月の終盤に更新される」ということが発生していました。そのため、1日1回起動する CloudFunctions のロジックでは、1日分のデータを取得&BQに投入するのでなく、1ヶ月+10日分のデータを洗い替えするようにしています。10日分余計に取得しているのは、万が一 AWS の障害で CostExplorer API でデータが取れなかった場合 / GCP の障害で CloudFunctions が実行できない日があった場合の両方に対応するために設定しています。 図にすると以下のようなイメージです。

f:id:uhm3:20210113033612p:plain
費用情報の洗い替え範囲

費用情報を請求日フィールドでのパーティション分割テーブルとしておくことで、洗い替えで1ヶ月+10日分のデータを消すのに DELETE (データ更新のクエリ)を使わず、パーティション単位でのデータ削除が可能になります。*2 BigQuery ではデータの更新に対して費用がかかる原則があるため、ここでもまた余計な費用を節約できます。

また、BigQuery へのデータ投入にはいくつかの方法がありますが、今回の用途で選択肢になるのは Streaming Insert でデータを逐次投入する方法か、一旦 CloudStorage にデータファイルを格納してバッチロードさせる方法の2択です。両者で試行錯誤した結果、 Streaming Insert の各種クオータ *3 を超えないよう制御することと、BQ の重複排除がデータの洗い替え(削除+追記)の挙動との相性が悪かったため、 CloudStorage 経由でのバッチロードを採用しました。

その他細かな調整を行うことで、 AWS / GCP 費用情報を安定して収集& BigQuery に格納できるようになっています。

まとめと感想

この記事では、エムスリーのSREが行っている活動の1つとして、クラウドの費用監視(のためのデータ収集)について説明しました。(続編はまたいずれ)

本当はこの収集したデータに対して、ダッシュボードで可視化し、異常を判定し、その結果を通知するところまでできてようやく『費用監視』として一巡りしたことになります。

エムスリーではこれら一通りの仕組みを構築・運用していて、実際にダメージを軽減できた実績もありますが、まだまだ改善の余地がたくさんあると感じています。チーム SRE の体制づくりが広まるにつれてクラウドの費用監視の重要度が増していることをひしひしと感じているので、今後も改善し続けていきたいと思います。

We're hiring

というわけで、エムスリーではクラウドをバリバリ使う人、バリバリ使う人をしっかりサポートしたい人を大大大募集しています!コア SRE や チーム SRE はもちろん、変化し続ける組織の中で活躍したいエンジニアの皆さん、是非ともお声掛け下さい!!!

open.talentio.com open.talentio.com jobs.m3.com