この記事はトレタ Advent Calendar 2022の15日目の記事です。
はじめに
こんにちは、サーバーサイドエンジニアの @shiroemons です。
前回の記事に書いた通り、認定資格を取得してからGoogle Cloudを頻繁に活用するようになりました。
現在のプロジェクトでは、Cloud Buildを用いてdocker buildやCloud Runへのデプロイを行っています。
また、データベース(Cloud SQL)へのマイグレーションもCloud Buildから行っています。
今回は、Cloud Buildからpsqldef
というマイグレーションツールを使用して、Cloud SQL for PostgreSQLにマイグレーションする方法を紹介します。
ただし、Cloud SQL for PostgreSQLなどの設定は完了している前提のため、省略しています。
psqldefとは
SQLで羃等にDBスキーマ管理ができるツール「sqldef」のPostgreSQL用のツールです。
PostgreSQL用の他に、MySQL用のmysqldefやSQLite3用のsqlite3defなども存在します。
sqldefについての細かい説明は、ここでは省略します。
Cloud Buildとは
Cloud Buildは、Google Cloud 上でビルドを実行するサービスです。
Cloud Buildでは、ビルド構成ファイルと呼ばれる設定ファイルにビルドやデプロイの方法(指示)を記述します。記述した指示に基づいてタスクを実行し、ビルドやデプロイを行います。
Cloud SQLへのマイグレーションで使用した構成ファイルの紹介と説明をします。
Cloud Buildの構成ファイル
Cloud SQLへのマイグレーションで使用したCloud Buildの構成ファイルはこちらになります。
- cloudbuild-migration.yaml
steps: - name: gcr.io/cloud-builders/wget args: - 'https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64' - '-O' - ./cloud_sql_proxy id: cloud_sql_proxy download - name: gcr.io/cloud-builders/gcloud args: - '-c' - | chmod +x ./cloud_sql_proxy && ./cloud_sql_proxy --version id: cloud_sql_proxy version entrypoint: bash - name: gcr.io/cloud-builders/wget args: - >- https://github.com/k0kubun/sqldef/releases/latest/download/psqldef_linux_amd64.tar.gz id: psqldef download - name: gcr.io/cloud-builders/gcloud args: - '-c' - | tar -zxvf psqldef_linux_amd64.tar.gz && ./psqldef --version id: psqldef version entrypoint: bash - name: gcr.io/cloud-builders/gcloud args: - '-c' - > ./cloud_sql_proxy -instances=$_INSTANCE_CONNECTION_NAME=tcp:$_DATABASE_PORT & sleep $_SLEEP_SEC; ./psqldef --dry-run --file $_SCHEMA_FILE --host $_DATABASE_HOST --port $_DATABASE_PORT --user $_DATABASE_USER --password $$DATABASE_PASS $_DATABASE_NAME id: psqldef dry-run entrypoint: bash secretEnv: - DATABASE_PASS - name: gcr.io/cloud-builders/gcloud args: - '-c' - > ./cloud_sql_proxy -instances=$_INSTANCE_CONNECTION_NAME=tcp:$_DATABASE_PORT & sleep $_SLEEP_SEC; ./psqldef --file $_SCHEMA_FILE --host $_DATABASE_HOST --port $_DATABASE_PORT --user $_DATABASE_USER --password $$DATABASE_PASS $_DATABASE_NAME id: psqldef execute entrypoint: bash secretEnv: - DATABASE_PASS substitutions: _SCHEMA_FILE: ./schema.sql _DATABASE_HOST: 127.0.0.1 _DATABASE_PORT: '5432' _DATABASE_NAME: db_name _DATABASE_USER: db_user _DATABASE_PASSWORD_KEY: database_password _INSTANCE_REGION: asia-northeast1 _INSTANCE_ID: database _INSTANCE_CONNECTION_NAME: '${PROJECT_ID}:${_INSTANCE_REGION}:${_INSTANCE_ID}' _SLEEP_SEC: '5' availableSecrets: secretManager: - versionName: >- projects/$PROJECT_ID/secrets/${_DATABASE_PASSWORD_KEY}/versions/latest env: DATABASE_PASS
(代入変数部分を変更して動作することを確認しています。)
各ビルドステップの説明
- よく使用するフィールドについて簡単に説明します。
- name: クラウドビルダーの指定(Docker..etc)
- args: ビルダーに渡す引数のリスト
- id: ビルドステップに対して一意の識別子
- entrypoint: エントリポイントを指定 (bash etc)
- secretEnv: Cloud KMS暗号鍵を使用して暗号化された環境変数のリスト
- 詳しい説明は、 ビルド構成ファイルの構造 を参照ください。
ステップ1: Cloud SQL Proxyのダウンロード
- name: gcr.io/cloud-builders/wget args: - 'https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64' - '-O' - ./cloud_sql_proxy id: cloud_sql_proxy download
- Cloud SQLに接続する際、Cloud SQL Proxyを使用して接続します。
- Cloud SQL Proxy を使用するには、Cloud SQL Admin API を有効にする必要があります。
- こちらから有効にできます。
- Cloud SQL Proxyをwgetでダウンロードします。
ステップ2: Cloud SQL Proxyの実行権限付与とCloud SQL Proxyのバージョン確認
- name: gcr.io/cloud-builders/gcloud args: - '-c' - | chmod +x ./cloud_sql_proxy && ./cloud_sql_proxy --version id: cloud_sql_proxy version entrypoint: bash
- ダウンロードしたCloud SQL Proxyに実行権限を付与します。
- どのバージョンを使用したかわかるようにバージョンを確認します。
- ファイルの存在確認の意図もあります。
ステップ3: psqldef の最新版をダウンロード
- name: gcr.io/cloud-builders/wget args: - >- https://github.com/k0kubun/sqldef/releases/latest/download/psqldef_linux_amd64.tar.gz id: psqldef download
- マイグレーションに必要なpsqldef(最新版)をwgetでダウンロードします。
ステップ4: psqldef の解凍とpsqldef のバージョン確認
- name: gcr.io/cloud-builders/gcloud args: - '-c' - | tar -zxvf psqldef_linux_amd64.tar.gz && ./psqldef --version id: psqldef version entrypoint: bash
- ダウンロードしたpsqldefは圧縮されているため解凍します。
- どのバージョンを使用したかわかるようにバージョンを確認します。
- ファイルの存在確認の意図もあります。
ステップ5: psqldef の dry-run 実行
- name: gcr.io/cloud-builders/gcloud args: - '-c' - > ./cloud_sql_proxy -instances=$_INSTANCE_CONNECTION_NAME=tcp:$_DATABASE_PORT & sleep $_SLEEP_SEC; ./psqldef --dry-run --file $_SCHEMA_FILE --host $_DATABASE_HOST --port $_DATABASE_PORT --user $_DATABASE_USER --password $$DATABASE_PASS $_DATABASE_NAME id: psqldef dry-run entrypoint: bash secretEnv: - DATABASE_PASS
- Cloud SQLに接続する場合、Cloud SQL Proxyを先に起動しておく必要があります。
- Cloud SQL Proxyの起動に一定時間かかるため
sleep
を入れています。 - 設定に必要な値は、すべて代入変数で定義しておきます。
- 代入変数を用いることでビルド構成ファイル自体の変更をしなくてもよくなります。
- psqldefを本実行する前に、dry-runで実行してエラーがないことを確認しておきます。
- DBのパスワードは、Secret Managerに保存して使用しています。
ステップ6: psqldef の 実行
- name: gcr.io/cloud-builders/gcloud args: - '-c' - > ./cloud_sql_proxy -instances=$_INSTANCE_CONNECTION_NAME=tcp:$_DATABASE_PORT & sleep $_SLEEP_SEC; ./psqldef --file $_SCHEMA_FILE --host $_DATABASE_HOST --port $_DATABASE_PORT --user $_DATABASE_USER --password $$DATABASE_PASS $_DATABASE_NAME id: psqldef execute entrypoint: bash secretEnv: - DATABASE_PASS
内容は、dry-runとほぼ同じです。psqldefのdry-runオプションを外した内容です。
代入変数(substitutions)の説明
substitutions: _SCHEMA_FILE: ./schema.sql _DATABASE_HOST: 127.0.0.1 _DATABASE_PORT: '5432' _DATABASE_NAME: db_name _DATABASE_USER: db_user _DATABASE_PASSWORD_KEY: database_password _INSTANCE_REGION: asia-northeast1 _INSTANCE_ID: database _INSTANCE_CONNECTION_NAME: '${PROJECT_ID}:${_INSTANCE_REGION}:${_INSTANCE_ID}' _SLEEP_SEC: '5'
代入変数名 | 説明 |
---|---|
_SCHEMA_FILE |
psqldef でマイグレーションするスキーマファイル |
_DATABASE_HOST |
DBのホスト |
_DATABASE_PORT |
DBのポート |
_DATABASE_NAME |
DB名 |
_DATABASE_USER |
DBのユーザー名 |
_DATABASE_PASSWORD_KEY |
DBのパスワードを Secret Manager に保存した際のシークレット名 |
_INSTANCE_REGION |
Cloud SQLのインスタンスのリージョン |
_INSTANCE_ID |
Cloud SQLのインスタンスID |
_INSTANCE_CONNECTION_NAME |
Cloud SQLの接続名(環境変数や代入変数で値を作成する) |
_SLEEP_SEC |
Cloud SQL Proxyの起動を待つスリープ(秒数を指定する) |
数値の指定の場合、クォートが必要です。そのため、DBのポートやスリープの秒数にシングルクォートを付けています。
availableSecretsの説明
availableSecrets: secretManager: - versionName: >- projects/$PROJECT_ID/secrets/${_DATABASE_PASSWORD_KEY}/versions/latest env: DATABASE_PASS
- availableSecretsは、Cloud BuildでSecret Managerのシークレットを使用する時のフィールドです。
- Secret Managerの詳しい使い方は、Secret Manager のシークレットの使用 を参照ください。
DBのパスワードを、Secret Managerに保存しており、そこから最新の設定内容を取得するようにしています。
Cloud Build 実行に必要なロール
- 今回のCloud Build実行には以下の2つのロールが必要です。
Cloud SQL クライアント
Secret Manager のシークレット アクセサー
実行ログ
構成ファイルの代入変数の値を適宜変更し、実行すると以下のように成功します。
振り返り
Cloud Buildでsqldefを用いてマイグレーションする方法をネットで探しても出てこず苦労しました。
Cloud SQL ProxyとpsqldefをwaitFor
を使用して分けて実行させてみたりと試行錯誤の連続でした。
Cloud BuildでCloud SQL Proxyを用いてCloud SQLへの接続がどうしてもうまく行かず、Google Cloudのサポートも利用しました。
Cloud SQL Proxyの起動には、少し時間を要するためスリープを入れることで接続できない問題は解決しました。
さいごに
この記事が、Cloud Buildからpsqldefもしくはmysqldefを使用してマイグレーションを検討している方の助けになれば幸いです。
次回の トレタ Advent Calendar 2022 の22日目は、Cloud Buildの結果をSlackに通知する方法を紹介したいと思います。
トレタではエンジニアの募集を全方位で行なっております。
コロナ禍を乗り越えた飲食店の新しい姿を探求する仲間をお待ちしております。