Se connecter depuis des fonctions Cloud Run

Cette page contient des informations et des exemples de connexion à une instance Cloud SQL à partir d'un service s'exécutant dans les fonctions Cloud Run.

Pour obtenir des instructions détaillées sur l'exécution d'un exemple d'application Web des fonctions Cloud Run connectée à Cloud SQL, consultez la section Démarrage rapide pour la connexion à partir des fonctions Cloud Run.

Cloud SQL est un service de base de données entièrement géré qui vous aide à configurer, maintenir, gérer et administrer vos bases de données relationnelles dans le cloud.

L'outil fonctions Cloud Run est une solution de calcul légère permettant aux développeurs de créer des fonctions autonomes à usage unique qui répondent aux événements Cloud, sans avoir à gérer de serveur ni d'environnement d'exécution.

Configurer une instance Cloud SQL

  1. Activez l'API Cloud SQL Admin dans le projet Google Cloud à partir duquel vous vous connectez, si ce n'est pas déjà fait :

    Enable the API

  2. Créez une instance Cloud SQL pour MySQL. Nous vous recommandons de choisir un emplacement d'instance Cloud SQL qui soit dans la même région que votre service Cloud Run, afin d'améliorer la latence, d'éviter certains coûts de mise en réseau et de réduire les risques de défaillance interrégionale.

    Par défaut, Cloud SQL attribue une adresse IP publique à une nouvelle instance. Vous avez également la possibilité d'attribuer une adresse IP privée. Pour en savoir plus sur les options de connectivité disponibles pour ces deux types d'adresses IP, consultez la page Présentation du processus de connexion.

Configurer les fonctions Cloud Run

La procédure à suivre pour configurer la solution fonctions Cloud Run dépend du type d'adresse IP que vous avez attribué à votre instance Cloud SQL.

Adresse IP publique (par défaut)

Pour configurer les fonctions Cloud Run afin d'activer les connexions à une instance Cloud SQL, procédez comme suit :

  • Vérifiez que l'instance créée ci-dessus possède une adresse IP publique. Vous pouvez le vérifier sur la page Présentation de l'instance dans la console Google Cloud. Si vous devez ajouter une adresse IP publique, consultez la section Configurer une adresse IP publique.
  • Obtenez le INSTANCE_CONNECTION_NAME de l'instance. Cette valeur est disponible :
    • Sur la page Présentation de l'instance, dans la console Google Cloud, ou
    • En exécutant la commande suivante : gcloud sql instances describe [INSTANCE_NAME]
  • Configurez le compte de service pour votre fonction. Si le compte de service d'autorisation appartient à un projet différent de l'instance Cloud SQL, activez l'API Cloud SQL Admin et ajoutez les autorisations IAM répertoriées ci-dessous pour les deux projets. Vérifiez que le compte de service dispose des rôles et autorisations Cloud SQL appropriés pour se connecter à Cloud SQL.
    • Pour se connecter à Cloud SQL, le compte de service doit bénéficier de l'un des rôles IAM suivants :
      • Cloud SQL Client (rôle à privilégier)
      • Cloud SQL Editor
      • Cloud SQL Admin
      Vous pouvez également attribuer manuellement les autorisations IAM suivantes :
      • cloudsql.instances.connect
      • cloudsql.instances.get
  • Si vous utilisez des fonctions Cloud Run et non des fonctions Cloud Run (1re génération), les éléments suivants sont obligatoires (voir également la section Configurer Cloud Run) :
    1. Initialisez votre fonction.
      Lorsque vous commencez à créer une fonction Cloud Run dans la console Google Cloud, le service Cloud Run sous-jacent n'a pas encore été créé. Vous ne pouvez pas configurer une connexion Cloud SQL tant que ce service n'est pas créé (en déployant la fonction Cloud Run).
    2. Dans la console Google Cloud, dans l'angle supérieur droit de la page Informations sur la fonction, sous Fourni par Cloud Run, cliquez sur le lien pour accéder au cloud sous-jacent.
    3. Sur la page Détails du service de Cloud Run, sélectionnez l'onglet Modifier et déployer la nouvelle révision.
    4. Suivez les étapes standards (comme pour tout changement de configuration) afin de définir une nouvelle configuration pour une connexion Cloud SQL.
      Cela crée une révision Cloud Run, après quoi les révisions suivantes reçoivent automatiquement cette connexion Cloud SQL, sauf si vous la modifiez explicitement.

Adresse IP privée

Si le compte de service d'autorisation appartient à un projet différent de celui contenant l'instance Cloud SQL, procédez comme suit :

  • Dans les deux projets, activez l'API Cloud SQL Admin.
  • Pour le compte de service du projet contenant l'instance Cloud SQL, ajoutez les autorisations IAM.
Un connecteur d'accès au VPC sans serveur utilise des adresses IP privées pour gérer la communication avec votre réseau VPC. Pour vous connecter directement avec des adresses IP privées, procédez comme suit :
  1. Assurez-vous que l'instance Cloud SQL créée précédemment possède une adresse IP privée. Si vous devez en ajouter une, consultez la page Configurer une adresse IP privée pour savoir comment procéder.
  2. Créez un connecteur d'Accès au VPC sans serveur dans le même réseau VPC que votre instance Cloud SQL. Veuillez noter les conditions suivantes :
    • À moins que vous n'utilisiez le VPC partagé, votre connecteur doit se trouver dans le même projet et la même région que la ressource qui l'utilise, mais il peut envoyer du trafic à des ressources se trouvant dans d'autres régions.
    • L'accès au VPC sans serveur accepte la communication avec les réseaux VPC connectés à l'aide de Cloud VPN et de l'appairage de réseaux VPC.
    • L'accès au VPC sans serveur n'est pas compatible avec les anciens réseaux.
  3. Configurez les fonctions Cloud Run de façon à utiliser le connecteur.
  4. Connectez-vous avec l'adresse IP privée et le port 3306 de votre instance.

Se connecter à Cloud SQL

Une fois que vous avez configuré les fonctions Cloud Run, vous pouvez vous connecter à votre instance Cloud SQL.

Adresse IP publique (par défaut)

Pour les chemins d'accès d'adresses IP publiques, la solutions de fonctions Cloud Run assure le chiffrement et se connecte à l'aide du proxy d'authentification Cloud SQL de deux manières :

Adresse IP privée

Pour les chemins d'accès des adresses IP privées, votre application se connecte directement à votre instance via un réseau VPC. Cette méthode utilise TCP pour se connecter directement à l'instance Cloud SQL sans utiliser le proxy d'authentification Cloud SQL.

Se connecter avec TCP

Connectez-vous en utilisant l'adresse IP privée de votre instance Cloud SQL en tant qu'hôte et le port 3306.

Python

Pour afficher cet extrait dans le contexte d'une application Web, consultez le fichier README sur 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

Pour afficher cet extrait dans le contexte d'une application Web, consultez le fichier README sur GitHub.

Remarque :

  • INSTANCE_CONNECTION_NAME doit être représenté au format <MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>.
  • L'utilisation de l'argument ipTypes=PRIVATE force la connexion de SocketFactory à l'adresse IP privée associée à une instance.
  • Pour en savoir plus sur les exigences de version Socket Factory des sockets JDBC pour le fichier pom.xml, cliquez ici.


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

Pour afficher cet extrait dans le contexte d'une application Web, consultez le fichier README sur 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

Pour afficher cet extrait dans le contexte d'une application Web, consultez le fichier README sur GitHub.

package cloudsql

import (
	"crypto/tls"
	"crypto/x509"
	"database/sql"
	"errors"
	"fmt"
	"io/ioutil"
	"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

Pour afficher cet extrait dans le contexte d'une application Web, consultez le fichier README sur 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;
    }
}

Bonnes pratiques et autres informations

Vous pouvez utiliser le proxy d'authentification Cloud SQL lorsque vous testez votre application en local. Pour obtenir des instructions détaillées, consultez le guide de démarrage rapide pour l'utilisation du proxy d'authentification Cloud SQL.

Pools de connexions

Les connexions aux bases de données sous-jacentes peuvent être supprimées, soit par le serveur de base de données lui-même, soit par l'infrastructure qui sous-tend les fonctions Cloud Run. Nous vous recommandons d'utiliser une bibliothèque cliente compatible avec les pools de connexions qui restaurent automatiquement les connexions client interrompues. De plus, nous recommandons d'utiliser un pool de connexions globalement limité, car cela augmente la probabilité que votre fonction réutilise la même connexion pour les invocations ultérieures de la fonction et qu'elle ferme naturellement la connexion lorsque l'instance est évincée (autoscaling à la baisse). Pour obtenir des exemples plus détaillés d'utilisation des pools de connexions, consultez la page Gérer les connexions à la base de données.

Limites de connexion

Cloud SQL impose une limite maximale de connexions simultanées, laquelle peut varier en fonction du moteur de base de données choisi (consultez la page Quotas et limites de Cloud SQL). Il est recommandé d'utiliser une connexion avec les fonctions Cloud Run, mais il est important de définir le nombre maximal de connexions sur 1.

Lorsque cela est possible, veillez à n'initialiser un pool de connexions que pour les fonctions qui doivent accéder à votre base de données. Certains pools de connexions créent des connexions de manière préemptive, ce qui peut consommer des ressources excédentaires et être comptabilisé dans vos limites de connexion. Pour cette raison, il est recommandé d'utiliser l'initialisation différée pour retarder la création d'un pool de connexions jusqu'à ce que cela soit nécessaire et n'inclure le pool de connexions que dans les fonctions où il est utilisé.

Pour obtenir des exemples plus détaillés de limitation du nombre de connexions, consultez la page Gérer les connexions à la base de données.

Limites de quota d'API

La solution de fonctions Cloud Run fournit un mécanisme permettant de se connecter à l'aide du proxy d'authentification Cloud SQL, qui utilise l'API Cloud SQL Admin. Les limites de quota d'API s'appliquent au proxy d'authentification Cloud SQL. Le quota de l'API Cloud SQL Admin utilisé correspond approximativement au double du nombre d'instances Cloud SQL configurées ou au nombre total de fonctions déployées. Vous pouvez définir le nombre maximal d'appels simultanés pour modifier le quota d'API que vous prévoyez d'utiliser. La solution des fonctions Cloud Run impose également des limitations de débit sur le nombre d'appels d'API autorisés par tranche de 100 secondes.

Étape suivante