Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。
この記事は、「BigQueryのデータ監視の社内サービスを作った話」の書き起こしです。
@hyrrot:株式会社メルペイ Data Management Team、Data Managerの髙橋です。「BigQueryのデータ監視の社内サービスを作った話」と題し、発表します。
自己紹介をします。髙橋宏文と申します。2022年より、メルペイでData Managerとして、メルカリグループのアナリストの皆さまに最強のデータ分析環境を享受していただくため、日々奮闘しております。
メルカリグループでは、データウェアハウスとしてGoogle BigQueryを利用しています。データウェアハウスに関わる主要なチームとして、二つのチーム「Data Platform Team」「Data Management Team」があります。
Data Platform Teamは、サービスデータベースやログからBigQueryにデータを届けるパイプラインの開発と運用を担当し、Data Management Teamは、データの利用者が安全に安心して簡単にデータを活用できるような仕組みやプロセス構築サポートを行います。
今回はData Management Teamの成果にフォーカスしてお話しします。
Data Management Teamは、データ利用者のデータ活用を促進するため、BigQueryのデータを整え、データ利用者に届ける仕組みを運用しています。
例えば、生テーブルを中間テーブルに変換するために、dbtを用いています。dbtの定期実行のための基盤として、Cloud Buildをはじめとした、GCPのマネージドサービスやArgo Workflowsなどを利用しています。
ある日、社内の複数チームから別々のリクエストをもらいました。どちらのリクエストも具体的な要件は異なりましたが、「BigQuery内のテーブル内のデータが正しくないときに通知が欲しい」というものでした。
一方のチームでは、「BigQueryのテーブル内のデータを用いて、顧客企業に対する経費精算を行っているが、テーブルのデータがクエリの前提条件を満たしていないときに、それを検出したい」、もう一方のチームでは、「BigQueryテーブルのデータを用いて、お客さまに対してポイントの付与オペレーションを行っている。テーブルがポイントの誤付与が発生したことを示すようなデータを含む場合、それを検出したい」という要求がありました。
このような要求に簡単に応えるサービスは、社内にはまだありませんでした。
リクエストをもらった2チームの依頼に応えるため、また、今後他のチームから同様の依頼を受けたときのために、全社で利用できるBigQueryデータの監視システムを作ることにしました。このようなシステムは、「BigQuery内のデータが正しくないときに通知が欲しい」という要求に応えるものとなるでしょう。ここで言うデータの正しさとは、監視対象のデータに依存するものとなります。
ここでは、データのドメイン条件を熟知しているそれぞれのチームに、データが正しいとみなされる場合に0行の結果を返し、正しくないとみなされる場合に、1行以上の任意の結果を返すクエリを作ってもらいます。
監視システムはそのクエリを実行し、1行以上の結果が返ってきた場合、およびクエリの実行に失敗した場合にチームに通知するようにします。このような仕様を持つ監視システムを作り、それにQueryMon(クエリもん)という名前をつけ、社内に展開することにしました。
QueryMonの最初のバージョン1.0を、Argo Workflows上に実装しました。まず、クエリ実行のプロセスを管理するWorkflowTemplateを用意します。このプロセスは、パラメータとしてService Account名、実行するクエリ、通知先となるSlackチャンネル名などを受け取り、指定されたService Accountにimpersonateしてから、クエリを実行します。
その結果が1行以上、あるいはクエリの実行に失敗した場合に、Slackチャンネルにメッセージを送信します。CronWorkflowは、WorkflowTemplateのパラメータの実際の値を持ち、また指定された時間にプロセスを実行する役割があります。
このシステムはシンプルですが、いくつか問題点があります。
まずは、何らかの原因で監視が行われるべきタイミングで、実際行われなかったという場合に、それを知ることができない点です。データに問題があった場合、チームが問題を見逃してしまうリスクに繋がります。
次に、監視設定の変更に対して、QueryMon管理者のレビューを必要としていた点です。監視設定は、Argo Workflowsのリソースとして表現され、このリソースは社内のC/ICDシステムを経由して、変更するように設定されており、それがQueryMon管理者のレビューと承認を必要としていました。
QueryMonとその管理者は、データのドメイン知識に関与しないので、この監視設定変更の権限をチームに委譲するのが望ましいです。
また、Argo Workflowsを運用するチームが私たちとは別のチームであったため、トラブルシューティング時のコミュニケーションコストが上がる点も厄介でした。
それらの問題を解決するバージョン2.0を開発することにしました。
GCPのCloud Scheduler、Cloud Pub/Sub、Cloud Functions、Datadogを利用して実装しました。チームはそれぞれ独立したGCPプロジェクトを持ち、その中にチーム名、クエリ名、クエリ、サービスアカウント名、BigQueryの実行プロジェクト、タイムアウト時間の情報をJSON形式として、QueryMonのPub/SubトピックにpublishするCloud Schedulerのジョブを用意します。
チームが所有するプロジェクト内のリソースは、チーム内のメンバーのみの承認で変更できるようになっています。QueryMonは、そのPub/SubトピックがトリガーとなっているCloud Functions関数を持っています。
この関数は、トピックにpublishされた情報に含まれるService Accountにimpersonateし、クエリを実行します。さらに、クエリの実行結果をメトリクスとしてDatadogに送信します。
Datadogは、クエリ結果の行数が1行以上である場合、失敗した場合、および開始結果が一定時間存在しない場合に、Slackにメッセージを通知するように設定しています。
このシステムでは、Cloud Schedulerのジョブが、Pub/Subトピックにメッセージをpublishする必要があります。元々Cloud Schedulerは、Pub/Subトピックにpublishするジョブをサポートしていますが、このシステムのように、SchedulerのジョブとPub/Subトピックが別のプロジェクトにある場合は利用できないようになっています。
今回は、SchedulerからPub/Subのpublish HTTPS APIを呼び出すことで、この問題を解決しています。
Pub/Subトピックのpublish APIは、publishするデータをBASE64エンコードしたものを、パラメータとして受け取ります。
Cloud SchedulerのUIで、このような設定を直接管理するのは困難であるため、Terraformを利用して管理することにしました。
具体的には、図の赤文字で記載されたように、Terraformの関数を利用し、BASE64エンコードされたJSON形式のデータ構造を作成します。これにより、Terraformリソースのコードを通じ、人間にとってわかりやすい形で監視設定を確認できます。
次に、Datadogにmonitorを設定します。monitorは、QueryMonから送られてきたmetricの条件が成立したときに、Slackにメッセージを送るように設定します。
例えば、1行以上データが返ってきたときは、querymon.monitor_result.returned_row_countというmetricの値が0より大きくなります。スライドに記載のDatadogクエリを用いて、メッセージを送信する条件を指定できます。
Datadogクエリに、クエリ名とチーム名を条件に加えることで、特定のチームとクエリだけを選択的に通知の対象とします。また、クエリの実行に失敗したことを検出するために別のmetricを用意しており、上記と似た方法でmonitorを設定しています。
さらに、このmonitorの評価と対象となるmetricが、一定時間存在しない場合にalertを発生させることで、監視が行われていないことを検知できるようにしています。
Ver.2.0は1.0と比べて、複数の点が改善されました。DatadogのAlert Conditionの機能を活用し、監視が行われなかったことを検出できるようになったという点。監視設定をチーム内所有のCloud Schedulerに持つことにしたことで、チームが監視の設定を自分たちで変更できるようになったという点。DatadogがサポートするSlack以外の通知先も設定できるようになったという点。別チームの管理であった、Argo Workflowsを利用しなくなり、トラブルシューティング時のコミュニケーションコストが軽減された点です。
一方で、未解決の問題も残っています。一つは、チームが所有していないService Accountを利用し、任意のクエリを実行できてしまう点です。
QueryMon2.0は、Pub/Subトピックから渡されたデータに含まれるService Accountの権限を使ってクエリを実行します。あるチームが自分たちの責任範囲外のService Accountを用いることを拒否できません。
これにより、セキュリティレベルの高いデータを漏えいするリスクを軽減するために、いくつかの対策を行っています。
まずはPub/Subトピックのpublish権限を事前に申請されたチームのService Accountのみが持つことにしていること。次に、QueryMonがテーブルのデータそのものを扱わないことです。
監視に必要な情報は、クエリが成功したか、成功した場合に返ってきた行数は何行であるかのみです。BigQueryのquery APIをmaxResultsパラメータに0を指定して呼び出すと、クエリの成功失敗と結果の行数を返し、データそのものを返さない挙動となります。これは前述の仕様に合っており都合がよく、そのようにしています。
今回は、BigQueryのデータが正しくないことを検出したいという複数の要件を叶えるため、BigQueryのデータを監視する仕組みを作り、社内に展開した話をしました。同様の課題を持つ皆さまにとって参考となりましたら、嬉しく思います。
本日はありがとうございました。