Conéctate a Cloud SQL desde Cloud Run (completamente administrado)

En esta página, se muestran información y ejemplos para conectarse a una instancia de Cloud SQL desde un servicio que se ejecuta en Cloud Run (completamente administrado).

Cloud SQL es un servicio de base de datos completamente administrado que te ayuda a configurar, mantener, controlar y administrar tus bases de datos relacionales en la nube.

Configura una instancia de Cloud SQL

  1. Habilita la API de Administrador de Cloud SQL en el proyecto desde el que te conectas, si aún no lo has hecho:

    Habilita la API

  2. Crea una instancia de Cloud SQL para MySQL

    De forma predeterminada, Cloud SQL asigna una dirección IP pública a una instancia nueva. También puedes asignar una dirección IP privada. Para obtener más información sobre las opciones de conectividad de ambos, consulta la página Descripción general de las conexiones.

Configura Cloud Run (completamente administrado)

Los pasos para configurar Cloud Run (completamente administrado) dependen del tipo de dirección IP que asignaste a la instancia de Cloud SQL.

IP pública (predeterminada)

  • Asegúrate de que la instancia que creaste antes tenga una dirección IP pública. Puedes verificarlo en la página Descripción general de tu instancia en Google Cloud Console. Si necesitas agregar una, consulta la sección sobre cómo configurar la conectividad de IP pública para obtener instrucciones.
  • Obtén el INSTANCE_CONNECTION_NAME de tu instancia. Puedes encontrarlo en la página Descripción general de la instancia en Google Cloud Console o mediante la ejecución del siguiente comando: gcloud sql instances describe [INSTANCE_NAME].
  • Configura la cuenta de servicio de tu servicio. Asegúrate de que la cuenta de servicio tenga las funciones y los permisos de Cloud SQL adecuados para conectarse a Cloud SQL.
      La cuenta de servicio de tu servicio necesita una de las siguientes funciones de IAM:
      • Cloud SQL Client (recomendada)
      • Cloud SQL Editor
      • Cloud SQL Admin
      O bien, puedes asignar los siguientes permisos de IAM de forma manual:
      • cloudsql.instances.connect
      • cloudsql.instances.get

    Si la cuenta de servicio de autorización pertenece a un proyecto distinto al de la instancia de Cloud SQL, se deberán agregar los permisos de IAM y la API de Administrador de Cloud SQL para ambos proyectos.

Como sucede con cualquier cambio de configuración, establecer una configuración nueva para la conexión de Cloud SQL da lugar a la creación de una nueva revisión de Cloud Run. Las revisiones posteriores también adoptarán de forma automática esta conexión de Cloud SQL, a menos que realices actualizaciones explícitas para cambiarla.

Console

  1. Ir a Cloud Run

  2. Configura el servicio:

    • Si agregas una conexión de Cloud SQL a un servicio nuevo, haz lo siguiente:

      • El servicio debe estar organizado en contenedores y subido a Container Registry. Si aún no tienes una imagen de contenedor, consulta estas instrucciones para compilar e implementar una.

      • Haz clic en CREAR SERVICIO.

    • Si agregas conexiones de Cloud SQL a un servicio existente, haz lo siguiente:

      • Haz clic en el nombre del servicio.

      • Haz clic en IMPLEMENTAR NUEVA REVISIÓN.

  3. Habilita la conexión a un Cloud SQL:

    • Haz clic en MOSTRAR CONFIGURACIÓN OPCIONAL:

    Agregar conexión de Cloud SQL

    • Si agregas una conexión a una instancia de Cloud SQL en tu proyecto, selecciona la instancia de Cloud SQL deseada en el menú desplegable.
    • Si usas una instancia de Cloud SQL de otro proyecto, selecciona string de conexión personalizada en el menú desplegable y, luego, ingresa el nombre completo de la conexión de la instancia en el formato PROJECT-ID:REGION:INSTANCE-ID.

    • Si deseas borrar una conexión, coloca el cursor a la derecha de la conexión para que se muestre el ícono de la papelera y haz clic en él.

  4. Haz clic en Crear o Implementar.

Línea de comandos

Antes de usar cualquiera de los siguientes comandos, realiza los reemplazos que se muestran a continuación:

  • IMAGE por la imagen que implementas
  • SERVICE-NAME por el nombre del servicio de Cloud Run
  • INSTANCE-CONNECTION-NAME por el nombre de conexión de la instancia de Cloud SQL o por una lista delimitada por comas de nombres de conexión

    Si implementas un contenedor nuevo, usa el siguiente comando:

    gcloud run deploy --image IMAGE \
      --add-cloudsql-instances INSTANCE-CONNECTION-NAME \
      --update-env-vars INSTANCE_CONNECTION_NAME="INSTANCE-CONNECTION-NAME"
    Si actualizas un servicio existente, usa el siguiente comando:
    gcloud run services update SERVICE-NAME \
      --add-cloudsql-instances INSTANCE-CONNECTION-NAME \
      --update-env-vars INSTANCE_CONNECTION_NAME="INSTANCE-CONNECTION-NAME"

IP privada

El conector de acceso a VPC sin servidores controla la comunicación con la red de VPC. Para conectarte directamente con una IP privada, debes hacer lo siguiente:

  1. Asegúrate de que la instancia de Cloud SQL que creaste antes tenga una dirección IP privada. Si necesitas agregar una, consulta la página sobre cómo configurar IP privadas para obtener instrucciones.
  2. Crea un conector de Acceso a VPC sin servidores en la misma red de VPC en la que se encuentra tu instancia de Cloud SQL.
  3. A menos que uses la VPC compartida, un conector debe estar en el mismo proyecto y región que el recurso que lo usa, pero puede enviar tráfico a recursos en diferentes regiones.

    El acceso a VPC sin servidores admite la comunicación con las redes de VPC conectadas a través de Cloud VPN y el intercambio de tráfico entre redes de VPC.

    El Acceso a VPC sin servidores no es compatible con las redes heredadas.

  4. Configura Cloud Run (completamente administrado) para usar el conector.
  5. Conéctate mediante la IP privada y el puerto 3306 de tu instancia.

Conéctate a Cloud SQL

Después de configurar Cloud Run (completamente administrado), puedes conectarte a tu instancia de Cloud SQL. Cloud Run (completamente administrado) proporciona un mecanismo que se conecta mediante el proxy de Cloud SQL.

IP pública (predeterminada)

Conéctate con sockets Unix

Una vez que el servicio esté configurado de forma correcta, puedes conectarlo al socket del dominio Unix de la instancia de Cloud SQL al que se accede a través del sistema de archivos del entorno en la siguiente ruta de acceso: /cloudsql/INSTANCE_CONNECTION_NAME.

Estas conexiones se encriptan de forma automática sin ninguna configuración adicional. Las muestras de código que aparecen a continuación son extractos de ejemplos más completos que aparecen en el sitio de GitHub. Haz clic en View on GitHub para obtener más información.

Python

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

# 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_socket_dir = os.environ.get("DB_SOCKET_DIR", "/cloudsql")
cloud_sql_connection_name = os.environ["CLOUD_SQL_CONNECTION_NAME"]

pool = sqlalchemy.create_engine(
    # Equivalent URL:
    # mysql+pymysql://<db_user>:<db_pass>@/<db_name>?unix_socket=<socket_path>/<cloud_sql_instance_name>
    sqlalchemy.engine.url.URL(
        drivername="mysql+pymysql",
        username=db_user,  # e.g. "my-database-user"
        password=db_pass,  # e.g. "my-database-password"
        database=db_name,  # e.g. "my-database-name"
        query={
            "unix_socket": "{}/{}".format(
                db_socket_dir,  # e.g. "/cloudsql"
                cloud_sql_connection_name)  # i.e "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
        }
    ),
    **db_config
)

Java

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

// 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:mysql:///<DB_NAME>?cloudSqlInstance=<CLOUD_SQL_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.mysql.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:mysql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "mysql"
config.setPassword(DB_PASS); // e.g. "my-password"

// For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_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.
DataSource pool = new HikariDataSource(config);

Node.js

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

const createUnixSocketPool = async config => {
  const dbSocketPath = process.env.DB_SOCKET_PATH || '/cloudsql';

  // 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'
    // If connecting via unix domain socket, specify the path
    socketPath: `${dbSocketPath}/${process.env.CLOUD_SQL_CONNECTION_NAME}`,
    // Specify additional properties here.
    ...config,
  });
};

C#

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

// Equivalent connection string:
// "Server=<dbSocketDir>/<INSTANCE_CONNECTION_NAME>;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>;Protocol=unix"
String dbSocketDir = Environment.GetEnvironmentVariable("DB_SOCKET_PATH") ?? "/cloudsql";
String instanceConnectionName = Environment.GetEnvironmentVariable("INSTANCE_CONNECTION_NAME");
var connectionString = new MySqlConnectionStringBuilder()
{
    // The Cloud SQL proxy provides encryption between the proxy and instance.
    SslMode = MySqlSslMode.None,
    // 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.
    Server = String.Format("{0}/{1}", dbSocketDir, instanceConnectionName),
    UserID = Environment.GetEnvironmentVariable("DB_USER"),   // e.g. 'my-db-user
    Password = Environment.GetEnvironmentVariable("DB_PASS"), // e.g. 'my-db-password'
    Database = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'
    ConnectionProtocol = MySqlConnectionProtocol.UnixSocket
};
connectionString.Pooling = true;
// Specify additional properties here.
// ...
DbConnection connection =
    new MySqlConnection(connectionString.ConnectionString);

Comienza a usarlo

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

var (
	dbUser                 = mustGetenv("DB_USER")                  // e.g. 'my-db-user'
	dbPwd                  = mustGetenv("DB_PASS")                  // e.g. 'my-db-password'
	instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
	dbName                 = mustGetenv("DB_NAME")                  // e.g. 'my-database'
)

socketDir, isSet := os.LookupEnv("DB_SOCKET_DIR")
if !isSet {
	socketDir = "/cloudsql"
}

var dbURI string
dbURI = fmt.Sprintf("%s:%s@unix(/%s/%s)/%s?parseTime=true", dbUser, dbPwd, socketDir, instanceConnectionName, 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

Ruby

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

production:
  adapter: mysql2
  # Configure additional properties here.
  username: <%= ENV["DB_USER"] %>  # e.g. "my-database-user"
  password: <%= ENV["DB_PASS"] %> # e.g. "my-database-password"
  database: <%= ENV.fetch("DB_NAME") { "vote_production" } %>
  socket: "<%= ENV.fetch("DB_SOCKET_DIR") { '/cloudsql' } %>/<%= ENV["INSTANCE_CONNECTION_NAME"] %>"

PHP

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

// // $username = 'your_db_user';
// // $password = 'yoursupersecretpassword';
// // $db_name = 'your_db_name';
// // $cloud_sql_connection_name = getenv("CLOUD_SQL_CONNECTION_NAME");
// // $socket_dir = getenv('DB_SOCKET_DIR') ?: '/cloudsql';

// Connect using UNIX sockets
$dsn = sprintf(
    'mysql:dbname=%s;unix_socket=%s/%s',
    $db_name,
    $socket_dir,
    $cloud_sql_connection_name
);

// Connect to the database.
$conn = new PDO($dsn, $username, $password, $conn_config);

IP privada

Conéctate con TCP

Conéctate directamente con la dirección IP privada y el puerto 3306 de la instancia.

Python

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

# 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"
    ),
    **db_config
)

Java

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

// 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:mysql:///<DB_NAME>?cloudSqlInstance=<CLOUD_SQL_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.mysql.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:mysql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "mysql"
config.setPassword(DB_PASS); // e.g. "my-password"

// For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_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.
DataSource pool = new HikariDataSource(config);

Node.js

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

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

Comienza a usarlo

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

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

C#

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

            // Equivalent connection string:
            // "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<DB_HOST>;Database=<DB_NAME>;"
            var connectionString = new MySqlConnectionStringBuilder()
            {
                // The Cloud SQL proxy provides encryption between the proxy and instance.
                SslMode = MySqlSslMode.None,

                // 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.
                Server = Environment.GetEnvironmentVariable("DB_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'
                Database = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'
            };
            connectionString.Pooling = true;
            // Specify additional properties here.
            // ...
            DbConnection connection =
                new MySqlConnection(connectionString.ConnectionString);

Ruby

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

development:
  adapter: mysql2
  # Configure additional properties here
  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("DB_HOST") { "127.0.0.1" }%> # '172.17.0.1' if deployed to GAE Flex
  port: <%= ENV.fetch("DB_PORT") { 3306 }%> 

PHP

Para ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

// // $username = 'your_db_user';
// // $password = 'yoursupersecretpassword';
// // $db_name = 'your_db_name';
// // $host = "127.0.0.1";

// Connect using TCP
$dsn = sprintf('mysql:dbname=%s;host=%s', $db_name, $host);

// Connect to the database.
$conn = new PDO($dsn, $username, $password, $conn_config);

Prácticas recomendadas y más información

Puedes usar el proxy de Cloud SQL cuando pruebes tu aplicación de forma local. Consulta Inicio rápido para usar el proxy para pruebas locales si quieres obtener instrucciones detalladas.

También puedes realizar pruebas mediante el proxy de Cloud SQL a través de un contenedor de Docker.

Grupos de conexiones

Las conexiones a las bases de datos subyacentes pueden interrumpirse, ya sea por el servidor de la base de datos o por la infraestructura de la plataforma. Te recomendamos usar una biblioteca cliente que admita grupos de conexiones que vuelvan a establecer de forma automática las conexiones de clientes que no funcionan. Si quieres obtener ejemplos más detallados sobre cómo usar los grupos de conexiones, consulta la página Administra conexiones de bases de datos.

Límites de conexión

Las ediciones de MySQL y PostgreSQL de Cloud SQL imponen un límite máximo en la cantidad de conexiones simultáneas, y estos límites pueden variar según el motor de la base de datos elegida (consulta la página Cuotas y límites de Cloud SQL).

Los servicios de Cloud Run (completamente administrados) se limitan a 100 conexiones a una base de datos de Cloud SQL. Este límite se aplica por instancia de servicio, por lo que cada instancia del servicio de Cloud Run (completamente administrado) puede tener 100 conexiones a la base de datos. A medida que aumenta la escala, puede aumentar el total de conexiones por implementación.

Puedes limitar la cantidad máxima de conexiones de cada instancia mediante un grupo de conexiones. Para obtener ejemplos más detallados sobre cómo limitar la cantidad de conexiones, consulta la página Administra conexiones de bases de datos.

Límites de cuota de la API

Cloud Run (completamente administrado) proporciona un mecanismo que se conecta mediante el proxy de Cloud SQL, que usa la API de Administrador de Cloud SQL. Los límites de cuota de la API se aplican al proxy de Cloud SQL.

Próximos pasos