🐈
Github ActionsでCloud BuildとCloud Runを実行する
これは何か
Great Expectationsとdbtとairflowでロバストなデータパイプラインを構築するで作成したデータパイプラインを、Github Actionsを用いて自動でGCPにデプロイできるようにしたので、その時の調査内容とコードをまとめる。
前提
普通はAirflowをデプロイするならCloud Composerを使うか、GKEでデプロイすると思うが、サーバーが常駐してしまってコストが発生してしまうのと、今回はあくまで自分の練習用なので、あえて一つのコンテナにまとめてデプロイしてみる。
業務要件
- mainブランチへのpushをトリガーに、GCP上に自動でコンテナのdeployを行う
- デプロイされたコンテナは、Airflowでタスクがスケジューリングされ、データのバリデーションとロードを定期実行する
機能要件
- mainブランチにpushされると、GithubActionsがコンテナのデプロイを行う
- コンテナのデプロイは、CloudBuildとCloudRunを用いて、リポジトリ内のDockerfileを読み取って行う
- デプロイに必要なサービスアカウントキーや、AirflowがGCP内のリソースを扱うために必要なサービスアカウントキーはGithubActionsのsecretsに保存して渡す
構成
.
├── prod # デプロイに必要なファイル
│ ├── Dockerfile.prod
│ ├── airflow.conf
│ └── cloudbuild.yaml
└── scr # 各種ソースコード
├── dag
├── dbt
└── great_expectations
コード
Dockerfile.prod
ARG GCP_AIRFLOW_SA_KEY
RUN echo -n ${GCP_AIRFLOW_SA_KEY} | base64 --decode > /tmp/gcp_secret.json
cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/***/prod_data_pipeline', '--build-arg', 'GCP_AIRFLOW_SA_KEY=${_GCP_AIRFLOW_SA_KEY}', '-f', './prod/Dockerfile.prod', '.']
substitutions:
_GCP_AIRFLOW_SA_KEY: foobar
options:
substitution_option: 'ALLOW_LOOSE'
ci.yaml
on:
push:
branches:
- main
name: Build and Deploy a Container
env:
PROJECT_ID: ${{ secrets.GCP_PROJECT }}
GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
GCP_AIRFLOW_SA_KEY: ${{ secrets.GCP_AIRFLOW_SA_KEY }}
SERVICE: datapipeline
REGION: us-central1
IMAGE: gcr.io/${{ secrets.GCP_PROJECT }}/prod_data_pipeline
PORT: 8080
MEMORY: 2G
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Cloud SDK
uses: google-github-actions/setup-gcloud@v0.2.0
with:
project_id: ${{ env.PROJECT_ID }}
service_account_key: ${{ secrets.GCP_SA_KEY }}
export_default_credentials: true
- name: Configure Docker
run: |
gcloud auth configure-docker
- name: Deploy to Cloud Build
run: |
gcloud builds submit --config ./prod/cloudbuild.yaml --substitutions=_GCP_AIRFLOW_SA_KEY=${{ env.GCP_AIRFLOW_SA_KEY }}
- name: Deploy to Cloud Run
run: |
gcloud run deploy ${{ env.SERVICE }} --project ${{ env.PROJECT_ID }} --region ${{ env.REGION }} --image ${{ env.IMAGE }} --port ${{ env.PORT }} --memory ${{ env.MEMORY }}
ややこしい構成としては、AirflowのconnectionでKey Json Pathを指定する必要があり、DockerfileにGithub Actionsのsecretsに登録したキーJSONの中身をどのように渡すか迷ったため、
①secretsにencodeした文字列を登録
②ci.yamlでcloudbuild.yamlの実行時に、substitutionsとして①を注入
③cloudbuild.yamlでdockerfileに--build-argとして渡す
④dockerfile上で受け取ったargをdecodeしてjsonファイルを作成・配置
という流れになった。
もう少し賢いやり方を考えたい。
実行
deployには成功した模様。途中ではまった要因としては、
CloudRunでAirflowの挙動を確かめてみたところ、webserverは正常に立ち上がり、ジョブを動かすことに成功した。
Discussion