Cloud Run は Google Cloud で提供されているフルマネージドなサーバーレスプラットフォームです。
Django や Ruby on Rails といった Web アプリケーションを Cloud Run で実行すれば、従来に比べてインフラの管理コストを大きく削減することができます。
このエントリでは、Cloud Run+Cloud SQL 構成の Django アプリケーションを対象に Cloud Build を使って CI/CD 環境を構築する方法を説明します。
下記の前提で説明していきます。
- Python 3.9.7
- Django 3.2.9
基本的には下記で説明されている内容になりますが、一部 CI/CD する上での注意点を挙げながら説明していきます。
説明に用いるサンプルアプリケーションのリポジトリは下記です。
環境は production, staging, development, test の4つあるものとします。
production, staging 環境はそれぞれが Google Cloud プロジェクトで、development と test 環境はローカルです。
Django アプリケーションは Docker コンテナで実行します。
データベースには MySQL を使い、development, test 環境は Docker Compose で、production, staging 環境は Cloud SQL でデータベースを用意します。
CI/CD は master ブランチへの push をトリガーに Cloud Build を実行します。
Cloud Build では Docker イメージのビルドと Container Registry への push、そしてデータベースのマイグレーションと Cloud Run へのデプロイを行います。
今回は静的ファイルを配信するための collectstatic
は行いません。
秘匿情報の管理にはシークレットマネージャーを利用します。
秘匿情報の取得はシークレットマネージャーの Python クライアント google-cloud-secret-manager
を使ってDjango アプリケーション内で行います。
ここからはサンプルアプリケーションを使って説明していきます。実際に手を動かして試す場合は下記のリポジトリをフォークしてください。
フォークしたリポジトリをローカルにクローンしたら Docker Compose で development 環境を構築し Web サーバーを起動します。
$ git clone git@github.com:otoyo/django-cloudrun-sample.git
$ cd django-cloudrun-sample
$ docker compose build
$ docker compose run
MySQL コンテナが起動するまでしばらく待ちます。下記のようなログが現れたらブラウザで http://localhost:58000 を開きます。
app_1 | MySQL is up - executing command
app_1 | Watching for file changes with StatReloader
"The install worked successfully!" と表示されれば成功です。
ここで django_cloudrun_sample/settings.py
を見てみましょう。L22 で必要な環境変数を定義しているのがわかります。
env = environ.Env(
DEBUG=(bool, True),
SECRET_KEY=(str, 'django-insecure-qnr$*ocy$diy6v#o&^k5x-9ofw@mn@4+bww*vyzwd4ydx%g@!d'),
DB_NAME=(str, 'django_cloudrun_sample_dev'),
DB_USER=(str, 'root'),
DB_PASSWORD=(str, ''),
DB_HOST=(str, 'mysql'),
DB_PORT=(str, '3306'),
)
環境変数の扱いには django-environ を使用しています。詳細はドキュメントを参照してください。
production, staging 環境ではこれらの環境変数をシークレットマネージャーから取得します。
L48 で環境の判別とシークレットマネージャーからの秘匿情報取得を行なっています。
try:
_, os.environ["GOOGLE_CLOUD_PROJECT"] = google.auth.default()
except google.auth.exceptions.DefaultCredentialsError:
pass
if os.environ.get("GOOGLE_CLOUD_PROJECT", None):
# Pull secrets from Secret Manager and set env
project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")
secret_name = 'django-cloudrun-sample-settings' # name of secret in Secret Manager
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/{secret_name}/versions/latest"
payload = client.access_secret_version(name=name).payload.data.decode("UTF-8")
env.read_env(io.StringIO(payload))
production, staging 環境は Google Cloud 上で実行されるため google.auth.default()
でプロジェクトIDを取得することができます。プロジェクトIDが存在する場合は環境変数をシークレットマネージャーから取得した秘匿情報で上書きしています。
development, test 環境はローカルで実行されるため、環境変数はデフォルトが使用されます。
production, staging 環境は Google Cloud プロジェクトが異なるだけという前提なので、ここでは staging 環境を例に説明していきます。
ここから各種インスタンスやサービスを作成するとき、リージョンは asia-northeast1 (東京)
とします。
Google Cloud コンソールにログインし staging の Google Cloud プロジェクトを選択します(無ければ作成します)。
シークレットマネージャーを開き新規にシークレットを作成します。
django-cloudrun-sample-settings
の名前で下記の情報を登録します。
<secret>
および <db_password>
<PROJECT_ID>
は自身で置き換えてください。
SECRET_KEY=<secret>
DB_NAME=django_cloudrun_sample
DB_USER=django
DB_PASSWORD=<db_password>
DB_HOST=/cloudsql/<PROJECT_ID>:asia-northeast1:django
DB_PORT=3306
シークレット名を変更する場合は settings.py
の secret_name
も変更します。
Cloud SQL を開き django
という名前でインスタンスを作成します。インスタンスの接続設定でパブリック IP を割り当てていることを確認します。
インスタンスを作成したら、左のメニューから django_cloudrun_sample
データベースと django
ユーザーを作成します。ユーザーのパスワードは先ほどシークレットに登録したパスワードを設定します。
Cloud Build を開き新規にトリガーを作成します。トリガー名は何でも構いません。ここでは deploy-django-cloudrun-sample
という名前にします。
「構成」セクションで「自動検出」ではなく「Cloud Build 構成ファイル」を選択し、構成ファイルの場所として /cloudbuild.staging.yaml
を指定します。
こうしておくことで production 環境と staging 環境で構成ファイルを分けておくことができます。
Cloud Run を開きサービスを作成します。
Cloud Run は Container Registry から Docker イメージを取得しますが、まだ Docker イメージをビルドおらず存在しないため、いったん手動で URL を gcr.io/django-cloudrun-sample/django-cloudrun-sample
として登録しておきます。
"Container, Variables & Secrets, ..." セクションで、まず「変数とシークレット」タブを選び環境変数 DEBUG
を値 False
で追加します。
次に「接続」タブを選択し Cloud SQL 接続を追加します。先ほど作成した django
SQLインスタンスを選択します。
ここまで設定できたらサービスを作成します。
IAM を開き PROJECTNUM@cloudbuild.gserviceaccount.com
と PROJECTNUM-compute@developer.gserviceaccount.com
の2つのサービスアカウントに必要なロールを付与します。
下記の説明に従って Cloud Build サービスアカウントに権限を付与します。
上記に加えて、Cloud Build サービスアカウントに Cloud Build から Cloud SQL インスタンスの接続に cloud_sql_proxy を使うため 「Cloud SQL 管理者」を、Compute Engine のサービスアカウントにシークレットマネージャーからシークレットを取得するため「Secret Manager のシークレット アクセサー」を付与します。
最終的にサービスアカウントのロールは下記のようになりました。
これで CI/CD の準備が整いました。
フォークしたリポジトリに適当なコミットを push すると Cloud Build がトリガーされ、Docker イメージのビルドと push、データベースのマイグレーション、Cloud Run へのデプロイが順に実行されます。
Cloud Run へのデプロイが成功すると、Cloud Run のサービス画面に表示される URL に /admin
パスを付けてブラウザで開きます。
https://django-cloudrun-sample-hogehoge.a.run.app/admin
Django Admin のログイン画面が表示されれば成功です。
以上です。
このエントリでは、Cloud Run+Cloud SQL 構成の Django アプリケーションを対象に Cloud Build を使って CI/CD 環境を構築する方法を説明しました。
コメントを送る
コメントはブログオーナーのみ閲覧できます