dbt Projects on Snowflakeを本番運用するとしたら…を本気で考えてみた
今回は記事執筆時点でPublic Previewになっているdbt Projects on Snowflakeを本番運用するとしたら…について本気で考えてみたら dbt Projects on Snowflake を「完全に理解した」ので徒然なるままに書き留めておきます。
dbt Projects on Snowflakeとは?
一言で言うと、Snowflake上でdbtが実行できる機能です。
イメージを持ってもらいやすいようにめちゃくちゃスクリーンショットたっぷりの検証記事がいくつかありますので、そちらを参考にしてみてください。
ただ、実際にちゃんと使ってみると、大きく2種類の dbt Projects on Snowflake に分ける事ができることに気づきます。以下の2つです。
- スキーマオブジェクトとしての dbt Projects on Snowflake
- workspacesで動くタイプの dbt Projects on Snowflake
スキーマオブジェクトとしての dbt Projects on Snowflake
これは CREATE DBT PROJECT で作成できるスキーマオブジェクトで、一般的に dbt Project と表現する際にはこちらを指すのだと理解しています。明確に dbt project object と表現されればこちらで間違い無いでしょう。
詳細は後述しますが、 dbt project object の本質的な姿はdbtのコードの保管庫であると考えています。
workspaces で動くタイプの dbt Projects on Snowflake
ややこしいのですが、 workspaceでdbtを実行できる仕組みは dbt project object とは別物です。こちらはドキュメント上は「workspaces for dbt Projects on Snowflake」や 「workspace for dbt on Snowflake」 と表現されているようです。
workspaces版では基本的にSnowsightのworkspaceの中の機能でdbtコマンドを実行できます。
また、dbt project object に接続してコードをデプロイしたり dbt project object 自体を作成したりすることもできます。
workspace自体がファイルを保管できる一種のステージ的な役割を持っていますが、そこのコードをベースに dbt Projects on Snowflake の実行環境にアクセスしてコマンドを実行しているイメージです。
つまり dbt Projects on Snowflake って何物?
dbt Projects on Snowflake は dbt project object もしくは workspace にあるdbtのコードを実行するための基盤だと私は捉えています。
さらに dbt project object に関しては EXECUTE DBT PROJECT コマンドで単にdbtを実行するだけじゃなくてログやトレース情報も Event Table に保存してSnowsightを介して可視化する事ができる機能もついていたりします。
開発のライフサイクルを通して捉えると、workspace でdbtを開発して、そのコードを dbt project object としてデプロイして本番運用をする、そんなイメージです。
以下のように整理できます。
- workspace for dbt Projects on Snowflake
- dbtの開発環境
- dbt project object
- dbtのジョブ実行環境
dbt project object を本番運用したい!
そんなこんなで、今回のタイトルは「dbt Projects on Snowflakeを本番運用するとしたら…を本気で考えてみた」ということなので、この記事で取り扱うのは dbt project object の方です。
細かい仕様は今後GAに向けて、そしてGA後も継続的な改善が入ってくると思うので割愛しますが、本質のところは変わらないと思うので、本番運用する上で実際にはどう扱うのが現実的なのかということを考察していきます。
想定するデータパイプライン
簡単なパイプラインだとすでにある検証記事で十分な情報があるのであまり面白くありません。本格的な運用にも耐えうるものなのか?という疑問を解消するために、あえて捻ったパイプラインを想定します。(とはいえ、よくあるパターンではあると思います。)
今回想定するのは以下のような要件があるとします。
- 特定のデータ転送処理の完了を待ってdbtコマンドを実行したい
- 複数人で開発・保守をしている
これらを満たすためには以下が必要です。
- dbtのコードはGitHubなどのリモートのリポジトリで管理されている
- Snowflakeのtaskではない形で実行契機を管理する(cronトリガーではなくてイベントトリガー)
こんなパイプラインのdbt実行基盤として dbt Projects on Snowflake を採用しようとした際の考察をしていきます。
こんなアーキテクチャを考えてみた
本気で考えるので、開発のライフサイクル全体を考慮してCI/CDをどう実装するのかについても考察していきます。
- 開発環境
- なんでもいいよ(VSCodeのdevcontainerでも workspace for dbt Projects on Snowflake でもなんでもいいです。個人的にはできることの多いdevcontainer推し)
- コードリポジトリ GitHub (別に何でもいいけど、やっぱりGitHubだよね)
- CI/CD基盤
- GitHub Actions(別にCircleCIとかCodeBuildとかでもなんでもいいよ)
- dbtとSnowflake CLIを組み合わせて利用します
- ジョブオーケストレーション
- そもそもここをリッチなものにすると dbt Projects on Snowflake を利用する意味がないのでここは質素にさせてください。(dagsterとかはそこまで複雑な環境じゃないと運用が重たすぎる)
- ほぼサービスのコストがかからない Step Functions と ECS on Fargate とか Lambda ベースにした基盤
PoCは脱却するけど、ガチガチのデータオーケストレーションを運用するほどの規模じゃないくらいまでは使えるんじゃないかなという肌感覚ではいます。結構こんなパターンはありそう(というかこれで運用しようとしている)
CI/CD基盤の役割
CI/CDの役割は、ずばり dbt deps コマンドを実行した上で dbt project object に新しいバージョンとしてデプロイすることです。
なぜdbt depsを実行する必要があるのかについて解説します。
最初の方でdbt project object は本質的にはdbtコードの保管庫であると紹介しました。
これは実際に dbt project object を作成してみて DESCRIBE DBT PROJECT コマンドで設定を確認してみるとわかりやすいです。(この辺りは実際に試してみてください。)
ここでは、DECSコマンドでも確認可能な snow://dbt/my_db.my_schema.my_existing_dbt_project_object/versions/last
みたいなURIで表現されるdbt project object が持っている保管庫(「dbt project stage」と表現されたりする)にコードが保管されているという話を詳しくドキュメントから読み解いていきます。
また、ドキュメントの記述だとここが該当します。
Snowflake maintains versions of dbt project objects and their corresponding project files. You can use this versioning to track and manage changes throughout your data development and deployment lifecycle.
詳しくはドキュメントを読んでみてほしいのですが、dbt project object ではデプロイするたびにそこにバージョンの番号と共にdbtのコードが保管されるという事が書いてあります。
そしてもっと深ぼって動作確認も進めていくと、その dbt project stage にあるこのコードをそのまま丸っとコピーしてdbt実行環境で実行するという動作になっている事が見えてきます。
これは以下のような記載からも読み取れます。
- profiles.ymlが一緒にデプロイされる必要がある
- デプロイする前にdbt depsコマンドを実行しておく必要がある(外部パッケージを利用する場合)
大事なのは dbt deps を実行して dbt_packages を生成しておく必要があるという点です。
(一応ちゃんとドキュメントに記載もあるので引用しておきます)
You must execute the dbt deps command from within a workspace for dbt Projects on Snowflake or using the snow dbt execute command from the Snowflake CLI to build and populate the dbt_packages project folder. You can’t execute the deps command by using the EXECUTE DBT PROJECT SQL command. Alternatively, you can run deps on your local dbt project before deploying to Snowflake as a dbt project object.
これは小話的に聞いて貰えばいいのですが、「EXECUTE DBT PROJECTではdbt depsは実行できない」ような記述がありますが、実際には抜け道はあって、実行自体はできてログ自体も成功したとの表示は出るのです。ただし、その後同じ dbt project object に対して EXECUTE DBT PROJECT コマンドでbuildなどを実行した際にdbt depsが実行されていないというエラーが出ていました。(つまり実行はできるけど、その後環境がまたまっさらな状態に戻っているのです。実行しても意味ないから実行できないと表現しておいた方が誰も時間を溶かすことはないで、これは優しさだと思います。)
このことから、毎回クリーンな状態でスタートするアーキテクチャになっているということがわかりました。(個人的には GitHub Actions のランナー的な環境って捉えると近いかなと思います。)
そういうアーキテクチャなので、dbt depsを実行してdbt_packagesディレクトリが存在する状態でデプロイする必要があるのだと理解しています。
ちなみに、dbt depsを実行した後は、Snowflake CLI の snow dbt deploy コマンド でデプロイするのがオススメです。
まとめると以下のような処理フローのGitHub Actionsを作るといいと思います。
- mainにマージされてdbtの階層のファイルが更新されているのをトリガーにワークフローが起動する
- git checkout
- dbtのインストール
- dbt depsの実行
- Snowflake CLIのインストール
- snow dbt deployコマンドの実行
Git Repository って必要?
少し話は脱線しますが、CREATE DBT PROJECTのリファレンス をよく読むとデプロイする際のファイルを取り込む元として Git Repository stageを利用する事ができます。
ただ、実際の運用を考えると上記の dbt deps 問題があるので、個人的には workspace for dbt Projects on Snowflake を利用しないのであればGit Repositoryの準備は要らないと思います。
もういっそのこと Git Repository Stageからのデプロイは公式でサポートしてますという記載をなくしておいても健全かなと思っています。(もしくは将来的に勝手に dbt depsを実行してくれるようになったりするとかしてほしい)
ジョブ実行の仕方
ジョブの実行の仕方はシンプルに Snowflake CLI の snow dbt execute コマンド がオススメです。(ドキュメントがほぼdbtのリファレンスに飛ぶだけでかなり雑なので、実際の実行イメージを書いておきます)
# connectionのオプションは割愛
snow dbt execute my_dbt_project_object build --select @your_model_name
オプションは実際にインストールしてみて snow dbt execute --help
で表示してみてください。
非同期実行もできるよ
executeのオプションはそんなに多く無いのですが、非同期に実行するかどうかというフラグが設定できます。
つまり、呼び出しだけして成功かどうかは待機しないという形です。これも便利ですね。大きめのデータを扱うとかなりの時間を待つことになるので従量課金体系だと無駄にコストがかかってしまうだけなので、こういう機能があるのはとても経済的です。
非同期処理の場合はエラーになったかどうかをevent tableとかで取得したりする必要があるでしょうか?
この辺りはまだ検証できていないので、ぜひ皆さんの方で検証してみてください。
ヒントはここにあります(たぶん)
モニタリングが便利
ここまで読んでなんかめんどいな…と思ったそこのあなた!
非同期実行の話の中で少し触れましたが、モニタリング機能がしっかりしているところが dbt project object を利用する一番のメリットと言えます。
自前でそこのレベルのモニタリングの仕組みを作ろうとするとおそらくそうは簡単にいかないはずです。(せいぜいログを見れるくらい)
このレベルのモニタリングの仕組みを作ろうとするとがっつりdagsterなどの重ための仕組みをインテグレーションしないといけないのが厄介そうだとは思いませんか?
そんな面倒なことを考えずに気軽にdbt実行基盤を利用する事ができるという事自体がめっちゃありがたいのです。
今回はあえてちょっと複雑なdbtが組み込まれたパイプラインを想定していたのでややこしいなと思ったかもしれませんが、現実はtaskでcronベースで実行したりとかが基本になると思いますし、デプロイの仕方もworkspaceからGUIベースでdeployすることも可能なので小さく始めちゃう分にはとても簡単にスタートできる点も魅力です。
そこから進化してやや要件が複雑になってきたとしても、ちょっと手を加えるだけでそのまま利用できそうなレベルまで機能が提供されているのが dbt Projects on Snowflake のポジションどりの上手さかなと思いました。
細かい仕様というか注意点についての補足
もう少し細かいところにも触れておきます。
スキーマは専用のものがあるといいよ
モニタリングの機能をがっつり使うためにはスキーマ単位でログの設定などを変更する必要があるので専用のスキーマを用意しておくといいでしょう。
workspaceを使わない場合は超簡単だよ
workspace版を利用しないで今回のようなアーキテクチャを組む場合は以下のリソースなんていらないのです。
- GitHubのPATやSnowflakeのSecretオブジェクト
- Git RepositoryのためのSnowflakeの API Integration
- external access integrationやnetwork rule
最後に
dbt Projects on Snowflake を本番運用するということに真剣に向き合ってみた結果をまとめてみました。
私はサクッとdevcontainerで開発環境作っちゃいがちな人間であんまりworkspaces版はあまり刺さらない人種ということもありdbt project objectに寄った内容になりました。
実際にはメインのターゲットにはworkspaces版の方がありがたいものになるのかもしれないなと思ったりしています。
おそらくなのですが、dbt project objectはパブリックプレビュー段階にもかかわらず、近いうちに本番稼働をするために開発中のデータ基盤で利用してみようと本気で本番導入目指してインテグレーションをしている人間は私くらいなのではないでしょうか?(いたらぜひコメント残しておいてくださいw)
この記事が少しでも参考になったら幸いです⭐️
Discussion