挨拶
どうも!BaseconnectのBIチームに所属してます。おこどんです。
弊社BIチームは ユーザー行動のログ化 <=> データ収集・蓄積 <=> データ可視化・分析
までの領域を社内で担当しております!
担当領域の都合から、クライアントサイドログ収集関連リソース
, ETL
, データレイク
, データウェアハウス
, BIツール
などなどデータ分析基盤周りのインフラリソースの作成と管理も担当してまいりました。
立ち上げから2年ちょっとの歳月が経ち構成も一旦落ち着いたので、弊社の分析基盤周りの構成の歴史・変遷を今回記事にすることとしました!
(※社員1人インターン1,2名のチームでずっと作ってきたため、人的リソース依存の課題感や技術選択があります。ベストプラクティスの参考としてではなく、失敗の歴史を温かく見守ってもらえたら幸いです)
黎明期(2020/02~)
〜データレイクという概念の不在〜
どのような変更を加えたか
パフォーマンス監視及びReact製SPAのフロントログ収集を目的としてElasticAPMを導入しました。
- APMのサービスエージェントのログにアカウント情報を載せて、バックエンド・フロントエンド共通のロギングツールとして運用しました。
- 尖った使い方だと思うので、これは別で記事化出来たらと思ってます。
- APMのサービスエージェントのログにアカウント情報を載せて、バックエンド・フロントエンド共通のロギングツールとして運用しました。
ETLツールのLogstashをEC2内で運用しました。
- 弊社がストレージ用途としても活用しているElasticsearchのデータをDWHに転送しました。
- ElasticAPMによって収集されたクライアントサイドユーザーログをElasticsearchからDWHに転送しました。
- 弊社のアプリケーションのメインDBであるNeo4jのクエリAPIから取得したデータをDWHに転送しました。
ETLツールのembulkをEC2内で運用しました。
- アプリケーションで活用しているRDS内のデータをDWHに転送しました。
DWHにBigQueryを採用しました。
BIツールにTableauを採用しました。
この構成になった理由
分析基盤の構成自体が存在しなかった状態で入社して「数ヶ月以内に何かデータが見られるようにする」ことを目標にしていました。 1人目データ人材として入社しており、データが見られるようにしないと存在価値を発揮できないと考えていた焦りと当時の経験不足故にデータレイクなんてものは存在していませんでした。
ETL
- 国内では珍しいかもしれませんがfluentdではなくLogstashを採用しています。
- 弊社はElasticsearchをストレージ目的としてもかなり活用しており、Elastic社のデザインパターンであるELK構成で推奨されているLogstashの採用をした方が、何かと良いことがありそうと考えての採用でした。
- 現在の感想は「fluentdでもLogstashでもどっちでも良いなあ」です。
DWH
- マネージドで1人体制でも管理が楽そうな点とパフォーマンスなどについて評判が良かった点から、クロスクラウド構成にはなりますが、RedshiftではなくBigQueryを選択しました。
ログ生成
- バックエンド, フロントエンドの両アプリケーションのパフォーマンス監視ができるツールの検討が社内で既に行われており、ElasticAPMのreactエージェントであればページ遷移やコンポーネントのマウントまでをログ化可能なことが技術調査されていたので、その導入とカスタムログの作成などを行いました。
この構成で得られた学び
APM as ログ基盤構成について
「APMツールのログにアカウント情報を付与してユーザー行動ログとして扱ってみる」というほぼ前例が無いAPMツールの使い方をしてみました。
- フロントエンド、バックエンドで同様の形式のログが発行されて加工などが楽な点
- ログの格納場所が統一され、パイプラインの数が1つで済む点
などなどプラスポイントもあったので、この使い方はそこまで悪くなかったのでは?と考えています。
データレイクが無いと
日ごとに取り込んだテーブルに*_YYYY_mm_dd
のようなsuffixを付けて全て保存して、BigQuery内に擬似的なデータレイク層を作っていました。
dbtやdataformのようなデータモデリング技術を導入できていなかったので、BigQueryのスケジュールクエリでデータレイク=>データウェアハウスの変換を全て書いており、保守もしづらくカオスな状態でした。
データレイク作成(2020/06~)
どのような変更を加えたか
GoogleCloudStorageをデータレイクとして採用して、ETLのデータ輸送先をBigQueryからGCSに変更しました。
GCS to BigQueryの転送はCloudDataflowで行いました。
- CloudDataflow内の定義はApacheBeam JavaSDKで記述しました。
CloudDataflowのジョブをキックするための関数をCloudFunctionで作成しました。
Cloud Functionの定期実行はCloudSchedulerからCloudPubSub経由でメッセージを投げる形で起動させました。
この構成になった理由
何やらデータレイクなるものがあれば先述したBigQueryのカオスな状態が解決されるらしいとのことで、BigQueryとの親和性が高いGCSをデータレイクとして採用しました。
データレイク => データウェアハウスのデータ輸送はCloudDataflowで行いました。DataTransferServiceなども考慮したのですが、Transform処理(データのマスクなど)を挟むことが出来る点や動的に取得元テーブルを宣言できる点などから、Cloud Dataflowに軍配が上がった形です。
CloudComposer高すぎ問題
Cloud Dataflowの実行にCloudFunction, CloudPubSub, CloudSchedulerの3リソースの構成をわざわざ組まなくても、DataflowのマネージドサービスであるCloudComposer使えばいいじゃんと思われるかもしれません。
Cloud Composerを使わなかった理由は試験的に運用してみたらとても高かったという金銭的な理由からです。 CloudComposerの使い道が当時はデータレイク<=>DWH間の輸送の用途しかなかったため、TooRichだと感じて採用を見送りました。
この構成で得られた学び
やりたいことが実現できる技術 < 理解しやすい技術
にしないと属人化が進む- DataflowをApacheBeam JavaSDKで書いたのですが、難しくて保守しづらいものにしてしまったのが失敗だと感じています。
- PythonSDKには存在しない
NestedValueProvider
オブジェクトを使って、動的にパラメータを取得してコード内に反映する実装をしたいがために、pythonではなくJavaを選択しており、キャッチアップが難しい技術選択をしてしまったと感じています。 - 導入をした僕と当時のインターンの2人だけがApacheBeamパイプラインを作れるが、後からジョインしたインターンメンバーなどはパイプラインを作れないといった状況になり、同じチーム内でも技術格差が生まれてしまいました。
データレイクができて感じたメリット
- GCSに日付ごとのマスターデータを格納して、BigQuery内のデータは最新のテーブルのコピーを持つ形としたので、BigQuery UI上でのデータの一覧性が著しく上がりました。
- マスターデータをBigQuery上で持つ形では無くなったため、元の構成に戻せる安心感を持ちつつ、立ち上げ時のぐちゃぐちゃな構成のBigQueryに対して、データセットの整理やパーティショニングなどの構成変更を行えるようになりました。
- DataflowのETLの段階で個人情報にあたるものなどに列単位で閲覧制限をかけることで、BigQueryの権限を他者に渡しやすくなりました。
dataformの導入 (2021/01~)
どのような変更を加えたか
DWH内のデータモデリングツールとしてDataformを採用しました。
- Dataformを使うことで、BigQuery内でダッシュボード表示や特定の計算を走らせるためのテーブルをデータマート層として定義しました。
BigQuery内の100個くらいあったスケジュールクエリを根絶しました。
Dataformを使うことで依存関係が明示的に示され、複雑なロジックも保守性が高い状態で書くことができるようになりました。
- コード管理されるおかげで、SQLのレビューも徹底されるようになりました。
この構成になった理由
確か当時「DataformというBigQueryを便利にするツールがGoogleに買収されて〜」みたいな話を聞いて、こんな便利なものがあるのかと感動して導入を決定したと思います。
- 恥ずかしながらデータモデリングツールという存在をこのタイミングで初めて認知しました。
- なんでdbtじゃないの?という疑問が湧くと思いますが、純粋にdbtをこの時知らなかったので選択肢にも上がりませんでした。
スケジュールクエリでのDWH内データ変換が地獄すぎた。
- スケジュールクエリは一覧性が悪く、管理もしづらく悩みの種でした。
この構成で得られた学び
データモデリングはBIの最重要業務。良いこと尽くし
- 複雑な定義のKPIなどのテーブルも、テーブルやViewに分割することで理解及びレビューをしやすくなる。
- 更新タイミング、Table化、View化などの管理すべき項目が全て定義可能。
- テストを書くことで、データ欠落やロジックの意図せぬ変更などを補足可能。
- テストユーザー除外処理やタイムゾーン変更処理などの共通する処理を作ることで、今後の開発の高速化に繋げられる。
dbtでもdataformでもどっちでも良さそう
- 1年以上dataformのSQLX書きまくってますが困ってないので、どっちでもやりたいことできるんだろうなあと思ってます。
- ただdbtのユーザーコミュニティの盛り上がりは羨ましかったです
事件:Neo4jがREST APIを廃止 (2021/06~)
アプリケーション開発の都合から、弊社アプリケーションのメインDBであるNeo4jがver4.0に更新されたのですが、この更新によってboltプロトコルによる通信のみが許可される形となり これまで活用していたREST APIが使えなくなることになりました。
手持ちのETLツールであるembulkやLogstashなどではboltプロトコルによるNeo4jからのデータ取得をサポートしてくれるようなものは存在せず、既存のETLツール以外の何らかのデータ取得手段を作成する必要が発生してしまいました。
データレイクお引っ越し・分散処理・インフラのコード管理(2021/09~)
どのような変更を加えたか
- AWS内でBIのデータエンジニアリングに関するリソースを別アカウントに切り出しました。
Terraformによる全BIリソースのコード管理を実施しました。
- IAM, ネットワーク, ETL, データレイクなどのコード管理をしました。
ETLツールをAWS Glueに一本化しました。
- Neo4j ApacheSpark connectorを使うことで、Neo4jからのデータ取得を可能としました。
- GlueのSpark定義ファイルはScalaで記述する方針としました。
データレイクをGCSからS3に変更しました。
この構成になった理由
BIリソースの別アカウントへの切り出し
Terraformによるコード管理
ETLとしてGlueを採用
- Neo4jからのデータ取得が可能なドライバーがApacheSparkくらいでしか見つけることができず、ApacheSparkを動作させられる環境が必須要件でした。
- 管理するコストはできるだけ少なくしたいため、フルマネージドなサービスを検討しました。
- ETLツールは複数あるとキャッチアップコストや管理コストがかかると考え、 ETLを全てGlueに統一することにしました。
- ApacheSparkが動作環境になるので、ほぼ全てのデータソースへの接続が可能となりました。
- ETL処理の分散処理化
- データが大きすぎてETLが動かなくなるといった事故が時々起きていたのですが、スケーラブルな分散処理にすることで防止しようと考えました。
- pysparkだとできないことがあったり、Scalaを触ってみたかったり、pythonだとDataframeの変換の時にパフォーマンスが良くないらしいとの噂を聞いたのでScalaでコードを書く方針とした。
データカタログの作成
- データレイクに格納されたデータはGlueCrawlerによってカタログテーブルに登録する方式としました。
- カタログテーブルを指定してデータ輸送ができるので、Glueのデザインパターンに寄せたコードを書くことができるようになります。
データレイクをS3に移行
この構成で得られた学び
Glue高い
- AWSはDPU (DataProcessingUnit) の起動時間に比例して課金されます。
- プロセスの立ち上がりにも結構時間がかかるので、小さいボリュームのデータ輸送であっても、立ち上がり時間などを考慮すると結構な金額が発生することになってしまいます。
- マネージドサービスなので覚悟はしていましたが、Logstashやembulkの維持費と比較するとかなり高額なため、ワーカー数のチューニングや取り込み回数の見直しなどの考慮点が新しくできました。
Spark難しい
ETLツールを1つに統一したことに意味はあったのか
- ETLという役割を複数ツールで実行するのではなく、スケーラブルでマネージドな1つのリソースにまとめたら無敵なのでは?と考えたのですが、先述した料金の問題などを考えるとそこまでのメリットを感じられていないのが現状です。
- 管理コストというか意識するべきことが減ったので、少人数でも基盤の運用はしやすくなったことは明確なメリットとして感じています。
Terraform鬼便利
Lookerの導入 ( 2021/12 ~ )
どのような変更を加えたか
- BIツールをTableauからLookerに変更しました。
この構成になった理由
データ基盤が一定整ってきたが、ビジネスサイドのメンバーでSQLを叩けるメンバーはおらず、データ活用をしているとは全く言えない状態でした。
- ダッシュボードや分析レポートなどは全てBIチームが出力している状態でした。
いざビジネスサイドに活用してもらおうと考えても「BigQueryデータの整理」「データにラベリング」「テーブルの関係性の説明」「SQL講習の実施」など途方もない道のりでした。
Lookerによるデータラベリングと探索環境の提供によって、これまでできなかったデータ活用を推進できると考えました。
この構成で得られた学び
Lookerの圧倒的なビジネスインパクト
- Tableauを使用している時は「使えるようになりたい」と名乗り上げるメンバーも現れなかったのですが、Lookerでの日本語ラベリングされたデータと探索環境を紹介することで、データ探索希望者が複数人出てきました。
- これまでどんなアウトプットであれBIチームが手を動かしていたのですが、LookMLを作れば作るほど、データ探索者が自身でアウトプットできる環境が整うため、BIがより本質的な業務に集中できるようになりました。
- 実際にデータを触ってもらうことで、「こんなものも見れるようにならないか」とBI以外のメンバー発信による環境作成依頼が来るようになりました。
Looker導入の工数
- Looker定義用ファイルであるLookMLを書いていくのに時間がかかると考えていたのですが、そこまで時間はかかりませんでした。
- 事前にDataformを活用することで、データモデリングをある程度のレベルまで行えていたからだと思います。
- Looker定義用ファイルであるLookMLを書いていくのに時間がかかると考えていたのですが、そこまで時間はかかりませんでした。
LookMLは考えることがいっぱい
まとめ
弊社データ基盤のNext To Do
データ発生からデータ閲覧可能になるまでの時間の短縮
リバースETL
- BIチームでは、弊社内で製造したデータを統計的に評価するモデルなんかも作成したりしています。 モデルの評価結果なんかをサービスに還元するようなリバース ETLのような機能の立案と構成作成には挑戦してみたいです。
データガバナンス
- 「誰がどのデータを見られるべきか」といった権限設計は作り切れておらず、どのメンバーが見ても問題がないデータのみを提供している状態です。
- データガバナンスの設計をしっかりとして、アクセスするべき人が自らの意思決定のために必要なデータにアクセスできるような、権限管理の設計は詰めていきたいです。
BIはいいゾ
今回の記事で紹介した通り、BIという領域に絞っただけでも
GCP/AWSの基礎的なリソース
, SQL
, ApacheBeam(Java)
, ApacheSpark(Scala)
, Dataform
, Terraform
, LookML
などの様々な技術が弊社内では使われています。
最近ホットな領域であるため、新しくやるべきことが次から次に出てきて楽しいです。
読者の方々もこれを機にBIのエンジニアリング部分に興味を持ってみてはいかがでしょうか?
(まだまだやりたいことはありますが、リソース的に限界なので、興味ある方は是非採用ページから応募してください)