この記事はアソビュー! Advent Calendar 2022 の 21日目です。
裏面もよろしくお願いいたします!!
こんにちは、アソビューデータ基盤チームの霧生です。
最近はポケモンsvにハマっています。ランクマッチに初めて挑戦し、マスターボール級に行けて非常に満足しています。
以前データ活用について、弊社執行役員CPOの横峯から下記の記事が出ています。 本稿はそのアフター記事として、どういったことを考えながら設計していったのかを書いていければと思います。
Intro
前述の記事にもある通り、データ分析基盤の構築は「DATALE」さんに協力をいただきながら構築を進めていきました。
DATALEさんとの話し合いの中で、データ基盤を構築するにあたって必要になってくるGAなど、各種Google系のサービスのデータ取得の親和性や、一部でGCPを利用していたことからBigQueryを利用することになり、BigQueryにデータを投入する部分にtroccoを採用することになりました。
troccoとはETL/データ転送機能やデータマート機能を提供する分析基盤構築・運用支援のSaaSで、競合としてはfivetran等になってくると思います。 troccoを提供しているprimeNumber社が日本企業なこともあり、手厚いサポートや日本でよく使われるSaaSからのデータ連携がしやすい所に強みがあると感じています。
troccoを使いBigQueryに各種データを溜め、そこから分析できる形式にtroccoでデータを変換してマートを生成、Tableauで分析する。
一言で言ってしまえばアソビューのデータ分析基盤は上記の形式になっているのですが、これらを構築するにあたってGCPとBigQueryをどう設計していったのかをいくつかのポイントに絞って解説していければと思います。
GCPとリソース階層、プロジェクト粒度について
GCPにはOrganization, Folder, Projectといくつかのリソース階層が存在します。
このリソース階層をどう定義し利用していくかを決めていくことで、IAMの適用範囲やGCPの各サービスをどこでアクティベーションするかが変わってくるため、BigQueryを利用する以前にGCPをどう利用していくかを決める必要があります。
GCPのプロジェクトとリソース階層の全体設計
リソース階層のベストプラクティスでは組織の構造に合わせる形が推奨されていますが、組織の移り変わりの激しいスタートアップ企業では必ずしも合致しないことから、大きな悩みポイントになるのではないかと思います。 組織変更が頻繁に行われることや、チームとサービスが必ずしも1対1ではないことから、アソビューにとっても非常に悩ましい問題でした。
そこで十分にGCPでのプロジェクトが発展していない状態でプロジェクトを細かい粒度で分割した場合、後に方針転換が発生した際にAWSアカウントの二の舞のような状態になってしまうと考え、できる限り最小限のフォルダ、最小限のプロジェクトで構成する方針をとりました。
これらを踏まえて作成した構成が下記になります。 (staging側は記述を省いていますが、production側と構成は同じになっています。)
フォルダ単位で環境を分離することで環境の冪等性と操作の柔軟性を担保しつつ、最小限のプロジェクトで構成することで、後に修正や移行が発生した際に対応しやすい形をとりました。
「iac-terraform」プロジェクトはその他の各プロジェクトの初期設定支援とリソースの作成を行うためのプロジェクトです。このプロジェクトでterraformで利用するサービスアカウントやstateを管理するGCSバケットを管理しています。
「product」プロジェクトはアプリケーション内で利用するサービスを管理しています。GCPの利用が今後増えていくとここが肥大化していく恐れがありますが、そこを適宜コントロールしていければと思っています。
そして、「data-lake」「data-mart」プロジェクトが今回のデータ分析基盤で利用するプロジェクトになっています。
データ分析基盤のプロジェクト設計
リソース階層が決まった段階で、次にデータ分析基盤のプロジェクトをどう定義するかが問題になりました。
基本方針
前述の最小限のプロジェクトで構成していくという基本方針はここでも則っていくのですが、あくまでこれは将来への柔軟性を担保するための方針です。 「product」プロジェクトはアプリケーション利用を目的にしていたため、こことは役割が大きく異ることからプロジェクト数は最低限にするもののデータ分析基盤のプロジェクトは分割して作成することにしました。
同時に、BIツール側の進化もあり中間層が必要ないと判断し、rowデータをそのまま溜めていくlakeと分析用のデータを持つmartの2層構造で進めていくことになりました。
BigQueryをデータ分析基盤として使う場合の考慮事項
上記の基本方針からアプリケーション用のプロジェクトとは別で構築していくことになりましたが、後述する2つの考慮事項からlakeとmartの2つのプロジェクトに分割して構築していくことに決めました。
サービスクォータへの対応
まず考慮すべきはサービスクォータへの対応です。 BigQueryのクエリの同時実行数といった各種サービスクオータはプロジェクトレベルでの制限になっています。 そのため、一部のクエリがこの条件に該当してしまうことで実行できなくなるリスクを減らすため一定の粒度で分割を行うことが望ましいです。
特にスロットの概念がBigQueryを利用する上で発生します。 上記にもありますが、初期段階でプロジェクトに付与されるスロット数は2000で、これを消費しきるとクエリの実行に支障が発生します。スロットは年間契約にすることで増加させることができますが、今後の利用の拡大や用途の変更を鑑みた場合、早急に手を出して実施するべきではありません。
martでの機密情報の取り扱い
データ分析基盤は様々なデータを扱うため、当然ですがデータの取り扱いには気をつけないといけません。 lakeを参照できるユーザーはmartを構築する人に限られているため問題なかったのですが、martでは機密情報の取り扱いを考慮する必要があります。
そもそもBigQueryに対してGCPのIAMで制限できるリソース階層は次の5つがあります。
- 組織、フォルダ、プロジェクト単位
- BigQueryデータセット単位
- BigQueryテーブル、ビュー、関数単位
- BigQueryテーブルの行単位、列単位
- 実行時の条件(時刻など)
この中で組織、フォルダは粒度が大きすぎ、テーブル以下は粒度が細かすぎて制限することが難しいため、基本的にプロジェクト単位かデータセット単位で権限制御を行いたいのですが、下記の理由からBigQueryのデータセット単位での権限分離が難しいと判断しました。
- あくまでIAM Conditionの機能ではなく「BigQuery」側の機能でデータセット毎の権限設定ができる仕様
- IAM一覧でどのService AccountやIAMがBigQueryのどのデータセットを参照できるかの一覧を確認できない
- IAMのロールではないため、BigQuery側での権限しか持っていないService AccountやIAMがIAMの一覧で出てこない
- そもそも権限を確認するためにそれぞれのデータセットを確認する必要があるのでかなり煩雑
「プロジェクトはなるべく増やしたくない自分 vs データセット単位での権限制御はしたくない自分 vs ダークライ」みたいな状況になっていたのですが、投稿時点ではbeta版の機能であるデータセットへのタグ付けがこれを解決してくれました。
これによりIAM側でデータセット粒度の権限制御が行えるようになるため最優の選択肢だと思っていますが、あくまでbeta版なのでここは今後変わるかもしれません。現状martに直接アクセスできるユーザーを絞っているためなくなった場合でも問題にはなりませんが、GAとなることを祈ってます。
中長期的にデータ分析基盤を拡張していくときの方針
ここまででlakeとmartの2つのプロジェクトに分割することに決めましたが、今後の利用の拡大等を鑑みて、プロジェクトを分割するための判断基準も設けることにしました。
- サービスクォータに達してしまった場合
- martへのデータの流入経路が増えた場合
1つ目は言葉の通りで、lakeとmartがそれぞれ該当します。2つ目が特に重要で、lakeへのデータ投入、lakeからmartへの連携はtroccoを利用しており、そこで利用するService Accountは「書き込みができるBigQueryは特定プロジェクトのBigQueryのみ」としています。 こうすることでlake及びmartのデータ整合性の担保と、データ流入経路の明確化による管理コストの低下なども見込めます。 現状まだ発生していませんが、機械学習の結果の投入などが今後発生した場合に対応していく予定です。
ここまでの考慮事項を含め、最終的には下記の簡易図のようになりました。
BigQuery構造設計
最後にデータ分析基盤で利用するBigQueryの構造と運用についてです。
Data Lake
lakeは分析者が参照するBigQueryではなく、martで使うためのデータを一所に集める目的のために利用されます。 そこでlakeのデータの重要な観点は下記2つにあると考えています。
■ データの保全
- 投入したデータが他のデータによって変更されないこと
- メンテナンスの容易性
■ あらゆるデータの収集
- 構造が異なるデータの投入ができる
- 元データを担保する
- 複数のデータ投入経路が存在する
ここから、下記3つをルールとして運用を行っています。
- データクリーニング以外のデータ構造の変換や結合といった変換は行わずに投入する
- データ投入経路が異なるものを同一のデータセット内に配置しない
- データの投入経路が分かるような命名を行う
更に、BigQuery内のデータセットの命名規則は下記の方針とし、テーブル名にも命名規則を付けることで、運用を標準化しています。
{環境名}_{データソース区分}
環境名はstagingやproductionといったものになり、データソース区分はデータの引用元になります。 データソース区分によってデータセットやテーブルの粒度が変わってくるため、データの引用元が増える度に議論して更新しています。
一部を例とすると、下記のような規則をそれぞれのデータソース区分に適用しています。
データソース区分: MySQL データセット分割単位: データベース名 データセット命名規則: production_db_{DB物理名}_{データベース名} テーブル分割単位: テーブル毎 テーブル命名規則: テーブル名
データソース区分: SaaS(Braze, SalesForce, etc...) データセット分割単位: SaaS毎 データセット命名規則: production_{SaaS名} テーブル分割単位: データの種類毎 テーブル命名規則: 連携時のファイル名やフォルダ名
Data Mart
こちらもBigQuery内のデータセットの命名規則を下記で運用しています。
{用途レベル}_{サービス名}_{データ機密性}_{データの種類}
特に、前述したタグをmartには付与するため、利用できる組み合わせからデータセット名を決定し、必要なタグを付与していきます。
■ 用途レベル
production/staging/sandbox毎にタグ付け
環境と読み替えてもいいのですが、データマート構築者が一時的な作業場を必要としていることもあるため、そこに対してのみ強めの権限を付けたりと柔軟な対応を取るために接頭語として付与します。
■ サービス名
エンドユーザーのゲストから見たときの区分。
ここがアソビューのデータ分析基盤として非常に重要なくくりで、事業として追いかけているKPIが違った場合でも裏側の元になっているDBは同じものを参照していたりするため、ここの分け目を作ることが難しい場合があります。そのため、あくまでデータの塊はひとつとして表現し、事業毎はBIやテーブルで表現する、という手法をとっています。
■ データ機密性
normal/confidential毎にタグ付け
データが機密情報を扱うか扱わないかを判断します。ここのタグによって見られるデータセットを制御していくことになります。
■ データの種類
特定の種類もしくはタグの分類レベルで作成していきます。 命名はシンプルにどんなデータかがわかる粒度感としています。
これらをまとめるとサンプルとしては下記のようになります。
データセット名: production_asoview_confidential_common タグ: environment=production, data-type=confidential
特にmartのデータセットの分類は難しく、よくできたものでも使われなければ意味がありません。 実際の運用から落とし込み、設計していくのがベストだと思います。
最後に
いかがでしたでしょうか。すべてのシチュエーションに適用できるわけではないですが、ひとつの参考になればと思います。
一般的なデータ分析基盤の記事でデータセットの分割単位や命名規則まで触れているものがほとんどなく、手探りで相談しながら進めていたのですが、そこそこいいものができたのではないかと今は思っています。
ただしまだ運用は始まったばかりです。今後運用していく中で出てくる課題は多くあると思いますし、よりこれに沿った構築・運用をしていかなければなりません。 最近はモダンデータスタックといったものも出てきて、より改善もできるのではないかと思っています。
特にデータ基盤チームは本当にできたばかりのチームです。 僕自身も今まではSREチームのメンバーとして働いていましたが、今はデータ基盤チームとして働いています。
まだまだできることもいっぱいあると思いますし、やりたいこともいっぱいあります。 ご興味のある方がいらっしゃいましたら、ぜひ一度お話ししましょう!