はじめに
背景
AlloyDBには、現時点で「マネージドな自動起動/停止」機能が提供されていません。
開発・検証用途では、夜間や週末に停止することでコスト最適化したいケースが多いため、Google Cloudのマネージドサービスを組み合わせて自動化を実装しました。
目的
定期的なスケジュールに合わせて、AlloyDBのインスタンスを自動で停止・起動する。
仕組み
全体構成
①Cloud Scheduler → ②Cloud Run(HTTP)→ ③AlloyDB Admin API(start/stop)
①:Cloud Schedulerが指定時刻にHTTPリクエストをCloud Runへ送信する。
②~③:Cloud Runは受け取ったパラメータに基づいて、AlloyDB の「起動」・「停止」APIを呼び出します。
Cloud Runは、RuntimeのService Accountで認可され、AlloyDB のプロジェクト/ロケーション/クラスタ/インスタンスを指定して「起動」・「停止」を実行します。
※Cloud Runでは、環境変数で、プロジェクトIDとインスタンスの情報を取得を実施している。
実行結果(成功/失敗、インスタンスの状態)をCloud Loggingへ出力する。
サービスアカウント
上記の実行には、サービスアカウントを利用して、処理します。
サービスアカウントの権限は、以下のとおりです。
・AlloyDB 管理者
・Cloud Run サービス起動元
・ログ書き込み
デプロイ時の設定
Cloud Scheduler
起動設定
平日8:30 に起動処理を行いたい場合、以下のように設定を行います。
cronの設定方法の詳細は、cron ジョブの形式とタイムゾーンをご参照ください。
Cloud Run
今回実装した、Cloud Runソースコードは、以下のとおりです。
<起動処理>
import functions_framework
import requests
import os
# 環境変数からプロジェクトIDとインスタンス情報を取得
PROJECT_ID = os.environ.get('PROJECT_ID')
LOCATION = os.environ.get('LOCATION')
CLUSTER_ID = os.environ.get('CLUSTER_ID')
INSTANCE_ID = os.environ.get('INSTANCE_ID')
@functions_framework.http
def start_alloydb_instance(request):
"""
HTTPリクエストを受け取り、AlloyDB Admin APIを呼び出してインスタンスを起動します。
"""
if not all([PROJECT_ID, LOCATION, CLUSTER_ID, INSTANCE_ID]):
print("Error: Required environment variables are not set.")
return 'Error: Required environment variables are missing', 500
# AlloyDBインスタンスのリソースパス
instance_name = f'projects/{PROJECT_ID}/locations/{LOCATION}/clusters/{CLUSTER_ID}/instances/{INSTANCE_ID}'
api_url = f'https://alloydb.googleapis.com/v1beta/{instance_name}'
# APIリクエストのペイロード
payload = {
"activationPolicy": "ALWAYS"
}
# APIリクエストのクエリパラメータ
params = {
"updateMask": "activationPolicy"
}
try:
# **認証ヘッダーの取得**
# Cloud Functions/Run 環境では、実行環境に割り当てられたサービスアカウント
# IDトークン(ID Token)を自動的に取得し、Authorizationヘッダーに設定することで認証を行う。
# Google Cloud のクライアントライブラリ(google-auth)を使用するとこの処理が簡略化。
from google.auth import default
from google.auth.transport.requests import AuthorizedSession
# 認証情報とセッションを取得
credentials, project = default()
authed_session = AuthorizedSession(credentials)
# PATCHリクエストの実行
print(f"AlloyDBインスタンス: {instance_name} の起動リクエストを送信中...")
response = authed_session.patch(
api_url,
json=payload,
params=params
)
# 応答の確認
response.raise_for_status() # HTTPエラーレスポンスをチェック
# レスポンスは長時間実行オペレーション(LRO)を示す
operation_name = response.json().get('name')
log_message = f'AlloyDBインスタンス起動リクエストが正常に送信されました。Operation: {operation_name}'
print(log_message)
return log_message, 200
except requests.exceptions.HTTPError as e:
error_message = f'AlloyDB API呼び出しエラー: {e.response.text}'
print(error_message)
return error_message, e.response.status_code
except Exception as e:
error_message = f'予期せぬエラーが発生しました: {str(e)}'
print(error_message)
return error_message, 500
停止処理については割愛しますが、APIリクエストのペイロードを停止:NEVERとすることで、実装可能です。
実際に動かしてみる
Cloud Schedulerを有効にしていると、自動実行はできるが、今回は「強制実行」して、処理が正常動作するか確認する。
Cloud Runから受け取ったパラメータに基づいて、AlloyDB の「起動」のAPIが呼び出され、AlloyDBのプライマリインスタンスのステータスが「開始中」となり、起動処理が開始されました。

数分~数十分ほどで、AlloyDBのプライマリインスタンスのステータスが「準備完了」となり、無事にCloud Scheduler+Cloud Run経由での起動が完了しました。

苦労した点
APIリクエストは、「start」や「stop」のような専用のAPIを呼び出すと当初思い込んでいましたが、調べてみると、実際はインスタンスのアクティベーションポリシーフィールドを更新するAPIリクエストを使用し、「起動」=ALWAYS、「停止」=NEVERと設定することが正しく、躓いてしまいました。
参考
まとめ
今回の検証では、Cloud Scheduler+Cloud Run+AlloyDB Admin APIを組み合わせることで、AlloyDBの自動起動・停止をシンプルに実装できることを確認しました。
手動での起動停止だと、起動・停止忘れが発生していまいます。そのため、常時起動ではない場合は、このような仕組みを入れることで、コスト最適化や開発環境の運用効率化を図ることが可能です。
留意点として、プライマリインスタンスのみの起動・停止であれば本記事の方法で対応できますが、読み取りプールインスタンスも含めて自動起動・停止を行いたい場合は、追加の考慮が必要です。その内容は、次回の記事として別途詳細を解説したいと考えております。


