コンテンツに移動
デベロッパー

Cloud Run ジョブを使用したデータベース移行の実行

2022年12月26日
Google Cloud Japan Team

※この投稿は米国時間 2022 年 12 月 14 日に、Google Cloud blog に投稿されたものの抄訳です。

2019 年に Cloud Run がまだ公開プレビュー版の段階だった頃、Cloud Run が Twelve-Factor App の手法に準拠している 12 個の理由について書きました。その記事では、Cloud Run がアプリケーション開発の 12 個の要因のほとんどに対応していることを説明しました。しかし、12 番目の要因である管理者プロセスは、「Cloud Run の対象範囲外」と記述しました。このため、Cloud Run は 12 点満点中 11 点で「ほぼ満点」でした。

現在、Cloud Run で管理者プロセスを実行できるようになったため、Cloud Run ジョブで 12 番目の要因が満たされるようになりました。このパターンは、1 回限りのコマンドの適用や、ウェブ フレームワーク(Django、Rails、Laravel など)に依存するデプロイためのデータベース スキーマの移行などのより複雑なタスクに使用できます。この記事では、データベース スキーマの移行ユースケースに焦点を当てます。

データベースの移行に適用できる既存のパターンもありますが、それらについては考慮すべき点があり、組織のセキュリティ ポリシーによって制限されている可能性もあります。Cloud SQL Auth Proxy を使用すると、本番環境のデータベースに対して移行を適用できますが、それらのコマンドはローカルマシンで実行することになります。Cloud Build プロセスの一部として移行コマンドを実行できますが、デプロイ時にデータベース スキーマの移行を自動的に適用したくない状況が出てくるかもしれません。

一度に 1 つのジョブ

Cloud Run のジョブでは、Cloud Run 自体の対象範囲内でコマンドを実行できます。Cloud Run のサービスを利用するには、コンテナを起動して、常に稼働しているプロセス(ウェブサーバーなど)を確保する必要があります。Cloud Run のジョブを使用することで、完了時に終了するコマンドを呼び出すことができます。

Cloud Run のジョブは Cloud Run のサービスと同じ構成を持つため、ジョブのシークレット、データベース、サービス アカウントを構成できます。つまり、同じコンテナを使用でき、使用中のサービスから既存の IAM 構成を利用することもできます。たとえば、新しいプロダクト用に再構成するなどの必要がありません。

このパターンをどう取り扱うかは、Dockerfile ベースのコンテナか、Cloud Buildpack ベースのコンテナのいずれを使用しているかによって異なります。

Dockerfile ベースのデータベースの移行

わかりやすい例として、Dockerfile を使用して構築されたコンテナの場合の既存の Cloud Run デプロイ コマンドを以下にご紹介します。

読み込んでいます...

通常、このサービスは、選択したウェブサーバーを実行しているコンテナのデフォルト エントリポイントを使用して、そのまま実行されます。しかし、--command でデフォルトのエントリポイントをオーバーライドすることで、他のものを実行できます。Cloud Run のサービスに課される唯一の制限は、デプロイ対象が必ずリクエストをリッスンするプロセスを持つ必要があることです。

Cloud Run のジョブでは、この制限がないため、好きなカスタム コマンドを設定し、同じコマンドライン引数を使用して、データベースとシークレットの接続を確保できます。

前の例をジョブに適用するには、以下のように deploy を jobs create に変更し、--command を指定します。

読み込んでいます...

この例では、ジョブを作成してすぐに実行するため、--execute-now フラグを使用しています。このコマンドを再度実行する必要があるときは、ジョブを再実行できます。

読み込んでいます...

Procfile の力

Dockerfiles を使用するときは、実行したいコマンドを省略せずに指定する必要があります。しかしながら、Google Cloud の Buildpacks を使用すると、Procfile にエントリを追加してから、これらのエントリポイントを --command で呼び出すことができます。

以下の Procfile の例を見てみましょう。

読み込んでいます...

デフォルトでは、Google Cloud の Buildpacks は、web エントリポイントを実行します。この構成で Cloud Run のジョブを使用すると、--command migrate を使用して移行を実行したり、--command test を使用してテストを行ったりできます。

ここまでの例では、一般的なコマンドを使用してきましたが、用途に応じてエントリを使用した Procfile を作成することもできます。たとえば、選択したウェブ フレームワークに応じて、以下のとおり作成します。

読み込んでいます...

Buildpacks には、ユーザーが提供するシェルプロセス用のエントリポイントである「launcher」が付属しているため、Procfile に定義を追加することなくどのコマンドも実行できます。このエントリポイントを利用することで、以下のように好きなコマンドを実行できます。

読み込んでいます...

移行の実践

では、このパターンを既存のデプロイに適用するには、どうすればよいでしょうか。

Django アプリケーションを実行している Cloud Run サービスがあるとします。Django では、python3 manage.py migrate を使用して、データベースの移行を適用します。

そこで、以下のようにアプリケーション コードの Procfile にこのコマンドを追加できます。

読み込んでいます...

次に、以下のようにソースデプロイを使用して、この新しいコード変更を反映して Cloud Run のサービスを再度デプロイします。これにより、新しいコンテナが構築され、サービスが更新されます。

読み込んでいます...

ここから、ジョブを作成できます。この例では、gcloud を使用して、サービスから構成、特にイメージ名と Cloud SQL インスタンス名を取得します。Cloud コンソールからこれらをコピーすることもできますが、ここではスクリプトを選びます。

読み込んでいます...

ここで、ジョブを実行できます。

読み込んでいます...

--wait を使用すると、ジョブが無事実行されるか確認してから、提示された URL へのログインを確認できます。

最新バージョンのコンテナに対して実行するジョブを構成したため、移行を再実行する場合は、サービスをデプロイした後で新しいコンテナを使用して以下のようにジョブをもう一度実行します。

読み込んでいます...

コマンドラインからこれを実行する必要もありません。デプロイ ステップの後、Cloud Build デプロイ スクリプト内のステップとしてこれを追加できます。

読み込んでいます...

このジョブを以下のように更新する必要があるのは、Cloud SQL インスタンスなどが変更された場合だけです。

読み込んでいます...

ただし、これはサービスをデプロイしてからデータベース移行を適用できるようサービスを構築していることが前提となります。ここでは、コンテナの構築とサービスのデプロイを一度に行い(ソースデプロイを使用)、その後にジョブを実行しています。データベース移行を最初に実行する必要がある場合、コンテナを構築し、ジョブを実行してから、サービスをデプロイする必要があります。詳しくは、クラウド スキーマの移行に関するドキュメントをお読みください。

Procfile に関する注意事項

Google Cloud の Buildpacks と Python 以外の言語を使用している方は、Procfile に馴染みがないかもしれません。たとえば JavaScript では、サービスを開始する方法は「1 つ」(package.json で定義されている npm run start)です。Google Cloud の Buildpacks は、JavaScript アプリケーションを検出すると、Procfile がない場合はデフォルトでこれを実行します。

ただし、Python では「1 つのコマンド」で物事を開始できないため、Python ユーザーは Procfile を使用する必要があります。

Procfile の使用を開始したら、web コマンドが何になるかを調べて、それを Procfile に追加する必要があります(執筆時点では、Procfile を含めると、デフォルトのエントリポイント機能を利用できなくなります)。Procfile を使用するかどうかにかかわらず、その場限りのコマンドを実行することは可能です。必ず --command launcher を使用し、コマンドには ---args を使用しましょう。

他に何を自動化できるでしょうか。

このパターンを使用して、他にどんなことができるか考えてみましょう。

Firestore を利用していますか?バックアップはありますか?gcloud firestore export $BUCKET を実行するジョブを設定して自動化できます。

実行したいレポートがある場合は、その設定も行えます。スケジュールを指定して、毎日または週次で実行することができます。

レコードのクリーンアップや、管理者タスクとしてのキャッシュの消去などのメンテナンス タスクを行うジョブを作成することもできます。

今や事実上完璧なサービスに

Cloud Run のジョブの導入により、Cloud Run は、アプリケーション開発の 12 個の要因すべてにおいて 12 点満点を獲得し、次のサーバーレス デプロイに最適な選択肢となりました。

Cloud Run のジョブの詳細については、以下をご覧ください。

Buildpacks の詳細については、以下をご覧ください。

 

- シニア デベロッパーリレーション エンジニア Katie McLaughlin
投稿先