🚀

Step FunctionsとECSでELTパイプラインを作ってみる(dbt)

2021/10/23に公開

完成しました(2022/05/07)

https://zenn.dev/jimatomo/books/d49ddf2e18ae8e

データパイプラインをサーバレスにしたい

ELTとdbtについて

データ活用基盤の役割の一つはデータを集めてきてデータマートまで加工していくことです。従来はストレージが高価であったりしたこともあり、連携段階で加工しておくことでストレージのコストを抑えたることが可能なETLが主流でしたが、近年アーキテクチャの進化を受けて連携時はほぼ無加工で連携後に加工をするELTが注目されています。

そんなデータエンジニアリングの世界観が広まる中で私が注目しているのはdbt (data build tool) というELTのTを担うOSSです。
https://dev.classmethod.jp/articles/dbt-tutorial/

ELTだからこそのサーバレス化する意味がある

ELTの良いところはSQLベースでデータ変換のパイプラインを実装するので、SnowflakeのようなクラウドDWHのパワーを使い倒せるという点です(他にもExtract/Loadがシンプルになるなどいろいろないい面があります)。
そのメリットを言い換えると、ELTのデータパイプラインを小さいコンピューティングリソースで構成することが可能にということです。

さらに一歩先に目を向けると、ELTパイプラインのコンピュートリソースにコンテナを利用することで、モダンなサーバレスアーキテクチャにすることも可能です。
具体的には、dbtをコンテナ化しECS Fargateで動かせるようにしてStep Functionsでワークフローを管理すれば、完全にサーバレスでELTデータパイプラインを構築可能です。
(え、そもそもdbt cloud使えばよくない?、みたいなことはいったん考えません)

将来的には体系的にまとめてハンズオンができるようにまとめて本を作ろうと思っています。今回はその構想をメモとして残すことにします(構想なので本を書くための検証結果で変わるかもしれないです)。

構成図

構成図はこんな感じです。
DockerのコンテナをビルドしてECRにプッシュしつつ、さらにdbtのポイントであるドキュメントをS3にputしてCloudfront+Lambda@Edgeで認証機能付きのデータカタログとして公開します。

CI/CD環境

CodeCommitにdbtのプロジェクトとDockerfileとbuildspec.ymlをセットでCodeCommitに管理しておきます。

  • dbtプロジェクト
  • Dockerfile
  • buildspec.yml

dbtプロジェクトの開発

dbtプロジェクトはdbtのモデルや設定ファイルが配置されています。基本的に開発環境で以下のように開発するイメージです。

  1. git cloneでリポジトリをクローンする
  2. dbt initでプロジェクトを生成する
  3. profiles.ymlをプロジェクトのルートに配置する
  4. ECSで実行する際にSSM Parameter Store(Secret ManagerでもOK)から認証情報を取得するなどの前処理とセットにくるんだシェルスクリプト用のフォルダとスクリプトを作成
  5. CodeCommitにpushする

Dockerfileについて

Dockerfileで指定する際のベースイメージは安定化させるために事前にdbtをインストールしたイメージ用意することにします。

CodeCommitでセットで管理しているdbtプロジェクトをコピーして最新のコンテナにします。

buildspec.ymlについて

ビルドプロセスの中で2つのことをやろうと思います。

  • DockerコンテナをビルドしてECRにPUSHする
  • 最新のdbtプロジェクトをドキュメント化してS3にPUTすること(ただし、CodeBuild内でやろうとするとVPCを利用するなど一定のハードルがあるので、Step Functionsを介してdbtコンテナをECSのタスクを呼び出すようにしようと思います)

サンプルをベースにこんなイメージにしようと思っています
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-docker.html

version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...          
      - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG      
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      - echo generating dbt document started on `date`
      - aws start-execution --state-machine-arn <value>

これらはCodePipelineでパイプライン化します。

ECSとStep Functions

ECSはTerraformとかと一緒にコード管理しようと構想しています(これは大いに迷っているところ)。

Step Functionsは正直難しいところで、GUIベースで開発可能なStep Functions Workflow Studioの機能が充実していて機能追加も活発なのでこれを利用する方がいい気がしています(逆に利用しない方がもったいない)。
https://dev.classmethod.jp/articles/stepfunctions-workflow-designer/

ドキュメントのホスティング

S3のWebサイトホスティング機能でやってもいいですが、データカタログは一般公開するものではないので認証をつけます。以前整理したCloudfront + Lambda@Edge + Cognitoを組み合わせた方法を利用しようと思います。
https://jimatomo.hatenablog.com/entry/2021/08/01/012757

その他

Parameter Storeの設定もTerraformを利用しようと思っています。

その他の基盤として対象のデータベースはRDS PostgreSQLを利用しようと思っています。

VPCやRDSなどのリソースはTerraformで作成しようと思っています(迷い中)。

以上、構想のメモでした。

Discussion