使用 Cloud SQL Auth 代理连接

本页面介绍了如何使用 Cloud SQL Auth 代理连接到 Cloud SQL 实例。

如需详细了解 Cloud SQL Auth 代理的工作原理,请参阅 Cloud SQL Auth 代理简介

概览

如需连接到 Cloud SQL 实例,建议使用方法 Cloud SQL Auth 代理。Cloud SQL Auth 代理:

  • 适用于公共和专用 IP 端点
  • 使用用户或服务账号的凭据验证连接
  • 将连接封装在针对 Cloud SQL 实例授权的 SSL/TLS 层中。

某些 Google Cloud 服务和应用使用 Cloud SQL Auth 代理,通过加密和授权为公共 IP 路径提供连接,包括:

Google Kubernetes Engine 中运行的应用可以使用 Cloud SQL Auth 代理进行连接。

请参阅 Cloud SQL Auth 代理使用快速入门,以便大致了解其使用方式。

您还可以使用本地机器或 Compute Engine 中的 sqlcmd 客户端进行连接,无论是否使用 Cloud SQL Auth 代理。

须知事项

在连接到 Cloud SQL 实例之前,请执行以下操作:

    • 对于用户或服务账号,请确保该账号具有 Cloud SQL Client 角色。此角色包含 cloudsql.instances.connect 权限,此权限向主账号授予连接到项目中的所有 Cloud SQL 实例的权限。

      转到 IAM 页面

    • 您可以选择在 IAM 政策绑定中添加 IAM 条件,向账号授予仅连接到一个特定 Cloud SQL 实例的权限。
  1. Enable the Cloud SQL Admin API.

    Enable the API

  2. 安装并初始化 gcloud CLI
  3. 可选。安装 Cloud SQL Auth 代理 Docker 客户端

下载 Cloud SQL Auth 代理

Linux 64 位

  1. 下载 Cloud SQL Auth 代理:
    curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.linux.amd64
  2. 使 Cloud SQL Auth 代理可执行:
    chmod +x cloud-sql-proxy

Linux 32 位

  1. 下载 Cloud SQL Auth 代理:
    curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.linux.386
  2. 如果找不到 curl 命令,请运行 sudo apt install curl 并重复执行下载命令。
  3. 使 Cloud SQL Auth 代理可执行:
    chmod +x cloud-sql-proxy

macOS 64 位

  1. 下载 Cloud SQL Auth 代理:
    curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.darwin.amd64
  2. 使 Cloud SQL Auth 代理可执行:
    chmod +x cloud-sql-proxy

Mac M1

  1. 下载 Cloud SQL Auth 代理:
      curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.darwin.arm64
      
  2. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud-sql-proxy
      

Windows 64 位

右键点击 https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.x64.exe,然后选择链接另存为以下载 Cloud SQL Auth 代理。将文件重命名为 cloud-sql-proxy.exe

Windows 32 位

右键点击 https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.x86.exe,然后选择链接另存为以下载 Cloud SQL Auth 代理。将文件重命名为 cloud-sql-proxy.exe

Cloud SQL Auth 代理 Docker 映像

Cloud SQL Auth 代理有不同的容器映像,例如 distrolessalpinebuster。默认的 Cloud SQL Auth 代理容器映像使用不包含 shell 的 distroless。如果您需要 shell 或相关工具,请下载基于 alpinebuster 的映像。如需了解详情,请参阅 Cloud SQL Auth 代理容器映像

您可以通过 Docker 使用以下命令将最新映像拉取到本地机器:

docker pull gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.13.0

其他操作系统

对于此处未列出的其他操作系统,您可以通过源代码编译 Cloud SQL Auth 代理

启动 Cloud SQL Auth 代理

您可以使用 TCP 套接字或 Cloud SQL Auth 代理 Docker 映像启动 Cloud SQL Auth 代理。Cloud SQL Auth 代理二进制文件会连接到命令行中指定的一个或多个 Cloud SQL 实例,并打开本地连接作为 TCP 套接字。其他应用和服务(例如您的应用代码或数据库管理客户端工具)可以通过“该 TCP 套接字连接”连接到 Cloud SQL 实例。

TCP 套接字

对于 TCP 连接,Cloud SQL Auth 代理默认监听 localhost (127.0.0.1)。因此,当您为实例指定 --port PORT_NUMBER 时,本地连接位于 127.0.0.1:PORT_NUMBER

或者,您也可以为本地连接指定其他地址。例如,下方展示了如何让 Cloud SQL Auth 代理监听 0.0.0.0:1234 的本地连接:

./cloud-sql-proxy --address 0.0.0.0 --port 1234 INSTANCE_CONNECTION_NAME
  1. 复制您的 INSTANCE_CONNECTION_NAME。您可以在 Google Cloud 控制台中的实例概览页面上或者通过运行以下命令找到它:

        gcloud sql instances describe INSTANCE_NAME --format='value(connectionName)'

    例如:myproject:myregion:myinstance

  2. 如果实例同时配置了公共 IP 和专用 IP,并且您希望 Cloud SQL Auth 代理使用专用 IP 地址,您必须在启动 Cloud SQL Auth 代理时提供以下选项:
    --private-ip
  3. 如果您要使用服务账号对 Cloud SQL Auth 代理进行身份验证,请记下随服务账号一起创建的私钥文件在客户端机器上的位置。
  4. 启动 Cloud SQL Auth 代理。

    一些可能的 Cloud SQL Auth 代理调用字符串如下所示:

    • 使用 Cloud SDK 身份验证:
      ./cloud-sql-proxy --port 1433 INSTANCE_CONNECTION_NAME
      指定的端口必须尚未被本地数据库服务器等所占用。
    • 使用服务账号并明确包含实例连接的名称(建议用于生产环境):
      ./cloud-sql-proxy \
      --credentials-file PATH_TO_KEY_FILE INSTANCE_CONNECTION_NAME &

    如需详细了解 Cloud SQL Auth 代理选项,请参阅用于对 Cloud SQL Auth 代理进行身份验证的选项

Docker

如需在 Docker 容器中运行 Cloud SQL Auth 代理,请使用 Google Container Registry 提供的 Cloud SQL Auth 代理 Docker 映像。

您可以使用以下所示命令通过 TCP 套接字或 Unix 套接字启动 Cloud SQL Auth 代理。这些选项使用 INSTANCE_CONNECTION_NAME 作为连接字符串来标识 Cloud SQL 实例。您可以在 Google Cloud 控制台中的实例概览页面上或者通过运行以下命令找到 INSTANCE_CONNECTION_NAME

gcloud sql instances describe INSTANCE_NAME

例如:myproject:myregion:myinstance

您可以使用 TCP 套接字或 Unix 套接字启动 Cloud SQL Auth 代理,具体使用哪一个要取决于您所用的语言和环境。采用 Java 编程语言编写的应用或 Windows 环境不支持 Unix 套接字。

使用 TCP 套接字

docker run -d \\
  -v PATH_TO_KEY_FILE:/path/to/service-account-key.json \\
  -p 127.0.0.1:1433:1433 \\
  gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.13.0 \\
  --address 0.0.0.0 --port 1433 \\
  --credentials-file /path/to/service-account-key.json INSTANCE_CONNECTION_NAME

如果您使用的是 Compute Engine 实例提供的凭据,请勿包含 --credentials-file 参数和 -v PATH_TO_KEY_FILE:/path/to/service-account-key.json 行。

请务必在 -p 中指定 127.0.0.1 前缀,以免 Cloud SQL Auth 代理在本地主机外部公开。若要从 Docker 容器外部访问端口,需要在实例参数中指定“0.0.0.0”。

使用 Unix 套接字

docker run -d -v /cloudsql:/cloudsql \\
  -v PATH_TO_KEY_FILE:/path/to/service-account-key.json \\
  gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.13.0 --unix-socket=/cloudsql \\
  --credentials-file /path/to/service-account-key.json INSTANCE_CONNECTION_NAME

如果您使用的是 Compute Engine 实例提供的凭据,请勿包含 --credentials-file 参数和 -v PATH_TO_KEY_FILE:/path/to/service-account-key.json 行。

如果您使用的是容器优化型映像,请使用可写目录代替 /cloudsql,例如:

-v /mnt/stateful_partition/cloudsql:/cloudsql

您可以指定多个实例(用英文逗号分隔),您还可以使用 Compute Engine 元数据以动态方式确定要连接的实例。 详细了解 Cloud SQL Auth 代理参数

连接到 sqlcmd 客户端

Debian/Ubuntu

对于 Debian/Ubuntu,请安装适用的 SQL Server 命令行工具

CentOS/RHEL

对于 CentOS/RHEL,请安装适用的 SQL Server 命令行工具

openSUSE

对于 openSUSE,请安装适用的 SQL Server 命令行工具

其他平台

如需了解如何安装 SQL Server,请参阅着陆页,以及 SQL Server 下载页面

使用的连接字符串取决于您是使用 TCP 套接字还是 Docker 启动 Cloud SQL Auth 代理。

TCP 套接字

  1. 启动 sqlcmd 客户端:
    sqlcmd -S tcp:127.0.0.1,1433 -U USERNAME -P PASSWORD

    使用 TCP 套接字连接时,可通过 127.0.0.1 访问 Cloud SQL Auth 代理。

  2. 如果出现提示,请输入密码。
  3. 系统会显示 sqlcmd 提示符。

需要帮助?如需获得代理问题排查方面的帮助,请参阅 Cloud SQL Auth 代理连接问题排查,或参阅我们的 Cloud SQL 支持页面。

连接到应用

您可以使用支持连接到 TCP 套接字的任何语言连接到 Cloud SQL Auth 代理。以下是 GitHub 上完整示例的一些代码段,可帮助您了解它们在您的应用中如何协同工作。

使用 TCP 进行连接

Cloud SQL Auth 代理调用语句:

./cloud-sql-proxy INSTANCE_CONNECTION_NAME &

Python

如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的 README

import os

import sqlalchemy


def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
    """Initializes a TCP connection pool for a Cloud SQL instance of SQL Server."""
    # 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.
    db_host = os.environ[
        "INSTANCE_HOST"
    ]  # e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
    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'
    db_port = os.environ["DB_PORT"]  # e.g. 1433

    pool = sqlalchemy.create_engine(
        # Equivalent URL:
        # mssql+pytds://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
        sqlalchemy.engine.url.URL.create(
            drivername="mssql+pytds",
            username=db_user,
            password=db_pass,
            database=db_name,
            host=db_host,
            port=db_port,
        ),
        # ...
    )

    return pool

Java

如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的 README

注意:

  • CLOUD_SQL_CONNECTION_NAME 应表示为 <MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>
  • 使用参数 ipTypes=PRIVATE 将强制 SocketFactory 与实例的关联专用 IP 连接
  • 如需查看 pom.xml 文件的 JDBC 套接字工厂版本的要求,请点击此处


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

public class TcpConnectionPoolFactory 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 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");

  private static final String INSTANCE_HOST = System.getenv("INSTANCE_HOST");
  private static final String DB_PORT = System.getenv("DB_PORT");


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

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


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

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

Node.js

如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的 README

const mssql = require('mssql');

// createTcpPool initializes a TCP connection pool for a Cloud SQL
// instance of SQL Server.
const createTcpPool = 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 dbConfig = {
    server: process.env.INSTANCE_HOST, // e.g. '127.0.0.1'
    port: parseInt(process.env.DB_PORT), // e.g. 1433
    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'
    options: {
      trustServerCertificate: true,
    },
    // ... Specify additional properties here.
    ...config,
  };
  // Establish a connection to the database.
  return mssql.connect(dbConfig);
};

Go

如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的 README

package cloudsql

import (
	"database/sql"
	"fmt"
	"log"
	"os"
	"strings"

	_ "github.com/denisenkom/go-mssqldb"
)

// connectTCPSocket initializes a TCP connection pool for a Cloud SQL
// instance of SQL Server.
func connectTCPSocket() (*sql.DB, error) {
	mustGetenv := func(k string) string {
		v := os.Getenv(k)
		if v == "" {
			log.Fatalf("Fatal Error in connect_tcp.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 secrets safe.
	var (
		dbUser    = mustGetenv("DB_USER")       // e.g. 'my-db-user'
		dbPwd     = mustGetenv("DB_PASS")       // e.g. 'my-db-password'
		dbTCPHost = mustGetenv("INSTANCE_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
		dbPort    = mustGetenv("DB_PORT")       // e.g. '1433'
		dbName    = mustGetenv("DB_NAME")       // e.g. 'my-database'
	)

	dbURI := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%s;database=%s;",
		dbTCPHost, dbUser, dbPwd, dbPort, dbName)


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

	// ...

	return dbPool, nil
}

C#

如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的 README

using Microsoft.Data.SqlClient;
using System;

namespace CloudSql
{
    public class SqlServerTcp
    {
        public static SqlConnectionStringBuilder NewSqlServerTCPConnectionString()
        {
            // Equivalent connection string:
            // "User Id=<DB_USER>;Password=<DB_PASS>;Server=<INSTANCE_HOST>;Database=<DB_NAME>;"
            var connectionString = new SqlConnectionStringBuilder()
            {
                // 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.
                DataSource = Environment.GetEnvironmentVariable("INSTANCE_HOST"), // e.g. '127.0.0.1'
                // Set Host to 'cloudsql' when deploying to App Engine Flexible environment
                UserID = Environment.GetEnvironmentVariable("DB_USER"),         // e.g. 'my-db-user'
                Password = Environment.GetEnvironmentVariable("DB_PASS"),       // e.g. 'my-db-password'
                InitialCatalog = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'

                // The Cloud SQL proxy provides encryption between the proxy and instance
                Encrypt = false,
            };
            connectionString.Pooling = true;
            // Specify additional properties here.
            return connectionString;
        }
    }
}

Ruby

如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的 README

tcp: &tcp
  adapter: sqlserver
  # Configure additional properties here.
  # 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.
  username: <%= ENV["DB_USER"] %>  # e.g. "my-database-user"
  password: <%= ENV["DB_PASS"] %> # e.g. "my-database-password"
  database: <%= ENV.fetch("DB_NAME") { "vote_development" } %>
  host: <%= ENV.fetch("INSTANCE_HOST") { "127.0.0.1" }%> # '172.17.0.1' if deployed to GAE Flex
  port: <%= ENV.fetch("DB_PORT") { 1433 }%> 

PHP

如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的 README

namespace Google\Cloud\Samples\CloudSQL\SQLServer;

use PDO;
use PDOException;
use RuntimeException;
use TypeError;

class DatabaseTcp
{
    public static function initTcpDatabaseConnection(): PDO
    {
        try {
            // 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.
            $username = getenv('DB_USER'); // e.g. 'your_db_user'
            $password = getenv('DB_PASS'); // e.g. 'your_db_password'
            $dbName = getenv('DB_NAME'); // e.g. 'your_db_name'
            $instanceHost = getenv('INSTANCE_HOST'); // e.g. '127.0.0.1' ('172.17.0.1' for GAE Flex)

            // Connect using TCP
            $dsn = sprintf(
                'sqlsrv:server=%s;Database=%s',
                $instanceHost,
                $dbName
            );

            // Connect to the database
            $conn = new PDO(
                $dsn,
                $username,
                $password,
                # ...
            );
        } catch (TypeError $e) {
            throw new RuntimeException(
                sprintf(
                    'Invalid or missing configuration! Make sure you have set ' .
                        '$username, $password, $dbName, and $instanceHost (for TCP mode). ' .
                        'The PHP error was %s',
                    $e->getMessage()
                ),
                $e->getCode(),
                $e
            );
        } catch (PDOException $e) {
            throw new RuntimeException(
                sprintf(
                    'Could not connect to the Cloud SQL Database. Check that ' .
                        'your username and password are correct, that the Cloud SQL ' .
                        'proxy is running, and that the database exists and is ready ' .
                        'for use. For more assistance, refer to %s. The PDO error was %s',
                    'https://cloud.google.com/sql/docs/sqlserver/connect-external-app',
                    $e->getMessage()
                ),
                (int) $e->getCode(),
                $e
            );
        }

        return $conn;
    }
}

其他主题

Cloud SQL Auth 代理命令行参数

上面的示例涵盖了最常见的用例,但 Cloud SQL Auth 代理还具有其他可通过命令行参数设置的配置选项。如需有关命令行参数的帮助,请使用 --help 标志查看最新文档:

./cloud-sql-proxy --help

如需查看有关如何使用 Cloud SQL Auth 代理命令行选项的更多示例,请参阅 Cloud SQL Auth 代理 GitHub 代码库中的 README

用于对 Cloud SQL Auth 代理进行身份验证的选项

所有这些选项都使用 INSTANCE_CONNECTION_NAME 作为连接字符串来标示 Cloud SQL 实例。您可以在 Google Cloud 控制台中的实例概览页面上或者通过运行以下命令找到 INSTANCE_CONNECTION_NAME

gcloud sql instances describe --project PROJECT_ID INSTANCE_CONNECTION_NAME

例如:gcloud sql instances describe --project myproject myinstance

其中一些选项使用包含账号的 RSA 私钥的 JSON 凭据文件。如需了解如何为服务账号创建 JSON 凭据文件,请参阅创建服务账号

Cloud SQL Auth 代理提供了多种身份验证备选选项,具体取决于您的环境。Cloud SQL Auth 代理会按照以下顺序检查以下各项,并使用找到的第一项尝试进行身份验证:

  1. 由 credentials-file 标志提供的凭据。

    使用服务账号创建和下载关联的 JSON 文件,并在启动 Cloud SQL Auth 代理时将 --credentials-file 标志设置为该文件的路径。服务账号必须具有 Cloud SQL 实例所需的权限

    要在命令行中使用此选项,请调用 cloud-sql-proxy 命令,并将 --credentials-file 标志设置为 JSON 凭据文件的路径和文件名。该路径可以是绝对路径,也可以是相对于当前工作目录的路径。 例如:

    ./cloud-sql-proxy --credentials-file PATH_TO_KEY_FILE \
    INSTANCE_CONNECTION_NAME
      

    如需详细了解如何将 IAM 角色添加到服务账号,请参阅向服务账号授予角色

    如需详细了解 Cloud SQL 支持的角色,请参阅适用于 Cloud SQL 的 IAM 角色

  2. 由访问令牌提供的凭据。

    创建访问令牌,然后调用 cloud-sql-proxy 命令,并将 --token 标志设置为 OAuth 2.0 访问令牌。例如:
    ./cloud-sql-proxy --token ACCESS_TOKEN \
    INSTANCE_CONNECTION_NAME
      
  3. 由环境变量提供的凭据。

    此选项与使用 --credentials-file 标志类似,只是指定您在 GOOGLE_APPLICATION_CREDENTIALS 环境变量中设置的 JSON 凭据文件,而不是使用 --credentials-file 命令行参数。
  4. 来自经过身份验证的 gcloud CLI 客户端的凭据。

    如果您已安装 gcloud CLI 并已使用您的个人账号进行身份验证,则 Cloud SQL Auth 代理可以使用相同的账号凭据。该方法特别适用于启动和运行开发环境。

    如需让 Cloud SQL Auth 代理能够使用您的 gcloud CLI 凭据,请使用以下命令对 gcloud CLI 进行身份验证:

    gcloud auth application-default login
  5. 与 Compute Engine 实例关联的凭据。

    如果您要从 Compute Engine 实例连接到 Cloud SQL,则 Cloud SQL Auth 代理可使用与该 Compute Engine 实例关联的服务账号。如果该服务账号具有 Cloud SQL 实例的必需权限,则 Cloud SQL Auth 代理会成功通过身份验证。

    如果 Compute Engine 实例与 Cloud SQL 实例位于同一项目中,则 Compute Engine 实例的默认服务账号具有可验证 Cloud SQL Auth 代理身份的必要权限。如果这两个实例属于不同的项目,则您必须将 Compute Engine 实例的服务账号添加到 Cloud SQL 实例所属的项目中。

  6. 环境的默认服务账号

    如果 Cloud SQL Auth 代理在先前介绍的任何位置都找不到凭据,则其将遵循为服务器到服务器生产应用设置身份验证中记录的逻辑。某些环境(例如 Compute Engine、App Engine 等)会提供一个默认服务账号,您的应用默认情况下可以使用该账号进行身份验证。如果您使用默认服务账号,则该账号必须具有角色和权限中所述的权限。如需详细了解 Google Cloud 的身份验证方法,请参阅身份验证概览

创建服务账号

  1. 在 Google Cloud 控制台中,转到服务账号页面。

    转到“服务账号”

  2. 选择包含您的 Cloud SQL 实例的项目。
  3. 点击创建服务账号
  4. 服务账号名称字段中输入服务账号的描述性名称。
  5. 服务账号 ID 更改为一个不重复且易于识别的值,然后点击创建并继续
  6. 点击选择角色字段,然后选择以下角色之一:
    • Cloud SQL > Cloud SQL Client
    • Cloud SQL > Cloud SQL Editor
    • Cloud SQL > Cloud SQL Admin
  7. 点击完成以完成服务账号的创建过程。
  8. 点击新服务账号的操作菜单,然后选择管理密钥
  9. 点击添加键下拉菜单,然后点击创建新密钥
  10. 确认密钥类型是 JSON,然后点击创建

    私钥文件将下载到您的机器上。您可以将此文件移至其他位置,但要确保密钥文件的安全。

将 Cloud SQL Auth 代理与专用 IP 结合使用

如需使用专用 IP 连接到 Cloud SQL 实例,Cloud SQL Auth 代理必须位于可以访问实例所在 VPC 网络的资源中。

Cloud SQL Auth 代理使用 IP 与您的 Cloud SQL 实例建立连接。默认情况下,Cloud SQL Auth 代理尝试使用公共 IPv4 地址进行连接。

如果您的 Cloud SQL 实例只具有专用 IP,或者实例同时配置了公共和专用 IP,并且您希望 Cloud SQL Auth 代理使用专用 IP 地址,则必须在启动 Cloud SQL Auth 代理时提供以下选项:

--private-ip

将 Cloud SQL Auth 代理与启用了 Private Service Connect 的实例搭配使用

您可以使用 Cloud SQL Auth 代理来连接到启用了 Private Service Connect 的 Cloud SQL 实例。

Cloud SQL Auth 代理是一种连接器,可让您安全访问此实例,而无需授权网络或配置 SSL。

为了允许 Cloud SQL Auth 代理客户端连接,您必须设置与为实例提供的建议 DNS 名称匹配的 DNS 记录。DNS 记录是 DNS 资源和域名之间的映射。

如需详细了解如何使用 Cloud SQL Auth 代理连接到启用了 Private Service Connect 的实例,请参阅使用 Cloud SQL Auth 代理连接

在单独的进程中运行 Cloud SQL Auth 代理

在单独的 Cloud Shell 终端进程中运行 Cloud SQL Auth 代理可能会很有用,可避免将其控制台输出与其他程序的输出混淆。使用下面所示的语法可以在单独的进程中调用 Cloud SQL Auth 代理。

Linux

在 Linux 或 macOS 上,在命令行上使用尾随 & 可以在单独的进程中启动 Cloud SQL Auth 代理:

./cloud-sql-proxy INSTANCE_CONNECTION_NAME
  --credentials-file PATH_TO_KEY_FILE &

Windows

在 Windows PowerShell 中,使用 Start-Process 命令可以在单独的进程中启动 Cloud SQL Auth 代理:

Start-Process --filepath "cloud-sql-proxy.exe"
  --ArgumentList "
  --credentials-file PATH_TO_KEY_FILEINSTANCE_CONNECTION_NAME"

在 Docker 容器中运行 Cloud SQL Auth 代理

如需在 Docker 容器中运行 Cloud SQL Auth 代理,请使用 Google Container Registry 提供的 Cloud SQL Auth 代理 Docker 映像。您可以使用此 gcloud 命令安装 Cloud SQL Auth 代理 Docker 映像:

docker pull gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.13.0

您可以使用以下所示命令通过 TCP 套接字或 Unix 套接字启动 Cloud SQL Auth 代理。

TCP 套接字

    docker run -d \
      -v PATH_TO_KEY_FILE:/path/to/service-account-key.json \
      -p 127.0.0.1:1433:1433 \
      gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.13.0 \
      --address 0.0.0.0 \
      --credentials-file /path/to/service-account-key.json \
      INSTANCE_CONNECTION_NAME

Unix 套接字

    docker run -d \
      -v /PATH_TO_HOST_TARGET:/PATH_TO_GUEST_TARGET \
      -v PATH_TO_KEY_FILE:/path/to/service-account-key.json \
      gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.13.0 --unix-socket /cloudsql \
      --credentials-file /path/to/service-account-key.json/PATH_TO_KEY_FILE \
      INSTANCE_CONNECTION_NAME

如果您使用的是容器优化型映像,请使用可写目录代替 /cloudsql,例如:

v /mnt/stateful_partition/cloudsql:/cloudsql

如果您使用的是 Compute Engine 实例提供的凭据,请勿包含 credential_file 参数和 -v PATH_TO_KEY_FILE:/path/to/service-account-key.json 行。

将 Cloud SQL Auth 代理作为服务运行

将 Cloud SQL Auth 代理作为后台服务运行是本地开发和生产工作负载的一个选项。在开发中,当您需要访问 Cloud SQL 实例时,可以在后台启动该服务,并在完成后停止该服务。

对于生产工作负载,Cloud SQL Auth 代理目前不提供作为 Windows 服务运行的内置支持,但可以使用第三方服务管理器将 Cloud SQL Auth 代理作为服务运行。例如,您可以使用 NSSM 将 Cloud SQL Auth 代理配置为 Windows 服务,NSSM 会监控 Cloud SQL Auth 代理,并在其停止响应时自动重启。如需了解详情,请参阅 NSSM 文档

需要 SSL 时连接

强制要求使用 Cloud SQL Auth 代理

使用 ConnectorEnforcement 在 Cloud SQL 中启用 Cloud SQL Auth 代理。

gcloud

以下命令强制要求使用 Cloud SQL 连接器。

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

如需停用强制执行,请使用以下代码行: --connector-enforcement NOT_REQUIRED 更新不会触发重启。

REST v1

以下命令强制要求使用 Cloud SQL 连接器。

在使用任何请求数据之前,请先进行以下替换:

  • project-id:项目 ID。
  • instance-id:实例 ID。

HTTP 方法和网址:

PATCH https://sqladmin.googleapis.com/v1/projects/project-id/instances/instance-id

请求 JSON 正文:

{
  "settings": {                     
    "connectorEnforcement": "REQUIRED"    
  }                                             
}   

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

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

如需停用强制使用,请改用 "connectorEnforcement": "NOT_REQUIRED"。更新不会触发重启。

REST v1beta4

以下命令强制要求使用 Cloud SQL 连接器。

在使用任何请求数据之前,请先进行以下替换:

  • project-id:项目 ID。
  • instance-id:实例 ID。

HTTP 方法和网址:

PATCH https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id

请求 JSON 正文:

{
  "settings": {
    "connectorEnforcement": "REQUIRED"
  }
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

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

如需停用强制使用,请改用 "connectorEnforcement": "NOT_REQUIRED"。更新不会触发重启。

Cloud SQL Auth 代理的使用提示

使用 Cloud SQL Auth 代理连接到多个实例

您可以使用一个本地 Cloud SQL Auth 代理客户端连接到多个 Cloud SQL 实例。具体操作方式取决于您要使用 Unix 套接字还是 TCP。

TCP 套接字

使用 TCP 建立连接时,请在您的计算机上指定端口,以供 Cloud SQL 身份验证代理监听每个 Cloud SQL 实例。连接到多个 Cloud SQL 实例时,指定的每个端口都必须唯一并且可用于您的机器。

例如:

    # Start the Cloud SQL Auth Proxy to connect to two different Cloud SQL instances.
    # Give the Cloud SQL Auth Proxy a unique port on your machine to use for each Cloud SQL instance.

    ./cloud-sql-proxy "myProject:us-central1:myInstance?port=1433" \
    "myProject:us-central1:myInstance2?port=1234"

    # Connect to "myInstance" using port 1433 on your machine:
    sqlcmd -U myUser -S "127.0.0.1,1433"

    # Connect to "myInstance2" using port 1234 on your machine:
    sqlcmd -U myUser -S "127.0.0.1,1234"
  

Cloud SQL 身份验证代理连接问题排查

Cloud SQL Auth 代理 Docker 映像基于特定版本的 Cloud SQL Auth 代理。当 Cloud SQL Auth 代理推出新版本时,请拉取 Cloud SQL Auth 代理 Docker 映像的新版本,以使您的环境保持最新状态。您可以通过查看 Cloud SQL Auth 代理 GitHub 版本页面,了解 Cloud SQL Auth 代理的当前版本。

如果在使用 Cloud SQL Auth 代理连接到 Cloud SQL 实例时遇到问题,可尝试通过以下几种方法来找出问题原因:

  • 验证您是否使用 IP 地址(而不是写入端点)连接到实例。
  • 检查 Cloud SQL Auth 代理输出。

    通常,Cloud SQL Auth 代理输出可帮助您确定问题根源和解决方法。将输出传送到文件中,或查看在其中启动 Cloud SQL Auth 代理的 Cloud Shell 终端。

  • 如果您收到 403 notAuthorized 错误,并且您使用服务账号来验证 Cloud SQL Auth 代理,请确保服务账号具有正确的权限

    您可在 IAM 页面上搜索服务账号的 ID 进行检查。该账号必须具有 cloudsql.instances.connect 权限。Cloud SQL AdminClientEditor 预定义角色具有此权限。

  • 如果您要从 App Engine 进行连接并且收到 403 notAuthorized 错误,请检查 app.yamlcloud_sql_instances 是否有拼写错误或不正确的实例连接名称。实例连接名称始终采用 PROJECT:REGION:INSTANCE 格式。

    此外,请检查 App Engine 服务账号(例如 $PROJECT_ID@appspot.gserviceaccount.com)是否具有 Cloud SQL Client IAM 角色。

    如果 App Engine 服务位于一个项目(项目 A)中,而数据库位于另一个项目(项目 B)中,则此错误表示 App Engine 服务账号尚未获得 Cloud SQL Client IAM 角色(位于项目 B 中)。

  • 请务必启用 Cloud SQL Admin API。

    如果未启用,则 Cloud SQL Auth 代理日志中会显示 Error 403: Access Not Configured 之类的输出。

  • 如果要在实例列表中包含多个实例,请确保使用英文逗号作为分隔符且不使用空格。如果要使用 TCP,请确保为每个实例指定不同的端口。

  • 如果要使用 UNIX 套接字进行连接,请确认已通过列出启动 Cloud SQL Auth 代理时提供的目录创建了套接字。

  • 如果设置了出站防火墙政策,请确保它允许连接到目标 Cloud SQL 实例上的端口 3307。

  • 您可以通过在 Google Cloud 控制台的操作 > Logging > Logs Explorer 部分下查看日志来确认 Cloud SQL Auth 代理已正确启动。操作成功如下所示:

    2021/06/14 15:47:56 Listening on /cloudsql/$PROJECT_ID:$REGION:$INSTANCE_NAME/1433 for $PROJECT_ID:$REGION:$INSTANCE_NAME
    2021/06/14 15:47:56 Ready for new connections
    
  • 配额问题:当 Cloud SQL Admin API 配额用完时,Cloud SQL 身份验证代理将启动并显示以下错误消息:

    There was a problem when parsing a instance configuration but ignoring due
    to the configuration. Error: googleapi: Error 429: Quota exceeded for quota
    metric 'Queries' and limit 'Queries per minute per user' of service
    'sqladmin.googleapis.com' for consumer 'project_number:$PROJECT_ID.,
    rateLimitExceeded
    

    应用连接到代理后,代理会报告以下错误:

    failed to refresh the ephemeral certificate for $INSTANCE_CONNECTION_NAME:
    googleapi: Error 429: Quota exceeded for quota metric 'Queries' and limit
    'Queries per minute per user' of service 'sqladmin.googleapis.com' for
    consumer 'project_number:$PROJECT_ID., rateLimitExceeded
    

    解决方案:确定配额问题的来源,例如,应用滥用连接器,并且不必要地创建新连接,或与支持团队联系以请求增加 Cloud SQL Admin API 配额。如果配额错误在启动时显示,您必须重新部署应用以重启代理。如果配额错误在启动后出现,则无需重新部署。

后续步骤