Conectarse desde Cloud Run Functions

En esta página se ofrece información y ejemplos sobre cómo conectarse a una instancia de Cloud SQL desde un servicio que se ejecuta en funciones de Cloud Run.

Para obtener instrucciones detalladas sobre cómo ejecutar una aplicación web de ejemplo de funciones de Cloud Run conectada a Cloud SQL, consulta la guía de inicio rápido para conectarse desde funciones de Cloud Run.

Cloud SQL es un servicio de base de datos totalmente gestionado que te permite configurar, mantener y gestionar tus bases de datos relacionales en la nube.

Cloud Run functions es una solución de computación ligera con la que los desarrolladores pueden crear funciones independientes con un solo propósito que respondan a eventos en Google Cloud sin necesidad de gestionar servidores ni entornos de ejecución.

Configurar una instancia de Cloud SQL

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

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  2. Crea una instancia de Cloud SQL para MySQL. Te recomendamos que elijas una ubicación de instancia de Cloud SQL en la misma región que tu servicio de Cloud Run para mejorar la latencia, evitar algunos costes de redes y reducir los riesgos de fallos entre regiones.

    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 Información general sobre la conexión.

  3. Cuando crees la instancia, puedes elegir la jerarquía de certificados de servidor (CA) de la instancia y, a continuación, configurar la jerarquía como serverCaMode de la instancia. Debes seleccionar la opción de AC por instancia (GOOGLE_MANAGED_INTERNAL_CA) como modo de AC del servidor para las instancias a las que quieras conectarte desde aplicaciones web.

Configurar funciones de Cloud Run

Los pasos para configurar las funciones de Cloud Run dependen del tipo de dirección IP que hayas asignado a tu instancia de Cloud SQL.

IP pública (predeterminada)

Para configurar funciones de Cloud Run que permitan conectarse a una instancia de Cloud SQL, sigue estos pasos:

  • Confirma que la instancia creada anteriormente tiene una dirección IP pública. Puedes confirmarlo en la página Descripción general de la instancia en la Google Cloud consola. Si necesitas añadir una dirección IP pública, consulta Configurar una IP pública.
  • Obtén el INSTANCE_CONNECTION_NAME de la instancia. Este valor está disponible:
    • En la página Información general de la instancia, en la Google Cloud consola, o
    • Ejecutando el siguiente comando: gcloud sql instances describe [INSTANCE_NAME]
  • Configura la cuenta de servicio de tu función. Si la cuenta de servicio de autorización pertenece a un proyecto distinto de la instancia de Cloud SQL, debes habilitar la API Cloud SQL Admin y añadir el Cloud SQL Client rol de gestión de identidades y accesos a ambos proyectos.
  • Confirma que la cuenta de servicio tiene este rol para que pueda conectarse a Cloud SQL.
  • Si usas Cloud Run functions y no Cloud Run functions (1.ª gen.), debes cumplir los siguientes requisitos (consulta también Configurar Cloud Run):
    1. Despliega tu función inicialmente.
      Cuando empiezas a crear una función de Cloud Run en la consola de Google Cloud , el servicio de Cloud Run subyacente aún no se ha creado. No puedes configurar una conexión de Cloud SQL hasta que se cree ese servicio (desplegando la función de Cloud Run).
    2. En la Google Cloud consola, en la parte superior derecha de la página Detalles de la función, en Desarrollado con Cloud Run, haz clic en el enlace para acceder al servicio de Cloud Run subyacente.
    3. En la página Detalles del servicio de Cloud Run, selecciona la pestaña Editar y desplegar nueva revisión.
    4. Sigue los pasos estándar (como en el caso de cualquier cambio de configuración) para definir una nueva configuración de una conexión de Cloud SQL.
      De esta forma, se crea una revisión de Cloud Run y las revisiones posteriores reciben automáticamente esta conexión de Cloud SQL, a menos que la cambies explícitamente.

IP privada

Si la cuenta de servicio de autorización pertenece a un proyecto distinto del que contiene la instancia de Cloud SQL, haz lo siguiente:

Un conector de acceso a VPC sin servidor usa direcciones IP privadas para gestionar la comunicación con tu red de VPC. Para conectarte directamente con direcciones IP privadas, debes hacer lo siguiente:
  1. Asegúrate de que la instancia de Cloud SQL que has creado anteriormente tenga una dirección IP privada. Si necesitas añadir una, consulta las instrucciones para configurar una IP privada.
  2. Crea un conector de acceso a VPC sin servidor en la misma red de VPC que tu instancia de Cloud SQL. Ten en cuenta las siguientes condiciones:
    • A menos que utilices una VPC compartida, el conector debe estar en el mismo proyecto y región que el recurso que lo utiliza, pero puede enviar tráfico a recursos de otras regiones.
    • Acceso a VPC sin servidor admite la comunicación con redes de VPC conectadas mediante Cloud VPN y emparejamiento entre redes de VPC.
    • Acceso a VPC sin servidor no admite redes antiguas.
  3. Configura las funciones de Cloud Run para que usen el conector.
  4. Conéctate mediante la dirección IP privada y el puerto de tu instancia 3306.

Conectar a Cloud SQL

Una vez que hayas configurado las funciones de Cloud Run, podrás conectarte a tu instancia de Cloud SQL.

IP pública (predeterminada)

En el caso de las rutas de IP públicas, las funciones de Cloud Run proporcionan cifrado y se conectan mediante el proxy de autenticación de Cloud SQL de dos formas:

IP privada

En el caso de las rutas de IP privadas, tu aplicación se conecta directamente a tu instancia a través de una red VPC. Este método usa TCP para conectarse directamente a la instancia de Cloud SQL sin usar el proxy de autenticación de Cloud SQL.

Conectarse con TCP

Conéctate mediante la dirección IP privada de tu instancia de Cloud SQL como host y el puerto 3306.

Python

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

import os

import sqlalchemy


def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
    """Initializes a TCP connection pool for a Cloud SQL instance of MySQL."""
    # 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. 3306

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

Java

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

Nota:


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

public class TcpConnectionPoolFactory extends ConnectionPoolFactory {

  // Saving credentials in environment variables is convenient, but not secure - consider a more
  // secure solution such as 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();

    // The following URL is equivalent to setting the config options below:
    // jdbc:mysql://<INSTANCE_HOST>:<DB_PORT>/<DB_NAME>?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:%s/%s", INSTANCE_HOST, DB_PORT, DB_NAME));
    config.setUsername(DB_USER); // e.g. "root", "mysql"
    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 ver este fragmento en el contexto de una aplicación web, consulta el archivo README en GitHub.

const mysql = require('promise-mysql');
const fs = require('fs');

// createTcpPool initializes a TCP connection pool for a Cloud SQL
// instance of MySQL.
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 = {
    host: process.env.INSTANCE_HOST, // e.g. '127.0.0.1'
    port: process.env.DB_PORT, // e.g. '3306'
    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'
    // ... Specify additional properties here.
    ...config,
  };
  // Establish a connection to the database.
  return mysql.createPool(dbConfig);
};

Go

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

package cloudsql

import (
	"crypto/tls"
	"crypto/x509"
	"database/sql"
	"errors"
	"fmt"
	"log"
	"os"

	"github.com/go-sql-driver/mysql"
)

// connectTCPSocket initializes a TCP connection pool for a Cloud SQL
// instance of MySQL.
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.", 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'
		dbPort    = mustGetenv("DB_PORT")       // e.g. '3306'
		dbTCPHost = mustGetenv("INSTANCE_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
	)

	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: %w", err)
	}

	// ...

	return dbPool, nil
}

PHP

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

namespace Google\Cloud\Samples\CloudSQL\MySQL;

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('mysql:dbname=%s;host=%s', $dbName, $instanceHost);

            // 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/mysql/connect-external-app',
                    $e->getMessage()
                ),
                $e->getCode(),
                $e
            );
        }

        return $conn;
    }
}

Prácticas recomendadas y otra información

Puedes usar el proxy de autenticación de Cloud SQL cuando pruebes tu aplicación de forma local. Consulta la guía de inicio rápido para usar el proxy de autenticación de Cloud SQL para obtener instrucciones detalladas.

Grupos de conexión

Es posible que se interrumpan las conexiones a las bases de datos subyacentes, ya sea por el propio servidor de la base de datos o por la infraestructura subyacente de las funciones de Cloud Run. Te recomendamos que utilices una biblioteca de cliente que admita grupos de conexiones que vuelvan a conectar automáticamente las conexiones de cliente rotas. Además, te recomendamos que uses un grupo de conexiones de ámbito global para aumentar la probabilidad de que tu función reutilice la misma conexión en invocaciones posteriores y cierre la conexión de forma natural cuando se elimine la instancia (se reduce la escala automáticamente). Para ver ejemplos más detallados sobre cómo usar los grupos de conexiones, consulta Gestionar conexiones de bases de datos.

Límites de conexiones

Cloud SQL impone un límite máximo en las conexiones simultáneas, y estos límites pueden variar en función del motor de base de datos elegido (consulta Cuotas y límites de Cloud SQL). Se recomienda usar una conexión con funciones de Cloud Run, pero es importante definir el número máximo de conexiones en 1.

Siempre que sea posible, solo debes inicializar un grupo de conexiones para las funciones que necesiten acceder a tu base de datos. Algunos grupos de conexiones crearán conexiones de forma preventiva, lo que puede consumir recursos en exceso y contabilizarse en los límites de conexión. Por este motivo, se recomienda usar inicialización diferida para retrasar la creación de un grupo de conexiones hasta que sea necesario e incluir el grupo de conexiones solo en las funciones en las que se utilice.

Para ver ejemplos más detallados sobre cómo limitar el número de conexiones, consulta el artículo Gestionar conexiones de bases de datos.

Límites de cuota de la API

Las funciones de Cloud Run proporcionan un mecanismo que se conecta mediante el proxy de autenticación de Cloud SQL, que usa la API Admin de Cloud SQL. Se aplican límites de cuota de API al proxy de autenticación de Cloud SQL. La cuota de la API Admin de Cloud SQL utilizada es aproximadamente el doble del número de instancias de Cloud SQL configuradas multiplicado por el número total de funciones implementadas. Puedes definir el número máximo de invocaciones simultáneas para modificar la cuota de API esperada que se consume. Las funciones de Cloud Run también imponen límites de frecuencia al número de llamadas a la API permitidas cada 100 segundos.

Siguientes pasos