Beatrust で SRE をやっている Yuta(中川 裕太)です.運用がラクにできように色々と改善したり,セキュリティ向上したり,インフラ作ったり API 開発したりしています. 今回のブログでは,データガバナンスをもってセキュアにお客様のデータを扱いつつ,データ分析者にとっても使いやすいことを目指して実装してきた Beatrust のデータ分析基盤について紹介します.
モチベーション
Beatrust では組織の中にある人びとの情報の構造や,協業に至るまでのプロセスに着目して BtoB SaaS を開発しています.まだ誰も答えが分かっていない領域で PMF を目指す中で,プロダクト上でそれぞれのユーザはどういった行動を取るのかということは学びの宝庫となっています.例えば,ユーザのある行動を誘発したくて開発を進めた機能が別の使われ方をして,むしろそちらの使い方の方がお客様にマッチしているケースなどがあったりしました.ある種 BtoC 的な視点で,ユーザ行動を分析しつつプロダクトの優先順位や方向性を決めたり,新しい機能の着想を得たりしています.まさにデータ分析がお客様のサクセスに直結するようなサービスとなっています.一方で,お客様の個人情報を扱うサービスでもあるため,むやみやたらに分析することはできず,データガバナンスをもってセキュリティを担保した上で分析する必要があります.しかし,セキュリティに過度に重きを置いた結果,分析がしにくくなりデータの価値を利用できなくなってしまっては元も子もありません.そこで,セキュアにかつ使いやすい分析基盤が求められます.具体的に言うと,生データは原則閲覧できないけど,メンバーの権限に応じて,匿名化されたデータを自由に分析できたり,統計処理されたデータのみを利用できたりなど,メンバーとデータ種別に応じた権限を自然な形で分けれるようにする必要があります.
Beatrust には創業間もないうちから簡易なデータ分析のための機能は存在していました.ユーザの UI 上での行動をログに出力し,静的な情報である DB と合わせて一日に一回匿名化した上で DB に dump して redash から分析するというものです.データのガバナンスと分析しやすさを考えた際,この簡易な仕組みでは賄えなくなってきたので,データ分析基盤を利用するメンバーも増えてきた今のタイミングでそれらを両立できるようなアーキテクチャに移行しました.今回のブログでは,そのアーキテクチャについて紹介していきます.
セキュアで使いやすいデータ分析基盤
メンバーとデータ種別に応じた権限管理が容易であることと,将来的にデータが増えていった際にも対応できるという理由から,下図のような BigQuery をベースとしたアーキテクチャを採用しました.
このアーキテクチャの主なポイントとしては3つあります.
- DBとログをそれぞれ external query とsink で BQ へ連携する.
- 各種データセットは Google Workspace の group と紐付けて権限を管理する.
- データパイプラインをすべて BQ 上に実装し承認済 view で権限をつなげる.
データ分析基盤の工夫点
上記で紹介したアーキテクチャのポイントについて,それぞれ設計思想や工夫点などを紹介していきます.
BQ へのデータ連携
静的な情報である DB と動的な情報であるログをそれぞれ external query と sink で BigQuery へ連携しています.
DB 同期
なるべくマネージドサービスに寄せていった方が開発運用面でラクができるだろうという考えから,external query を使って BQ に閉じた世界で Cloud SQL から BQ へ連携できるようにしました.また,同期は scheduling query で一時間に一回同期するようにしています.scheduling query を使わず view にすることで,リアルタイムでの DB 同期は可能になりますが,そもそも DB に溜まっている情報はある程度静的であることと,データガバナンスの観点から scheduling query を選択しました.データガバナンスの観点を補足すると,view で external query を実行すると,実行者の権限でデータを閲覧できるかが決まるため,データ分析を実施するメンバー全員に本番 DB の読み取り権限を与える必要があり,セキュアな分析を目指す上で現実的ではありませんでした.また,view の場合は分析クエリが走る度に本番 DB へアクセスが発生しますが,scheduling query では一時間に一回だけになるので,本番 DB への負荷が予想できるようになったことは嬉しい副効果です.
ログ連携
こちらも DB 同期同様にマネージドサービスに寄せていくため sink で直接同期するようにしました.他に Cloud Logging から一旦 GCS に sink でログを流した後に BQ へ流し込む定期バッチを実装するなどの方法も考えましたが,最終的には直接 sink することの制約を飲んで開発運用のラクさを選択することにしました.制約について具体的にあげると,ログのパーティションテーブルを作った際のキーがログの timestamp
フィールドになってしまう点と過去に取り込んだログとスキーマ不一致を起こした際にレコードが欠損する点です.前者については DWH の view 側で timestamp
を使うことで正しくパーティションキーが使われるようにしました.後者については exports/error_count
として欠損したログ数のメトリクスが得られるため,それを監視するようにしました.これらの工夫によって,制約についてはある程度緩和できたかなと考えています.さらに,ログレコードの重複が数%程度発生しているようだったので,重複を排除するような view も実装しました.また,sink を採用したことで,ほぼリアルタイムで動的な情報であるログを連携できるようになりました.
なお,sink は設定した時刻から Cloud Logging のログを BQ に連携させるため,過去ログについては自身でスクリプトを書くなりして BQ に import する必要があります.Beatrust のログスキーマが歴史とともに変わってきたこともあり,非常に苦労したポイントでもあります.ここについては「レガシーなデータ分析基盤の移行」というテーマで機会があったら紹介していこうと思います.
データセットの権限管理
生データや匿名化データ,DWH,データマートなどといったデータ種別の単位でデータセットを分けることでデータ種別単位でのデータガバナンスを効かせられるにしました.さらに,それぞれのデータセットに対して Google Workspace の group と紐付けて管理することで,自然と不便なく使える実装としました.こうすることで,例えば,匿名化されたデータの閲覧権限を持つメンバーと統計処理されたデータマートだけの閲覧権限を持つメンバーを Google Workspace の group 単位で管理することができます.つまり,新しいメンバーが増えた際も権限に応じた group に所属させるだけで適切なデータの閲覧権限を持つことができデータガバナンスのコントロールが容易になります.また,データ分析基盤の利用者側の観点で見た時には,自身の Google Workspace のアカウントでログインしてしまえば,適する閲覧権限が付与されるため,特に不便を感じることなく分析してもらうことが可能になります.
データセットと Google Workspace の group との紐付けは以下のような json を github 上で管理するようにしています.権限の変更などはレビュー時にチェックすることで誤った権限付与などを防いでいます.
[ {"role": "WRITER", "groupByEmail": "dev-admin@beatrust.com"}, {"role": "WRITER", "groupByEmail": "lab-admin@beatrust.com"} ]
権限管理については,ある種厳密にやりたくて,もともとは terraform で管理していました.しかし,データ分析に関わるメンバーがデータセットを追加したり権限を編集する必要が生じた際に terraform を書いてもらうことのハードルが高く今は json で管理する方法に変えました.
BQ 上でのデータパイプライン
上記のように生データから匿名化データ,DWH,データマートとデータを伝播していくデータパイプラインを実装するにあたり,view でつなげたり,scheduling query を使ったり,実行順番が重要な場合はジョブ管理ツールを使う方法などいくつかの方法が考えられます.Beatrust では,BQ の実行コストはややかかる可能性はありつつも SQL を書くだけで開発もデバッグも容易にできる view でつなげる方法を選択しました.一方で,この方法を選択した場合,つながれた各種 view はクエリを実行したメンバーの閲覧権限で実行されるため,1つの view でも閲覧権限がないとクエリは失敗してしまいます.そのため,結局すべての view に対する閲覧権限をデータ分析に関わる全メンバーが持つ必要が出てきてしまいます.これでは現実的ではないため,承認済み view を使って権限をつなげるようにしました.具体的には以下のような json を用いて
[ {"view": {"datasetId": "dwh__evt", "projectId": "beatrust-all", "tableId": "event"}}, ]
データセットの権限同様 github で管理するようにしています.こうすることで,データ分析基盤の利用者は自身が使いたい view の権限だけを意識すれば,適切に権限がつながり目的のデータが自然に閲覧できるようになります.
最後に
Google Workspace の group で各種データセットの権限管理をし,承認済み view で権限をつなげることで,利用者は特に意識することなくデータガバナンスをもってセキュアに使えるデータ分析基盤を構築しました.設計思想的に BQ に閉じた世界で実装できることをかなり意識していましたが,やりたいことのほぼほぼ全てが BQ の世界で閉じますし,データ量がある程度多くともかなり高速にクエリ結果を返してくれる BQ は改めてデータ分析界の革命児なんだなということを実装する中でまざまざと思い知りました.
これからは今回作ったデータ分析基盤を触媒にして如何にプロダクト成長を促進していけるかが勝負だと考えています.そんな楽しい勝負を一緒にできる仲間を募集中です!
今回はデータ分析基盤のアーキテクチャにフォーカスを当てた記事となりましたが,次回はデータ分析基盤上でどのように分析クエリを管理していくかについてブログを書こうと考えています.今回の内容よりも分析側に寄った話とはなりますが,いろいろと悩みながら設計思想を固めていった部分も多くあるのでぜひ読んでいただければと思います!