Step FunctionsとECSでELTパイプラインを作ってみる(dbt)
完成しました(2022/05/07)
データパイプラインをサーバレスにしたい
ELTとdbtについて
データ活用基盤の役割の一つはデータを集めてきてデータマートまで加工していくことです。従来はストレージが高価であったりしたこともあり、連携段階で加工しておくことでストレージのコストを抑えたることが可能なETLが主流でしたが、近年アーキテクチャの進化を受けて連携時はほぼ無加工で連携後に加工をするELTが注目されています。
そんなデータエンジニアリングの世界観が広まる中で私が注目しているのはdbt (data build tool) というELTのTを担うOSSです。
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のモデルや設定ファイルが配置されています。基本的に開発環境で以下のように開発するイメージです。
- git cloneでリポジトリをクローンする
- dbt initでプロジェクトを生成する
- profiles.ymlをプロジェクトのルートに配置する
- ECSで実行する際にSSM Parameter Store(Secret ManagerでもOK)から認証情報を取得するなどの前処理とセットにくるんだシェルスクリプト用のフォルダとスクリプトを作成
- CodeCommitにpushする
Dockerfileについて
Dockerfileで指定する際のベースイメージは安定化させるために事前にdbtをインストールしたイメージ用意することにします。
CodeCommitでセットで管理しているdbtプロジェクトをコピーして最新のコンテナにします。
buildspec.ymlについて
ビルドプロセスの中で2つのことをやろうと思います。
- DockerコンテナをビルドしてECRにPUSHする
- 最新のdbtプロジェクトをドキュメント化してS3にPUTすること(ただし、CodeBuild内でやろうとするとVPCを利用するなど一定のハードルがあるので、Step Functionsを介してdbtコンテナをECSのタスクを呼び出すようにしようと思います)
サンプルをベースにこんなイメージにしようと思っています
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の機能が充実していて機能追加も活発なのでこれを利用する方がいい気がしています(逆に利用しない方がもったいない)。
ドキュメントのホスティング
S3のWebサイトホスティング機能でやってもいいですが、データカタログは一般公開するものではないので認証をつけます。以前整理したCloudfront + Lambda@Edge + Cognitoを組み合わせた方法を利用しようと思います。
その他
Parameter Storeの設定もTerraformを利用しようと思っています。
その他の基盤として対象のデータベースはRDS PostgreSQLを利用しようと思っています。
VPCやRDSなどのリソースはTerraformで作成しようと思っています(迷い中)。
以上、構想のメモでした。
Discussion