🙆‍♀️

dbt x Snowflake x GithubActions 構成例

2022/03/16に公開

概要

https://www.youtube.com/watch?v=snp2hxxWgqk

Snowflakeをdbtで管理する
GitActionsでCI/CDを行う

そんな動画がYoutubeにありました。その中に、非常に参考になるものがあったので、こちらを調べてみたいと思います。

https://github.com/randypitcherii/cloud_cost_monitoring
こちらが動画内でデモにも使われていたレポジトリ

動画の説明

CIとは

  • DEV : 開発者がブランチで作業する際に使用
  • TEST : ブランチが承認される前にコードを配置し、テストするために使用される
  • PRD : エンドユーザが使用。マスターブランチで公開

Automation with Github Actions

dbtを用いる。dbtは、ELTツールで取り込んだRawDataを変換するツール。

EL(T)ツールとして、Fivetranで、データを DWH(Snowflake)に投入し、それをT(Transform)するのがdbtでマートなどを生成する。

Hans-on with Workflows

Production deployment from master

https://github.com/randypitcherii/cloud_cost_monitoring/actions/workflows/ci_prod.yml
こちらは、masterブランチにマージされて、本番環境にDeployするワークフロー
レポジトリ的には workflows/ディレクトリに存在している。

https://github.com/randypitcherii/cloud_cost_monitoring/actions/runs/30786133/workflow

  • masterブランチにPushされた時に起動
  • envにて環境変数をセット
    • targetは、prod
    • PASSWORDなどは secrets に入れてる
  • jobs : 起動するDockerイメージ(?)
    • dbt run --profiles-dir ./ci_profiles
    • dbt test --profiles-dir ./ci_profiles

Scheduled production run

こちらは、GitActionで定期的にDeployするワークフロー
レポジトリ的には workflows/ディレクトリに存在している。

https://github.com/randypitcherii/cloud_cost_monitoring/actions/runs/47803001/workflow

  • 起動は、cron ( '0 */1 * * *' # Run every hour )
  • envにて環境変数
    • targetは "prod"
  • jobs :
    • dbt run --profile-dir ./ci_profiles

Test deployment from a PR

https://github.com/randypitcherii/cloud_cost_monitoring/actions/runs/30785503/workflow

target : test になっている。
jobsの中で

  • export DBT_PROFILE_SCHEMA=pr_$(date +%s)
  • dbt run --profiles-dir ./ci_profiles → target=test
  • dbt test --profiles-dir ./ci_profiles → target=test

Pull-Requestをなげたら

「Test deployment from a PR」ワークフローが発火して、テストが走る。
この際テストが動くスキーマは、下記のようになる。

  • PR_20220102_REPORTING
  • PR_20220302_STAGING

で、テストが通ったら、masterブランチにマージボタンが有効化して、マージができるようになる。

Generate Docs

$ dbt docs generate --target prod && dbt docs serve

こちらで、dbtドキュメントを生成し、webサーバを立ち上げる。
http://127.0.1

dbtプロジェクトの構成

  • ci_profiles
    • profiles.yml
  • macros
    • get_custom_schema.sql
  • models
    • reporting
      • reporting.yml
      • snowflake_rolling_sum_of_usage.sql
    • staging
      • aws
        • aws.yml
        • stg_hashmap_aws_costs.sql
      • snowflake
        • snowflake.yml
        • stg_hashmap_snowflake_daily_usage.sql
        • stg_hashmap_snowflake_usage.sql
  • snowflake_setup
    • service_accounts
      • dbt_prod.sql
      • dbt_test.sql
      • singa_computing.sql
    • cloud_cost_monitorging_base.sql
    • teardown.sql
  • tests
    • staging
      • snowflake
        • asser_usage_for_every_day.sql
  • workflows
    • ci_prod.yml
    • ci_test.yml
    • scheduled_prod.yml
  • dbt_project.yml

という構成になっている。

ci_profiles/profiles.yml

https://github.com/randypitcherii/cloud_cost_monitoring/blob/master/ci_profiles/profiles.yml

target: "{{ env_var('DBT_PROFILE_TARGET') }}" となっているので、 workflowによって、prodtestが設定される。

macros/get_custome_schema.sql

macros/get_custom_schema.sql
スキーマ名を独自のものに変更するマクロで上書きをしている。

  • デフォルトスキーマは、target.schame
  • custom_schamaが設定されていなければ、デフォルトスキーマ
  • もし、target=prodなら、カスタムスキーマ名
  • それ以外の環境なら デフォルトスキーマ名_カスタムスキーマ名

models

staging/snowflake/snowflake.yml

models/staging/snowflake/snowflake.yml
freshness:
    warn_after: { count: 24, period: hour }
    error_after: { count: 48, period: hour }

※error_afterは、解説のために私が追加。

freshnessでは、「現在の時刻とデータの時刻がこれだけ離れていたら警告/エラーを出す」という定義をしている。
24時間以上前ならば、警告
48時間以上前ならば、エラー
を通知する設定となっている (※通知? Deploy時のwarn/errorになると思われる)
この状態で、dbt source snapshot-freshnessを実行すると、データの鮮度がチェックできる。
仮に、24時間以上前の場合は、WARNが通知される。

参考
https://dev.classmethod.jp/articles/dbt-sources/

staging/snowflake/stg_hashmap_snowflake_usage.sql

models/staging/snowflake/stg_hashmap_snowflake_usage.sql
with usage as (
  select 
    * 
  from 
    {{ source('snowflake_usage', 'warehouse_metering_history') }}
)

select * from usage

staging/snowflake/stg_hashmap_snowflake_daily_usage.sql

prehookが指定してあり、CREATE SEQUENCEを実行している。

カラムは、snowflake.ymlに記載があり、そちらでtests:not_nulluniqueが指定しており、そちらでデータのテストが実施される。

snowflake_setup

このディレクトリには、dbtを使う前の環境設定が行われている

├ service_accounts : WAREHOUSE, ROLE, Privilage , SERVICE ACCOUNTの作成
| ├ dbt_prod.sql
| ├ dbt_test.sql
| └ sigma_computing.sql
├ cloud_cost_monitoring_base.sql : DATABASE, SCHEMA, WAREHOUSE, ROLE, PRIVILAGE 
└ teardown.sql : DATABASE, WAREHOUSE, ROLE, USERの削除のSQL

tests

tests/staging/snowflake/assert_usage_for_every_day.sql

先頭ブロックの{{ config(severity='warn') }}は、このテストを実施した場合に、WARNで警告を出す設定。 serverity=重要度

workflows

ci_prod.yml

  • ブランチ「master」にPushされたら起動する
  • env:にて、設定。
    • secrets にパスワード
    • target : prod
  • jobs:
    • docker-imageの指定
    • ブランチのチェックアウト
    • Python3.7のインストール
    • DBTのインストール
    • DBTコマンドの実行
      • dbt run --profiles-dir ./ci_profiles
      • dbt test --profiles-dir ./ci_profiles

ci_test.yml

  • PRが作成されたときに起動
  • env:
    • target は test → profiles.ymlに関係する
    • secretsを使っている
  • jobs:
    • docker-imageの指定?
    • checkout
    • Python3.7のインストール
    • DBTのインストール
    • DBTコマンドの実行
      • DBT_PROFILE_SCHAMAを  PR_20220314 などに設定
        • PR_20220314_REPORTING、PR_20220320_STAGING などのカスタムスキーマに構築される。
      • dbt run --profiles-dir ./ci_profiles
      • dbt test --profiles-dir ./ci_profiles

scheduled_prod.yml

  • cronのスケジュールで起動 0 */1 * * * ※毎時起動
  • env:
    • target = prd
    • secretsを使用 ※パスワードとかハードコーディングしない!Gitに挙げない!!
  • jobs:
    • dbt run --profiles-dir ./ci_profiles

dbt_project.yml

profileは、cloud_cost_monitoringを使用
ci_profiles/profiles.yml でこの名前のprofileを作っている

基本的なディレクトリ構成は、デフォルトのママ

modelsにて
stagingは、カスタムスキーマ:stagingで、 view で作成
reportingは、カスタムスキーマ:reportingで、tableで作成指定

Discussion