Conectar a partir do Cloud Run

Nesta página, você verá informações e exemplos de conexão a uma instância do Cloud SQL por meio de um serviço em execução no Cloud Run.

Para instruções detalhadas sobre como executar um aplicativo da Web de amostra do Cloud Run conectado ao Cloud SQL, consulte o guia de início rápido para se conectar no Cloud Run

O Cloud SQL é um serviço de banco de dados totalmente gerenciado que ajuda a configurar, manter, gerenciar e administrar seus bancos de dados relacionais na nuvem.

O Cloud Run é uma plataforma de computação gerenciada que permite executar contêineres diretamente na infraestrutura do Google Cloud.

Configurar uma instância do Cloud SQL

  1. Ative a API Cloud SQL Admin no projeto do Google Cloud do qual você está se conectando, caso ainda não tenha feito isso:

    Ative a API

  2. Criar uma instância do Cloud SQL for SQL Server.

    Por padrão, o Cloud SQL atribui um endereço IP público a uma nova instância. Você também tem a opção de atribuir um endereço IP privado. Para mais informações sobre as opções de conectividade de ambos, consulte a página Visão geral da conexão.

Configurar o Cloud Run

As etapas para configurar o Cloud Functions dependem do tipo de endereço IP atribuído à instância do Cloud SQL. Se você encaminhar todo o tráfego de saída por meio da saída VPC direta ou de um conector de acesso VPC sem servidor, use um endereço IP particular. Compare os dois métodos de saída de rede.

IP público (padrão)

O Cloud Run é compatível com a conexão ao Cloud SQL para SQL Server por IP público usando os conectores Go, Java e Python.

  • Verifique se a instância criada anteriormente tem um endereço IP público. Você pode verificar isso na página Visão geral da sua instância no Console do Google Cloud. Se precisar adicionar um, consulte a página Como configurar o IP público para ver instruções.
  • Receba o INSTANCE_CONNECTION_NAME da instância. Isso pode ser encontrado na página Visão geral da instância no Console do Google Cloud ou executando o seguinte comando: gcloud sql instances describe INSTANCE_NAME.
  • Configure a conta de serviço do seu serviço. Verifique se a conta de serviço tem os papéis e as permissões do Cloud SQL apropriados para se conectar ao Cloud SQL.
      A conta de serviço do seu serviço precisa de um dos seguintes papéis do IAM:
      • Cloud SQL Client (recomendável)
      • Cloud SQL Admin
      Também é possível atribuir manualmente as seguintes permissões do IAM:
      • cloudsql.instances.connect
      • cloudsql.instances.get

Como qualquer alteração de configuração, definir uma nova configuração para a conexão do Cloud SQL leva à criação de uma nova revisão do Cloud Run. As revisões seguintes também receberão automaticamente essa conexão do Cloud SQL, a menos que você faça atualizações explícitas para alterá-la.

Console

  1. Acesse o Cloud Run

  2. Comece a configurar o serviço:

    • Se você estiver adicionando uma conexão do Cloud SQL a um novo serviço, faça o seguinte:

      O serviço precisa estar em contêiner e ser enviado ao Container Registry ou ao Artifact Registry. Se você ainda não tem, consulte estas instruções sobre como criar e implantar uma imagem de contêiner.

    • Se você estiver adicionando conexões do Cloud SQL a um serviço atual, faça o seguinte:
      1. Clique no nome do serviço.
      2. Clique na guia Editar e implantar nova revisão.
  3. Ative a conexão com uma instância do Cloud SQL:
    1. Clique em Contêiner, variáveis e secrets, conexões e segurança .
    2. Clique na guia Contêiner.
    3. Role para baixo até Conexões do Cloud SQL.
    4. Clique em Adicionar conexão
    5. Clique no botão Ativar o Cloud SQL Admin se você ainda não tiver ativado a API Cloud SQL Admin.

    Adicionar conexão com o Cloud SQL

    • Para adicionar uma conexão a uma instância do Cloud SQL no projeto, selecione a instância pretendida no menu suspenso.
    • Para usar uma instância do Cloud SQL de outro projeto, selecione string de conexão personalizada na lista suspensa e insira o nome completo da conexão da instância no formato PROJECT-ID:REGION:INSTANCE-ID.
    • Para excluir uma conexão, passe o cursor à direita da conexão para exibir o ícone de Lixeira e clique nele.
  4. Clique em Criar ou Implantar.

Linha de comando

Antes de usar qualquer um dos comandos abaixo, faça as seguintes substituições:

  • IMAGE pela imagem que você está implantando;
  • SERVICE_NAME pelo nome do serviço do Cloud Run;
  • INSTANCE_CONNECTION_NAME pelo nome da conexão da instância do Cloud SQL ou uma lista de nomes de conexões separados por vírgulas.

    Para implantar um novo contêiner, use o comando a seguir:

    gcloud run deploy \
      --image=IMAGE \
      --add-cloudsql-instances=INSTANCE_CONNECTION_NAME
    Para atualizar um serviço atual, use o seguinte comando:
    gcloud run services update SERVICE_NAME \
      --add-cloudsql-instances=INSTANCE_CONNECTION_NAME

Terraform

O código a seguir cria um contêiner base do Cloud Run, com uma instância conectada do Cloud SQL.

resource "google_cloud_run_v2_service" "default" {
  name     = "cloudrun-service"
  location = "us-central1"

  template {
    containers {
      image = "us-docker.pkg.dev/cloudrun/container/hello:latest" # Image to deploy

      volume_mounts {
        name       = "cloudsql"
        mount_path = "/cloudsql"
      }
    }
    volumes {
      name = "cloudsql"
      cloud_sql_instance {
        instances = [google_sql_database_instance.default.connection_name]
      }
    }
  }
  client     = "terraform"
  depends_on = [google_project_service.secretmanager_api, google_project_service.cloudrun_api, google_project_service.sqladmin_api]
}

  1. Para aplicar as mudanças, insira terraform apply.
  2. Para verificar as alterações, consulte o serviço do Cloud Run, clicando na guia Revisões e na guia Conexões.

IP particular

Se a conta de serviço de autorização pertencer a um projeto diferente daquele que contém a instância do Cloud SQL, faça o seguinte:

  • Nos dois projetos, ative a API Cloud SQL Admin.
  • Na conta de serviço no projeto que contém a instância do Cloud SQL, adicione as permissões do IAM.
A saída de VPC direta e os conectores usam endereços IP particulares para processar a comunicação com sua rede VPC. Para se conectar diretamente a endereços IP particulares usando um desses métodos de saída, faça o seguinte:
  1. Verifique se a instância do Cloud SQL criada anteriormente tem um endereço IP particular. Para adicionar um endereço IP interno, acesse Configurar IP particular.
  2. Configure o método de saída para se conectar à mesma rede VPC que a instância do Cloud SQL. Observe as seguintes condições:
    • A saída VPC direta e o acesso VPC sem servidor aceitam a comunicação com redes VPC conectadas usando o Cloud VPN e o peering de rede VPC.
    • A saída VPC direta e o acesso VPC sem servidor não são compatíveis com redes legadas.
    • A menos que você esteja usando a VPC compartilhada, é necessário que um conector compartilhe o mesmo projeto e a mesma região do recurso que o utiliza, mas o conector pode enviar tráfego para recursos em regiões diferentes.
  3. Conecte-se usando o endereço de IP privado e a porta 1433 da instância.

Conecte-se ao Cloud SQL

Depois de configurar o Cloud Run conecte-se à instância do Cloud SQL.

IP público (padrão)

Para caminhos de IP público, o Cloud Run fornece criptografia e se conecta usando os conectores do Cloud SQL.

Conectar-se com conectores do Cloud SQL

Os conectores do Cloud SQL são bibliotecas específicas de linguagens que fornecem autorização com base em IAM e criptografia ao se conectar a uma instância do Cloud SQL.

Python

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub (em inglês).

import os

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

import sqlalchemy

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

    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.get("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

    connector = Connector(ip_type)

    connect_args = {}
    # If your SQL Server instance requires SSL, you need to download the CA
    # certificate for your instance and include cafile={path to downloaded
    # certificate} and validate_host=False. This is a workaround for a known issue.
    if os.environ.get("DB_ROOT_CERT"):  # e.g. '/path/to/my/server-ca.pem'
        connect_args = {
            "cafile": os.environ["DB_ROOT_CERT"],
            "validate_host": False,
        }

    def getconn() -> pytds.Connection:
        conn = connector.connect(
            instance_connection_name,
            "pytds",
            user=db_user,
            password=db_pass,
            db=db_name,
            **connect_args
        )
        return conn

    pool = sqlalchemy.create_engine(
        "mssql+pytds://",
        creator=getconn,
        # ...
    )
    return pool

Java

Para conferir esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

Observação:

  • CLOUD_SQL_CONNECTION_NAME precisa ser representado como <MEU-PROJETO>:<REGIÃO-DA-INSTÂNCIA>:<NOME-DA-INSTÂNCIA>
  • Consulte os requisitos de versão de fábrica do soquete JDBC para o arquivo pom.xml aqui.


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 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 is equivalent to setting the config options below:
    // jdbc:sqlserver://;user=<DB_USER>;password=<DB_PASS>;databaseName=<DB_NAME>;
    // socketFactoryClass=com.google.cloud.sql.sqlserver.SocketFactory;
    // socketFactoryConstructorArg=<INSTANCE_CONNECTION_NAME>

    // 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
        .setDataSourceClassName("com.microsoft.sqlserver.jdbc.SQLServerDataSource");
    config.setUsername(DB_USER); // e.g. "root", "sqlserver"
    config.setPassword(DB_PASS); // e.g. "my-password"
    config.addDataSourceProperty("databaseName", DB_NAME);

    config.addDataSourceProperty("socketFactoryClass",
        "com.google.cloud.sql.sqlserver.SocketFactory");
    config.addDataSourceProperty("socketFactoryConstructorArg", INSTANCE_CONNECTION_NAME);

    // The Java Connector provides SSL encryption, so it should be disabled
    // at the driver level.
    config.addDataSourceProperty("encrypt", "false");

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

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

Go

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub (em inglês).

package cloudsql

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

	"cloud.google.com/go/cloudsqlconn"
	mssql "github.com/denisenkom/go-mssqldb"
)

type csqlDialer struct {
	dialer     *cloudsqlconn.Dialer
	connName   string
	usePrivate bool
}

// DialContext adheres to the mssql.Dialer interface.
func (c *csqlDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
	var opts []cloudsqlconn.DialOption
	if c.usePrivate {
		opts = append(opts, cloudsqlconn.WithPrivateIP())
	}
	return c.dialer.Dial(ctx, c.connName, opts...)
}

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 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")
	)

	dbURI := fmt.Sprintf("user id=%s;password=%s;database=%s;", dbUser, dbPwd, dbName)
	c, err := mssql.NewConnector(dbURI)
	if err != nil {
		return nil, fmt.Errorf("mssql.NewConnector: %w", err)
	}
	dialer, err := cloudsqlconn.NewDialer(context.Background())
	if err != nil {
		return nil, fmt.Errorf("cloudsqlconn.NewDailer: %w", err)
	}
	c.Dialer = &csqlDialer{
		dialer:     dialer,
		connName:   instanceConnectionName,
		usePrivate: usePrivate != "",
	}

	dbPool := sql.OpenDB(c)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

Usar o Secret Manager

O Google recomenda que você use o Secret Manager para armazenar informações sensíveis, como credenciais do SQL. É possível transmitir secrets como variáveis de ambiente ou montá-los como um volume com o Cloud Run.

Depois de criar um secret no Secret Manager, atualize um serviço existente com o seguinte comando:

Linha de comando

gcloud run services update SERVICE_NAME \
  --add-cloudsql-instances=INSTANCE_CONNECTION_NAME
  --update-env-vars=INSTANCE_CONNECTION_NAME=INSTANCE_CONNECTION_NAME_SECRET \
  --update-secrets=DB_USER=DB_USER_SECRET:latest \
  --update-secrets=DB_PASS=DB_PASS_SECRET:latest \
  --update-secrets=DB_NAME=DB_NAME_SECRET:latest

Terraform

A instrução a seguir cria recursos secretos para armazenar com segurança os valores de usuário, senha e nome do banco de dados usando google_secret_manager_secret e google_secret_manager_secret_version. Observe que você precisa atualizar a conta do serviço de computação do projeto para ter acesso a cada secret.


# Create dbuser secret
resource "google_secret_manager_secret" "dbuser" {
  secret_id = "dbusersecret"
  replication {
    auto {}
  }
  depends_on = [google_project_service.secretmanager_api]
}

# Attaches secret data for dbuser secret
resource "google_secret_manager_secret_version" "dbuser_data" {
  secret      = google_secret_manager_secret.dbuser.id
  secret_data = "secret-data" # Stores secret as a plain txt in state
}

# Update service account for dbuser secret
resource "google_secret_manager_secret_iam_member" "secretaccess_compute_dbuser" {
  secret_id = google_secret_manager_secret.dbuser.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com" # Project's compute service account
}


# Create dbpass secret
resource "google_secret_manager_secret" "dbpass" {
  secret_id = "dbpasssecret"
  replication {
    auto {}
  }
  depends_on = [google_project_service.secretmanager_api]
}

# Attaches secret data for dbpass secret
resource "google_secret_manager_secret_version" "dbpass_data" {
  secret      = google_secret_manager_secret.dbpass.id
  secret_data = "secret-data" # Stores secret as a plain txt in state
}

# Update service account for dbpass secret
resource "google_secret_manager_secret_iam_member" "secretaccess_compute_dbpass" {
  secret_id = google_secret_manager_secret.dbpass.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com" # Project's compute service account
}


# Create dbname secret
resource "google_secret_manager_secret" "dbname" {
  secret_id = "dbnamesecret"
  replication {
    auto {}
  }
  depends_on = [google_project_service.secretmanager_api]
}

# Attaches secret data for dbname secret
resource "google_secret_manager_secret_version" "dbname_data" {
  secret      = google_secret_manager_secret.dbname.id
  secret_data = "secret-data" # Stores secret as a plain txt in state
}

# Update service account for dbname secret
resource "google_secret_manager_secret_iam_member" "secretaccess_compute_dbname" {
  secret_id = google_secret_manager_secret.dbname.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com" # Project's compute service account
}

Atualize o recurso principal do Cloud Run para incluir os novos secrets.

resource "google_cloud_run_v2_service" "default" {
  name     = "cloudrun-service"
  location = "us-central1"

  template {
    containers {
      image = "us-docker.pkg.dev/cloudrun/container/hello:latest" # Image to deploy

      # Sets a environment variable for instance connection name
      env {
        name  = "INSTANCE_CONNECTION_NAME"
        value = google_sql_database_instance.default.connection_name
      }
      # Sets a secret environment variable for database user secret
      env {
        name = "DB_USER"
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.dbuser.secret_id # secret name
            version = "latest"                                      # secret version number or 'latest'
          }
        }
      }
      # Sets a secret environment variable for database password secret
      env {
        name = "DB_PASS"
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.dbpass.secret_id # secret name
            version = "latest"                                      # secret version number or 'latest'
          }
        }
      }
      # Sets a secret environment variable for database name secret
      env {
        name = "DB_NAME"
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.dbname.secret_id # secret name
            version = "latest"                                      # secret version number or 'latest'
          }
        }
      }

      volume_mounts {
        name       = "cloudsql"
        mount_path = "/cloudsql"
      }
    }
    volumes {
      name = "cloudsql"
      cloud_sql_instance {
        instances = [google_sql_database_instance.default.connection_name]
      }
    }
  }
  client     = "terraform"
  depends_on = [google_project_service.secretmanager_api, google_project_service.cloudrun_api, google_project_service.sqladmin_api]
}

Para aplicar as mudanças, insira terraform apply.

O comando de exemplo usa a versão do secret, latest. No entanto, o Google recomenda fixar o secret em uma versão específica, SECRET_NAME:v1.

IP particular

Para caminhos IP particulares, o aplicativo se conecta diretamente à instância por uma rede VPC. Esse método usa TCP para a conexão direta com a instância do Cloud SQL sem usar o proxy de autenticação do Cloud SQL.

Conectar com TCP

Conecte-se usando o endereço IP privado da sua instância do Cloud SQL como o host e a porta 1433.

Python

Para conferir esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

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

Para conferir esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

Observação:

  • CLOUD_SQL_CONNECTION_NAME precisa ser representado como <MEU-PROJETO>:<REGIÃO-DA-INSTÂNCIA>:<NOME-DA-INSTÂNCIA>
  • O uso do argumento ipTypes=PRIVATE forçará o SocketFactory a se conectar ao IP privado associado de uma instância
  • Consulte os requisitos de versão de fábrica do soquete JDBC para o arquivo pom.xml aqui.


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

Para conferir esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

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

Para conferir esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

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
}

Ruby

Para conferir esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

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

Para conferir esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

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;
    }
}

Práticas recomendadas e outras informações

Use o proxy do Cloud SQL Auth ao testar seu aplicativo localmente. Consulte o guia de início rápido para o uso do proxy de autenticação do Cloud SQL e confira instruções detalhadas.

Se preferir, teste usando o Cloud SQL Proxy por meio de um contêiner do Docker.

Pools de conexões

As conexões aos bancos de dados podem ser descartadas pelo próprio servidor de banco de dados ou pela infraestrutura da plataforma. Recomendamos o uso de uma biblioteca de cliente compatível com pools de conexões que reconectam automaticamente conexões de cliente danificadas. Para exemplos mais detalhados sobre como usar pools de conexões, consulte a página Como gerenciar conexões de banco de dados.

Limites de conexão

As edições MySQL e PostgreSQL do Cloud SQL impõem um limite máximo de conexões simultâneas. Esses limites podem variar dependendo do mecanismo do banco de dados escolhido. Consulte a página Limites e cotas do Cloud SQL.

As instâncias de contêiner do Cloud Run são limitadas a 100 conexões com um banco de dados do Cloud SQL. Cada instância de um serviço ou job do Cloud Run pode ter 100 conexões com o banco de dados e, conforme esse serviço ou job é escalonado, o número total de conexões por implantação pode aumentar.

Limite o número máximo de conexões por instância usando um pool de conexões. Para exemplos mais detalhados sobre como limitar o número de conexões, consulte a página Como gerenciar conexões de banco de dados.

Limites de cota da API

O Cloud Run fornece um mecanismo que se conecta usando o proxy do Cloud SQL Auth, por meio da API Cloud SQL Admin. Os limites de cota da API se aplicam ao proxy do Cloud SQL Auth. A cota da API Cloud SQL Admin usada é aproximadamente duas vezes o número de instâncias do Cloud SQL configuradas pelo número de instâncias do Cloud Run de um serviço específico implantado a qualquer momento. É possível limitar ou aumentar o número de instâncias do Cloud Run para modificar a cota de API esperada consumida.

A seguir