Gitlab CI/CD を用いて prefect をデプロイする
はじめに
今回は、Gitlab の CI/CD を用いて、prefect のデプロイをやってみたいと思います。
具体的には、prefect の workflow のエントリとなる Deployment を CI/CD を使って自動デプロイする方法についてみていきます。
動作環境
リポジトリの管理は SaaS 版の Gitlab ( gitlab.com ) を用い、CI/CD の Job 実行用の Gitlab-Runner はローカル環境に docker コンテナで用意します。
また、prefect-server や、そのバックエンドにあたる DB も同様に docker コンテナで用意します。
ローカルに用意する各 docker コンテナは、docker-compose でまとめて起動させます。
そのため、以下のような docker-compose.yml を作成します。
docker-compose.yml
services:
prefect_server:
image: prefecthq/prefect:2-python3.11
restart: always
volumes:
- prefect:/root/.prefect
entrypoint:
[
"/opt/prefect/entrypoint.sh",
"prefect",
"server",
"start"
]
environment:
- PREFECT_UI_URL=http://127.0.0.1:4200/api
- PREFECT_API_URL=http://127.0.0.1:4200/api
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_API_DATABASE_CONNECTION_URL=postgresql+asyncpg://postgres:postgres@database:5432/prefect
ports:
- 4200:4200
depends_on:
- database
database:
image: postgres:latest
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=prefect
expose:
- 5432
ports:
- 5432:5432
volumes:
- db:/var/lib/postgresql/data
gitlab-runner:
image: gitlab/gitlab-runner:latest
restart: always
volumes:
- "runner:/etc/gitlab-runner"
- /var/run/docker.sock:/var/run/docker.sock
volumes:
prefect:
db:
runner:
networks:
default:
name: prefect-network
また、Gitlab-Runner が実行する CI/CD Job はローカル環境の docker コンテナとして起動できるようにします。そのため、上記 docker-compose.yml 内の gitlab-runner の設定にて、/var/run/docker.sock:/var/run/docker.sock
の volumes を定義し、ローカル環境で動作している Docker Engine と通信が出来るようにしています。
Gitlab リポジトリに Runner を登録
docker-compose.yml で gitlab-runner の起動が完了したら、この Runner を Gitlab リポジトリに登録します。登録方法は Gitlab リポジトリの CI/CD Settings
> Runner
から実施します。以下のような Project Runner
の項目にて「New project runner」をクリックします。
以下のようなページになるので、 Platform は Linux 、 Tags は dev としておきます。
「Create runner」をクリックすると、登録用のコマンドが表示されます。このコマンドには、登録時に必要となる認証トークンが記載されているため、コマンド一式をコピーしておきます。
その後、ローカル環境で起動しておいた gitlab-runner に対してこのコマンドを実行します。
docker compose exec gitlab-runner gitlab-runner register --url https://gitlab.com --token XXXXXXXXXXXXXXXXXXXXXX
コマンドを実行すると、 CI/CD Job を実行する環境について聞かれるので、 docker
と入力します。これで docker コンテナを用いて Job を実行できるようになります。
.gitlab-ci.yml
の作成
Gitlab-Runner の登録が完了したら、次に .gitlab-ci.yml
を作成します。このファイルは、CI/CD Pipeline を定義するファイルです。
.gitlab-ci.yml
default:
tags:
- dev
stages:
- build
- deploy
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:v1.14.0-debug
entrypoint: [""]
script:
- /kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
rules:
- if: $CI_COMMIT_TAG
deploy:
stage: deploy
image:
name: registry.gitlab.com/<username>/<repository_name>:$CI_COMMIT_TAG
script:
- python deploy.py $CI_COMMIT_TAG
rules:
- if: $CI_COMMIT_TAG
tags
に dev
をセットすることで、先ほど登録した Gitlab-Runner を使ってくれるようになります。
また、今回は build と deploy という 2 つのステージを用意しました。
build ステージでは、kaniko
という docker image ビルド用のツールを用いて、prefect の flow 用 docker image をビルドしています。今回 prefect の flow はローカル環境の docker コンテナで実行するためです。
deploy ステージでは、prefect の deployment を登録します。このステージの script
で実行している deploy.py
は以下のようになっており、これで flow を deployment として prefect-server に登録しています。
deploy.py
import asyncio
import sys
from prefect import flow
@flow(log_prints=True)
async def sample_flow():
print("This is sample_flow!")
async def deploy(tag: str):
await sample_flow.deploy(
name="sample-flow-deployment",
work_pool_name="docker-pool",
image=f"registry.gitlab.com/<username>/<repository_name>:{tag}",
push=False,
build=False,
)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Docker image tag must be set.")
exit(1)
asyncio.run(deploy(sys.argv[1]))
それぞれのステージは、rules
にて Tag が作成された時に Pipeline が生成されるようにしています。また、ビルドした docker image に対してその Tag で Push するようにしました。
環境変数の登録
CICD から ローカル環境の prefect-server に flow を deploy するには、PREFECT_API_URL
の環境変数を Gitlab リポジトリに登録しておく必要があります。登録方法は Gitlab リポジトリの CI/CD Settings
> Variables
から実施します。
今回は、ローカル環境で動作している prefect-server に deploy が出来ればいいので、PREFECT_API_URL
には http://gateway.docker.internal:4200/api
を設定します。gateway.docker.internal
を使っているのは、Gitklab-Runner が起動した CI/CD Job 用の docker コンテナ内から、ホスト経由で prefect-server の docker コンテナに通信できるようにするためです。
環境変数の登録が出来れば、以下のように表示されるはずです。
Dockerfile と work-pool の作成
最後に prefect flow の実行に必要な Dockerfile と work-pool を作成しておきます。Dockerfile は、kaniko を用いた build ステージで flow 用の docker image をビルドするためのものです。以下のような Dockerfile を用意します。
FROM prefecthq/prefect:2-python3.11
COPY requirements.txt .
RUN pip install -r requirements.txt --trusted-host pypi.python.org --no-cache-dir
COPY <repository_name> ./<repository_name>
COPY deploy.py .
また、prefect flow を docker コンテナで起動するために docker 用の work-pool を用意します。以下のコマンドを実行します。
prefect work-pool create --type docker docker-pool
CI/CD から Deploy
それでは Gitlab リポジトリから CI/CD Pipeline を通してデプロイ( deployment の登録)を行なってみます。Gitlab リポジトリの Tags
から以下のように Tag を作成します。
Tag 作成後、Pipelines
をみると、自動的に CI/CD Job の実行が始まっているはずです。
build
Job にて prefect flow 用の docker image の push、 deploy
Job にて deployment の最新化を行なっています。
これらの Job 完了後、最新のコードで prefect flow を実行することができます。
終わりに
今回は、Gitlab CI/CD を用いて prefect flow を自動デプロイしてみました。prefect flow を docker コンテナで動作させる場合、事前にコンテナ用の docker image の用意と deployment の最新化を行う必要があります。CI/CD を通してこれらを自動化することで、煩雑な手作業が減り、継続的な開発がやりやすくなるかと思います。
参考
Discussion