Cloud SQL 言語コネクタを使用して接続する

Cloud SQL コネクタは、Cloud SQL インスタンスへの接続時に暗号化と Identity and Access Management(IAM)ベースの承認を行うライブラリです。Cloud SQL インスタンスへのネットワーク パスがまだ存在しない場合、ネットワーク パスを提供することはできません。

Cloud SQL インスタンスに接続するその他の方法には、データベース クライアントの使用または Cloud SQL Auth Proxy があります。Cloud SQL インスタンスへの接続について詳しくは、接続オプションについてのページをご覧ください。

このページでは、次の Cloud SQL コネクタについて説明します。

  • Cloud SQL Java コネクタ
  • Cloud SQL Python コネクタ(Colab で開く)
  • Cloud SQL Go コネクタ
  • Cloud SQL Node.js コネクタ

利点

Cloud SQL コネクタには、次のような利点があります。

  • IAM 認可: IAM 権限を使用して、Cloud SQL インスタンスに接続できるユーザーや対象を制御します。
  • 簡素化: SSL 証明書の管理、ファイアウォール ルールの構成、承認済みネットワークの有効化が不要になります。
  • IAM データベース認証: Cloud SQL の自動 IAM データベース認証機能をサポートします。

始める前に

  • Cloud SQL Admin API を有効にします。

    Enable the API

  • Cloud SQL インスタンスを作成し、デフォルト ユーザーを構成します。

    インスタンスの作成の詳細については、インスタンスを作成するをご覧ください。

    デフォルト ユーザーの構成の詳細については、デフォルト ユーザー アカウントのパスワードを設定するをご覧ください。

  • Cloud SQL インスタンスへの接続に必要なロールと権限を構成します。

設定

Java

Cloud SQL Java コネクタは、Cloud SQL インスタンスへの接続時に IAM ベースの認可と暗号化を提供するライブラリです。Cloud SQL インスタンスへのネットワーク パスがまだ存在しない場合、ネットワーク パスを提供することはできません。

インストール

JDBC と R2DBC のドライバを Cloud SQL Java コネクタでビルドして使用する方法については、次のリンク先をご覧ください。

このライブラリがアプリケーションのコンテキストでどのように使用されるかについては、サンプル アプリケーションをご覧ください。

認証

このライブラリは、アプリケーションのデフォルト認証情報を使用して Cloud SQL サーバーへの接続を認証します。

認証情報をローカルで有効にするには、次の gcloud コマンドを使用します。

    gcloud auth application-default login
    

Intellij との接続

Cloud SQL インスタンスに IntelliJ を接続するためには、ドライバ設定ページの追加のファイルセクションで、ライブラリを依存関係のある jar として追加する必要があります。たとえば、事前にビルドされた fat jar は Cloud SQL Java コネクタのリリースページに表示されます。

Python

Cloud SQL Python コネクタはデータベース ドライバとともに使用できるライブラリです。これにより、十分な権限があるユーザーは、IP を手動で許可リストに登録することなくCloud SQL データベースに接続できます。またはSSL 証明書を管理できます。

Cloud SQL Python コネクタのインタラクティブな使用例については、Cloud SQL Python コネクタ ノートブックをご覧ください。

PostgreSQL でサポートされているドライバは、pg8000asyncpg です。

インストール

Cloud SQL Python コネクタの最新リリースをインストールするには、pip install コマンドを使用して、データベースの pg8000 ドライバまたは asyncpg ドライバを指定します。

    pip install "cloud-sql-python-connector[pg8000]"
    

または

    pip install "cloud-sql-python-connector[asyncpg]"
    

認証

このライブラリは、アプリケーションのデフォルト認証情報を使用して Cloud SQL サーバーへの接続を認証します。

認証情報をローカルで有効にするには、次の gcloud コマンドを使用します。

    gcloud auth application-default login
    

Go

Cloud SQL Go コネクタは、Go 言語で使用できるように設計された Cloud SQL コネクタです。セキュリティ強化のため、このコネクタは、データベース プロトコルとは無関係に、クライアント コネクタとサーバー側プロキシの間で、堅牢な手動認証 TLS 1.3 暗号化を使用します。

インストール

このリポジトリは go get でインストールできます。

    go get cloud.google.com/go/cloudsqlconn
    

Node.js

Node.js コネクタは、Node.js ランタイムで使用するために設計されたライブラリであり、Cloud SQL インスタンスに安全に接続できます。

インストール

npm install を使用してライブラリをインストールできます。

    npm install @google-cloud/cloud-sql-connector
    

使用

Java

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

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;

public class ConnectorConnectionPoolFactory extends ConnectionPoolFactory {

  // Note: Saving credentials in environment variables is convenient, but not
  // secure - consider a more secure solution such as
  // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
  // keep secrets safe.
  private static final String INSTANCE_CONNECTION_NAME =
      System.getenv("INSTANCE_CONNECTION_NAME");
  private static final String INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
  private static final String DB_USER = System.getenv("DB_USER");
  private static final String DB_PASS = System.getenv("DB_PASS");
  private static final String DB_NAME = System.getenv("DB_NAME");

  public static DataSource createConnectionPool() {
    // The configuration object specifies behaviors for the connection pool.
    HikariConfig config = new HikariConfig();

    // The following URL is equivalent to setting the config options below:
    // jdbc:postgresql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
    // socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=<DB_USER>&password=<DB_PASS>
    // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
    // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url

    // Configure which instance and what database user to connect with.
    config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));
    config.setUsername(DB_USER); // e.g. "root", _postgres"
    config.setPassword(DB_PASS); // e.g. "my-password"

    config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
    config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);


    // The ipTypes argument can be used to specify a comma delimited list of preferred IP types
    // for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
    // SocketFactory to connect with an instance's associated private IP.
    config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");


    // ... Specify additional connection properties here.
    // ...

    // Initialize the connection pool using the configuration object.
    return new HikariDataSource(config);
  }
}

Python

ライブラリを使用する際の詳細な手順については、このコネクタの使用方法をご覧ください。GitHub で、接続テストのコード例を確認してください。

import os

from google.cloud.sql.connector import Connector, IPTypes
import pg8000

import sqlalchemy


def connect_with_connector() -> sqlalchemy.engine.base.Engine:
    """
    Initializes a connection pool for a Cloud SQL instance of Postgres.

    Uses the Cloud SQL Python Connector package.
    """
    # Note: Saving credentials in environment variables is convenient, but not
    # secure - consider a more secure solution such as
    # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
    # keep secrets safe.

    instance_connection_name = os.environ[
        "INSTANCE_CONNECTION_NAME"
    ]  # e.g. 'project:region:instance'
    db_user = os.environ["DB_USER"]  # e.g. 'my-db-user'
    db_pass = os.environ["DB_PASS"]  # e.g. 'my-db-password'
    db_name = os.environ["DB_NAME"]  # e.g. 'my-database'

    ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC

    # initialize Cloud SQL Python Connector object
    connector = Connector()

    def getconn() -> pg8000.dbapi.Connection:
        conn: pg8000.dbapi.Connection = connector.connect(
            instance_connection_name,
            "pg8000",
            user=db_user,
            password=db_pass,
            db=db_name,
            ip_type=ip_type,
        )
        return conn

    # The Cloud SQL Python Connector can be used with SQLAlchemy
    # using the 'creator' argument to 'create_engine'
    pool = sqlalchemy.create_engine(
        "postgresql+pg8000://",
        creator=getconn,
        # ...
    )
    return pool

Go

ライブラリを使用する際の詳細な手順については、使用方法をご覧ください。GitHub で、接続テストのコード例を確認してください。

package cloudsql

import (
	"context"
	"database/sql"
	"fmt"
	"log"
	"net"
	"os"

	"cloud.google.com/go/cloudsqlconn"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/stdlib"
)

func connectWithConnector() (*sql.DB, error) {
	mustGetenv := func(k string) string {
		v := os.Getenv(k)
		if v == "" {
			log.Fatalf("Fatal Error in connect_connector.go: %s environment variable not set.\n", k)
		}
		return v
	}
	// Note: Saving credentials in environment variables is convenient, but not
	// secure - consider a more secure solution such as
	// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
	// keep passwords and other secrets safe.
	var (
		dbUser                 = mustGetenv("DB_USER")                  // e.g. 'my-db-user'
		dbPwd                  = mustGetenv("DB_PASS")                  // e.g. 'my-db-password'
		dbName                 = mustGetenv("DB_NAME")                  // e.g. 'my-database'
		instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
		usePrivate             = os.Getenv("PRIVATE_IP")
	)

	dsn := fmt.Sprintf("user=%s password=%s database=%s", dbUser, dbPwd, dbName)
	config, err := pgx.ParseConfig(dsn)
	if err != nil {
		return nil, err
	}
	var opts []cloudsqlconn.Option
	if usePrivate != "" {
		opts = append(opts, cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPrivateIP()))
	}
	d, err := cloudsqlconn.NewDialer(context.Background(), opts...)
	if err != nil {
		return nil, err
	}
	// Use the Cloud SQL connector to handle connecting to the instance.
	// This approach does *NOT* require the Cloud SQL proxy.
	config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
		return d.Dial(ctx, instanceConnectionName)
	}
	dbURI := stdlib.RegisterConnConfig(config)
	dbPool, err := sql.Open("pgx", dbURI)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

Node.js

ライブラリの使用方法については、使用状況をご覧ください。

const Knex = require('knex');
const {Connector} = require('@google-cloud/cloud-sql-connector');

// In case the PRIVATE_IP environment variable is defined then we set
// the ipType=PRIVATE for the new connector instance, otherwise defaults
// to public ip type.
const getIpType = () =>
  process.env.PRIVATE_IP === '1' || process.env.PRIVATE_IP === 'true'
    ? 'PRIVATE'
    : 'PUBLIC';

// connectWithConnector initializes connection pool for a Cloud SQL instance
// of Postgres using the Cloud SQL Node.js Connector.
const connectWithConnector = async config => {
  // Note: Saving credentials in environment variables is convenient, but not
  // secure - consider a more secure solution such as
  // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
  // keep secrets safe.
  const connector = new Connector();
  const clientOpts = await connector.getOptions({
    instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME,
    ipType: getIpType(),
  });
  const dbConfig = {
    client: 'pg',
    connection: {
      ...clientOpts,
      user: process.env.DB_USER, // e.g. 'my-user'
      password: process.env.DB_PASS, // e.g. 'my-user-password'
      database: process.env.DB_NAME, // e.g. 'my-database'
    },
    // ... Specify additional properties here.
    ...config,
  };
  // Establish a connection to the database.
  return Knex(dbConfig);
};

適用

コネクタの適用を使用すると、Cloud SQL Auth Proxy または Cloud SQL 言語コネクタのみを使用して Cloud SQL インスタンスに接続するように強制できます。コネクタ強制が適用されている場合、Cloud SQL はデータベースへの直接接続を拒否します。

Private Service Connect が有効になっているインスタンスを使用している場合は、制限があります。インスタンスでコネクタ適用が有効になっている場合、そのインスタンスのリードレプリカは作成できません。同様に、インスタンスにリードレプリカがある場合、インスタンスでコネクタ適用を有効にすることはできません。

gcloud

Cloud SQL Auth Proxy または Cloud SQL 言語コネクタのみを使用してインスタンスに接続するように強制するには、gcloud sql instances patch コマンドを使用します。

gcloud sql instances patch INSTANCE_NAME \
--connector-enforcement=REQUIRED

INSTANCE_NAME は、Cloud SQL インスタンスの名前に置き換えます。

REST

リクエストのデータを使用する前に、次のように置き換えます。

  • PROJECT_ID: インスタンスが含まれている Google Cloud プロジェクトの ID またはプロジェクト番号
  • INSTANCE_NAME: Cloud SQL インスタンスの名前

HTTP メソッドと URL:

PATCH https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_NAME

リクエストの本文(JSON):

{
  "kind": "sql#instance",
  "name": INSTANCE_NAME,
  "project": PROJECT_ID,
  "settings": {
  "connectorEnforcement": "REQUIRED",
  "kind": "sql#settings"
  }
}

リクエストを送信するには、次のいずれかのオプションを展開します。

次のような JSON レスポンスが返されます。

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_NAME",
  "status": "PENDING",
  "user": "user@example.com",
  "insertTime": "2020-01-16T02:32:12.281Z",
  "operationType": "UPDATE",
  "name": "OPERATION_ID",
  "targetId": "INSTANCE_NAME",
  "selfLink": "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/operations/OPERATION_ID",
  "targetProject": "PROJECT_ID"
}

トラブルシューティング

ドライバのバージョン

非互換性の問題を回避するため、最新バージョンの Cloud SQL コネクタとデータベース ドライバを使用してください。一部の古いバージョンのドライバはサポートされていません。

接続パス

Cloud SQL コネクタでは接続の承認が提供されますが、接続するための新しいパスは提供されません。たとえば、プライベート IP アドレスを使用して Cloud SQL インスタンスに接続するには、アプリケーションがすでに VPC にアクセスできる必要があります。

接続の問題をデバッグする

接続の問題について詳しくは、トラブルシューティング接続の問題をデバッグするのページをご覧ください。

次のステップ