開発費用の削減: Cloud SQL インスタンスの起動と停止をスケジュールする
はじめに
こんにちは、クラウドエースの許と申します。
こちらの記事は、2021 年 6 月 21 日に Google Cloud の公式ブログで投稿された「開発費用の削減: Cloud SQL インスタンスの起動と停止をスケジュールする」(以降、2021 年記事)の 2024 年 9 月版(以降、2024 年版)となります。
2021 年記事では、Cloud Run Functions(旧: Cloud Functions)を利用して起動と停止の制御を行なっていたのですが、当時より以下の2点が変わっているため、2021 年記事のリマスター版的な位置付けで当記事を執筆しております。
- Cloud Run Functions の仕様やUIが大幅に変わっている
- 2021 年記事で利用していた、
SQLAdminの関数の一部が非推奨になっている
前提
作業者がオーナー権限を持った Google Cloud プロジェクトで操作を行なっていきます。
もし操作の途中で不足している権限がありましたら、適宜必要な権限を付与してください。
SQLインスタンスの作成
[インスタンスを作成]をクリックして、SQL インスタンスを作成します。

-
使用したいデータベースエンジンを選択します。(筆者は MySQL が好みなので、MySQL を選択します。)

-
エディションのプリセット、インスタンスID、パスワード、リージョンを入力していきます。今回は動作するかどうかの確認が目的なので、最低限の設定で進めます。


-
[インスタンスを作成]をクリックします。
Cloud Pub/Sub トピックの作成
サブスクリプションはトリガーに設定すると自動で作成されるため、トピックのみ作成します。
手順は少ないですが、以下の操作で作成できます。
- Cloud Pub/Sub の画面を開いて、[トピックを作成]を押下します。
- トピック ID を記入して、トピックを作成します。(トピック ID はなんでもいいですが、今回は
InstanceMgmtで進めていきます。)
Cloud SQL インスタンスの起動と停止を制御する Cloud Run Functions の作成
このセクションが 2021 年記事と大きく異なる部分です。
2021 年記事では、第一世代を利用していましたが、2024 年時点では第二世代を利用します。
第一世代と異なる点は、イベントの受け取り方が event.Event を利用して受け取るようになったことです。
ただし、画面上での操作は大きく変わらないため、手順に従って進めていただければ問題ありません。
なお、2021 年記事と同様に画面上で関数を作成する予定でしたが、原因不明のエラーが発生したため、今回は gcloud コマンドを利用して関数を作成します。

Cloud Run Functionsの作成の有効化
- Cloud Run Functions の画面を開きます。
- [ファンクションを作成]をクリックします。
- 以下の画面が表示されたら、[有効にする]をクリックします。(すでに有効になっている場合はこの画面は表示されません。)
コードの実装
-
functions.goとgo.modの2つのファイルを作成します。
- 以下の内容で
functions.goを作成します。
// Package p contains a Pub/Sub Cloud Function.
package p
import (
"context"
"encoding/json"
"fmt"
"github.com/cloudevents/sdk-go/v2/event"
"google.golang.org/api/option"
"log"
"github.com/GoogleCloudPlatform/functions-framework-go/functions"
sqladmin "google.golang.org/api/sqladmin/v1beta4"
)
func init() {
functions.CloudEvent("ProcessPubSub", ProcessPubSub)
}
// PubSubMessage is the payload of a Pub/Sub event.
// See the documentation for more details:
// https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage
type PubSubMessage struct {
Data []byte `json:"data"`
}
type MessagePublishedData struct {
Message PubSubMessage
}
type MessagePayload struct {
Instance string
Project string
Action string
}
// ProcessPubSub consumes and processes a Pub/Sub message.
func ProcessPubSub(ctx context.Context, e event.Event) error {
log.Println("ProcessPubSub function invoked")
// Unmarshal the Pub/Sub message.
var pubsubData MessagePublishedData
if err := e.DataAs(&pubsubData); err != nil {
fmt.Errorf("error unmarshalling Pub/Sub message: %v", err)
}
var psData MessagePayload
err := json.Unmarshal(pubsubData.Message.Data, &psData)
if err != nil {
log.Println(err)
}
log.Printf("Request received for Cloud SQL instance %s action: %s, %s", psData.Action, psData.Instance, psData.Project)
// Create the Google Cloud SQL service.
sqladminService, err := sqladmin.NewService(ctx, option.WithScopes(sqladmin.CloudPlatformScope))
// Get the requested start or stop Action.
action := "UNDEFINED"
switch psData.Action {
case "start":
action = "ALWAYS"
case "stop":
action = "NEVER"
default:
log.Printf("No valid action provided")
}
// See more examples at:
// https://cloud.google.com/sql/docs/sqlserver/admin-api/rest/v1beta4/instances/patch
rb := &sqladmin.DatabaseInstance{
Settings: &sqladmin.Settings{
ActivationPolicy: action,
},
}
resp, err := sqladminService.Instances.Patch(psData.Project, psData.Instance, rb).Context(ctx).Do()
if err != nil {
log.Fatal(err)
}
log.Printf("%#v\n", resp)
return nil
}
- 以下の内容で
go.modを作成します。
module example.com/gcf
go 1.22.7
require (
github.com/GoogleCloudPlatform/functions-framework-go v1.7.0
github.com/cloudevents/sdk-go/v2 v2.15.2
google.golang.org/api v0.196.0
)
require (
cloud.google.com/go/auth v0.9.3 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute/metadata v0.5.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.3 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
github.com/json-iterator/go v1.1.10 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect
go.opentelemetry.io/otel/metric v1.29.0 // indirect
go.opentelemetry.io/otel/trace v1.29.0 // indirect
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.10.0 // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sys v0.24.0 // indirect
golang.org/x/text v0.17.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/grpc v1.66.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)
- 以下の内容で関数を作成します。下記のコマンドを実行してください。(コマンドはカレントディレクトリが
functions.goとgo.modが入ったディレクトリを前提としています。カレントディレクトリが別の場所にある場合は、移動して実行をお願いします。)- 環境名: Cloud Run function
- 関数名:
start-or-stop-cloud-sql-instance - リージョン: asia-northeast1
- トリガー: Cloud Pub/Sub
- トピック: InstanceMgmt
- ランタイム: Go 1.22
gcloud functions deploy start-or-stop-cloud-sql-instance \
--gen2 \
--runtime=go122 \
--region=asia-northeast1 \
--source=. \
--entry-point=ProcessPubSub \
--trigger-topic=InstanceMgmt \
--project=<プロジェクト ID>
- Cloud Build が動いて、デプロイされるので、しばらく待ちます。
- 画像のように関数が作成されていたら成功です。
Cloud Run Functions のサービスアカウントに IAM ロールを付与
現状のままだと、SQL を起動、停止する権限がないため、サービスアカウントに IAM ロールを付与します。
- IAM と管理の画面を開きます。
- Cloud Run Functions で利用しているサービスアカウントのペンマークをクリックします。
-
Cloud SQL 管理者のロールを付与します。
- [保存]をクリックします。
Cloud SQL Admin API の有効化
- API とサービスの画面を開きます。
-
Cloud SQL Admin APIを検索して、有効化します。
これで、Cloud Run Functions を動作させるための準備が整いました。
Cloud Schedulerの設定
ここは 2021 年記事と変わらないため、手順に従って進めていただければ問題ありません。
-
Cloud Scheduler の画面を開き、[ジョブの作成]をクリックします。
-
名前、リージョン、頻度、タイムゾーンを設定し[続行]をクリックします。
-
[ターゲットタイプ]から Pub/Sub を選択します。
-
前章で作成したトピックを選択します。
-
以下記載の Pub/Sub メッセージを[メッセージ本文]に記入します。
- 起動メッセージ
{ "Instance": "<SQLインスタンス名>", "Project": "<プロジェクト名>", "Action": "start" }- 停止メッセージ
{ "Instance": "<SQLインスタンス名>", "Project": "<プロジェクト名>", "Action": "stop" }

-
[作成]をクリックします。
この手順が終了すると、Cloud SQL インスタンスの起動と停止をスケジュールすることができるようになります。
おわりに
今回は、Cloud SQL インスタンスの起動と停止をスケジュールする方法をご紹介しました。
こちらの記事が開発費用の削減の一助になれば幸いです。
Discussion