Cloud Functions から Cloud SQL への接続

このページでは、Cloud Functions で実行されているサービスから Cloud SQL インスタンスへの接続に関する情報と例を示しています。

Cloud SQL は、クラウド内のリレーショナル データベースの設定、維持、管理に役立つフルマネージド データベース サービスです。

Cloud Functions は軽量なコンピューティング ソリューションで、開発者はサーバーやランタイム環境を管理せずに、Cloud イベントに応答する単一目的のスタンドアロン関数を作成できます。

Cloud SQL インスタンスの設定

  1. 接続元のプロジェクトで Cloud SQL Admin API を有効にします(まだ有効にしていない場合)。

    API を有効にする

  2. Cloud SQL for MySQL インスタンスを作成します

    Cloud SQL は、デフォルトで新しいインスタンスにパブリック IP アドレスを割り当てます。プライベート IP アドレスを割り当てることもできます。両方の接続オプションの詳細については、[接続の概要] ページをご覧ください。

Cloud Functions の構成

Cloud Functions を構成する手順は、Cloud SQL インスタンスに割り当てられた IP アドレスのタイプによって異なります。

パブリック IP(デフォルト)

Cloud SQL インスタンスへの接続を有効にするように Cloud Functions を構成するには、次のようにします。

  • 上記で作成したインスタンスにパブリック IP アドレスがあることを確認します。これは、Google Cloud Console のインスタンスの [概要] ページで確認できます。パブリック IP を追加する必要がある場合は、パブリック IP の構成ページの手順をご覧ください。
  • インスタンスの INSTANCE_CONNECTION_NAME を取得します。これは、Google Cloud Console のインスタンスの [概要] ページで確認できます。また、コマンド gcloud sql instances describe [INSTANCE_NAME] を実行して確認することもできます。
  • 関数が Cloud SQL の呼び出しを認証するために使用しているサービス アカウントに、適切な Cloud SQL のロールと権限があることを確認します。
    • お使いのサービスのサービス アカウントには、次のいずれかの IAM ロールが必要です。
      • Cloud SQL Client(推奨)
      • Cloud SQL Editor
      • Cloud SQL Admin
      または、次の IAM 権限を手動で割り当てることもできます。
      • cloudsql.instances.connect
      • cloudsql.instances.get
      サービス アカウントに IAM ロールを追加する方法の詳細については、サービス アカウントへのロールの付与をご覧ください。

    デフォルトでは、アプリは Cloud Functions サービス アカウントを使用して接続を承認します。サービス アカウントの形式は service-PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com です。

    サービス アカウントの承認が Cloud SQL インスタンスとは異なるプロジェクトに属している場合、Cloud SQL Admin API と IAM の権限を両方のプロジェクトに追加する必要があります。

プライベート IP

サーバーレス VPC アクセス コネクタは VPC ネットワークとの通信を処理します。 プライベート IP に直接接続するには、次のようにする必要があります。

  1. 上記で作成した Cloud SQL インスタンスにプライベート IP アドレスが割り当てられていることを確認します。プライベート IP を追加する必要がある場合は、プライベート IP の構成ページの手順をご覧ください。
  2. Cloud SQL インスタンスと同じ VPC ネットワークにサーバーレス VPC アクセス コネクタを作成します。
  3. コネクタは、それを使用するリソースと同じプロジェクトとリージョンに配置する必要がありますが、異なるリージョンのリソースにトラフィックを送信できます。

    サーバーレス VPC アクセスでは、Cloud VPNVPC ネットワーク ピアリングを介して接続された VPC ネットワークとの通信がサポートされています。

    サーバーレス VPC アクセスは、レガシー ネットワークをサポートしていません。

  4. コネクタを使用するように Cloud Functions を構成します
  5. インスタンスのプライベート IP とポート 3306 を使用して接続します。

Cloud SQL への接続

Cloud Functions を構成すると、Cloud SQL インスタンスに接続できます。Cloud Functions には、Cloud SQL Proxy を使用して接続する仕組みが用意されています。

パブリック IP(デフォルト)

プライベート IP

TCP で接続

インスタンスのプライベート IP アドレスとポート 3306 を使用して直接接続します。

Python

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

# Remember - storing secrets in plaintext is potentially unsafe. Consider using
# something like https://cloud.google.com/secret-manager/docs/overview to help keep
# secrets secret.
db_user = os.environ["DB_USER"]
db_pass = os.environ["DB_PASS"]
db_name = os.environ["DB_NAME"]
db_host = os.environ["DB_HOST"]

# Extract host and port from db_host
host_args = db_host.split(":")
db_hostname, db_port = host_args[0], int(host_args[1])

pool = sqlalchemy.create_engine(
    # Equivalent URL:
    # mysql+pymysql://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
    sqlalchemy.engine.url.URL(
        drivername="mysql+pymysql",
        username=db_user,  # e.g. "my-database-user"
        password=db_pass,  # e.g. "my-database-password"
        host=db_hostname,  # e.g. "127.0.0.1"
        port=db_port,  # e.g. 3306
        database=db_name,  # e.g. "my-database-name"
    ),
    # ... Specify additional properties here.
)

Node.js

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

const createTcpPool = async (config) => {
  // Extract host and port from socket address
  const dbSocketAddr = process.env.DB_HOST.split(":")

  // Establish a connection to the database
  return await mysql.createPool({
    user: process.env.DB_USER, // e.g. 'my-db-user'
    password: process.env.DB_PASS, // e.g. 'my-db-password'
    database: process.env.DB_NAME, // e.g. 'my-database'
    host: dbSocketAddr[0], // e.g. '127.0.0.1'
    port: dbSocketAddr[1], // e.g. '3306'
    // ... Specify additional properties here.
    ...config
  });
}

Go

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

var (
	dbUser    = mustGetenv("DB_USER")     // e.g. 'my-db-user'
	dbPwd     = mustGetenv("DB_PASS")     // e.g. 'my-db-password'
	dbTcpHost = mustGetenv("DB_TCP_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
	dbPort    = mustGetenv("DB_PORT")     // e.g. '3306'
	dbName    = mustGetenv("DB_NAME")     // e.g. 'my-database'
)

var dbURI string
dbURI = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", dbUser, dbPwd, dbTcpHost, dbPort, dbName)

// dbPool is the pool of database connections.
dbPool, err := sql.Open("mysql", dbURI)
if err != nil {
	return nil, fmt.Errorf("sql.Open: %v", err)
}

// ...

return dbPool, nil

ベスト プラクティスとその他の情報

アプリケーションをローカルでテストする場合、Cloud SQL プロキシを使用できます。詳細については、ローカルテストにプロキシを使用する場合のクイックスタートを参照してください。

接続プール

基礎となるデータベースとの接続が、データベース サーバー自体または Cloud Functions のインフラストラクチャによって切断される可能性があります。切断されたクライアント接続を自動的に再接続する接続プールをサポートするクライアント ライブラリを使用することをおすすめします。さらに、グローバル スコープの接続プールを使用することをおすすめします。これにより、関数で、後続の関数の呼び出しで同じ接続が再利用される可能性が高くなり、インスタンスが強制削除(自動スケールダウン)されると、接続が自然に終了するためです。接続プールの使用方法の詳しい例については、データベース接続を管理するをご覧ください。

接続上限

Cloud SQL では、同時接続の上限が設定されています。これらの上限は、選択したデータベース エンジンによって異なる場合があります。詳しくは、Cloud SQL の割り当てと上限をご覧ください。Cloud Functions との接続を使用することをおすすめしますが、最大接続数を 1 に設定することが重要です。

可能な場合は、データベースにアクセスする必要がある関数の接続プールのみを初期化してください。一部の接続プールは、事前に接続を作成します。これにより、過剰なリソースが消費され、接続制限に加算される可能性があります。このため、遅延初期化を行って、必要となるまで接続プールの作成を遅らせ、接続プールが使用される関数にのみ接続プールを含めることをおすすめします。

接続数を制限する方法の詳細については、データベース接続を管理するをご覧ください。

API の割り当て上限

Cloud Functions には、Cloud SQL Admin API を使用する Cloud SQL Proxy を使用して接続する仕組みが用意されています。Cloud SQL Proxy には API 割り当て上限が適用されます。