התחברות מ-Cloud Run

בדף הזה מוסבר איך להתחבר למכונה של Cloud SQL משירות שפועל ב-Cloud Run, ומוצגות דוגמאות.

להוראות מפורטות להפעלת אפליקציית אינטרנט לדוגמה ב-Cloud Run שמחוברת ל-Cloud SQL, קראו את המדריך למתחילים להתחברות מ-Cloud Run.

‫Cloud SQL הוא שירות מנוהל של מסד נתונים, שבעזרתו אפשר ליצור, לתחזק ולנהל מסדי נתונים רלציוניים בענן.

‫Cloud Run היא פלטפורמת מחשוב מנוהלת שמאפשרת להריץ קונטיינרים ישירות בתשתית של Google Cloud .

הגדרת מכונה של Cloud SQL

  1. מפעילים את Cloud SQL Admin API בפרויקט ב- Google Cloud שממנו מתחברים, אם עדיין לא עשיתם את זה:

    התפקידים שנדרשים כדי להפעיל ממשקי API

    כדי להפעיל ממשקי API, צריך את ההרשאה serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד "בעלים" (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד "אדמין בממשק 'שימוש בשירות'" (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידים

    להפעלת ה-API

  2. יוצרים מכונה של Cloud SQL ל-MySQL. כדי לשפר את זמן האחזור, להימנע מעלויות מסוימות של שימוש ברשת ולהפחית את הסיכון לכשלים בין אזורים, מומלץ לבחור מיקום למכונה של Cloud SQL באותו אזור של שירות Cloud Run.

    כברירת מחדל, Cloud SQL מקצה כתובת IP ציבורית למכונה חדשה. אפשר גם להקצות כתובת IP פרטית. למידע נוסף על אפשרויות הקישוריות של שניהם, קראו את הדף סקירה כללית על התחברות.

  3. כשיוצרים את המכונה, אפשר לבחור את ההיררכיה של אישור השרת (CA) של המכונה, ואז להגדיר את ההיררכיה בתור serverCaMode של המכונה. כדי להתחבר למכונות מאפליקציות אינטרנט, צריך לבחור באפשרות של רשות אישורים לכל מכונה (GOOGLE_MANAGED_INTERNAL_CA) כמצב של רשות האישורים בשרת.

הגדרת Cloud Run

השלבים להגדרת Cloud Run משתנים בהתאם לסוג כתובת ה-IP שהקציתם למכונה של Cloud SQL. אם אתם מנתבים את כל תעבורת הנתונים היוצאת דרך Direct VPC או דרך מחבר של חיבור לרשת (VPC) מאפליקציית serverless, אתם צריכים להשתמש בכתובת IP פרטית. להשוואה בין שתי השיטות לתעבורת נתונים יוצאת, ראו השוואה בין Direct VPC לבין מחברי VPC.

כתובת IP ציבורית (ברירת מחדל)

  • מוודאים שלמכונה יש כתובת IP ציבורית. אפשר לוודא את זה בדף Overview של המכונה במסוףGoogle Cloud . אם אתם צריכים להוסיף כתובת IP, תוכלו להיעזר בהוראות שבדף הגדרת כתובת IP ציבורית.
  • משיגים את INSTANCE_CONNECTION_NAME של המכונה. אפשר למצוא את הערך הזה בדף Overview של המכונה במסוףGoogle Cloud , או על ידי הרצת הפקודה הבאה של gcloud sql instances describe:
       gcloud sql instances describe INSTANCE_NAME
       
    מחליפים את INSTANCE_NAME בשם של המכונה ב-Cloud SQL.
  • מאתרים את CLOUD_RUN_SERVICE_ACCOUNT_NAME של שירות Cloud Run. אפשר למצוא את הערך הזה בדף IAM של הפרויקט שמארח את שירות Cloud Run בGoogle Cloud מסוף, או על ידי הפעלת הפקודה הבאה של gcloud run services describe בפרויקט שמארח את שירות Cloud Run:
    gcloud run services describe CLOUD_RUN_SERVICE_NAME
    --region CLOUD_RUN_SERVICE_REGION --format="value(spec.template.spec.serviceAccountName)"
       
    מחליפים את המשתנים הבאים:
    • ‫CLOUD_RUN_SERVICE_NAME: השם של שירות Cloud Run
    • ‫CLOUD_RUN_SERVICE_REGION: האזור של שירות Cloud Run
  • מגדירים את חשבון השירות של שירות Cloud Run. כדי להתחבר ל-Cloud SQL, ודאו שלחשבון השירות יש את תפקיד ה-IAM Cloud SQL Client.
  • אם אתם מוסיפים חיבור של Cloud SQL לשירות חדש, אתם צריכים להכניס את השירות לקונטיינר ולהעלות אותו ל-Container Registry או ל-Artifact Registry. אם עדיין אין לכם חיבור, תוכלו להיעזר בהוראות לבנייה ולפריסה של קובץ אימג' של קונטיינר.
  • אם אתם מתחברים למכונות שמוגדרות עם האפשרות של רשות אישורים (CA) משותפת (GOOGLE_MANAGED_CAS_CA) או האפשרות של רשות אישורים בניהול הלקוח (CUSTOMER_MANAGED_CAS_CA) בתור מצב CA של השרת, בחרו בסביבת ההפעלה מהדור השני כשאתם בוחרים את סביבת ההפעלה של השירות. בשתי האפשרויות של מצב CA בשרת, צריך להתחבר למכונה באמצעות Cloud SQL Auth Proxy v2.

    אם השירות פועל בסביבת זמן ריצה מהדור הראשון, אפשר להתחבר רק למכונות Cloud SQL שמוגדרות עם האפשרות של רשות אישורים (CA) לכל מכונה (GOOGLE_MANAGED_INTERNAL_CA) כמצב ה-CA של השרת. סביבת זמן הריצה מהדור הראשון של Cloud Run כוללת את גרסה 1 של Cloud SQL Auth Proxy. מידע נוסף על דרישות החיבור ל-Cloud SQL בשביל Cloud SQL Auth Proxy זמין במאמר דרישות לשימוש ב-Cloud SQL Auth Proxy.

כמו כל שינוי בהגדרות, הגדרת תצורה חדשה לחיבור ל-Cloud SQL מובילה ליצירת גרסה חדשה של Cloud Run. גם הגרסאות הבאות יקבלו באופן אוטומטי את החיבור הזה ל-Cloud SQL, אלא אם תבצעו עדכונים מפורשים כדי לשנות אותו.

המסוף

  1. כניסה ל-Cloud Run

  2. מתחילים להגדיר את השירות. כדי להוסיף חיבורים של Cloud SQL לשירות קיים:

    1. ברשימה Services, לוחצים על שם השירות הרצוי.
    2. לוחצים על Edit & deploy new revision.
  3. מפעילים את החיבור למכונה של Cloud SQL:
    1. לוחצים על מאגרים ואז על הגדרות.
    2. גוללים לקטע Cloud SQL connections.
    3. לוחצים על הוספת חיבור.
    4. אם עדיין לא הפעלתם את Cloud SQL Admin API, לוחצים על הכפתור Enable the Cloud SQL Admin.

    הוספת חיבור ל-Cloud SQL

    • אם אתם מוסיפים חיבור למכונה של Cloud SQL בפרויקט, בחרו את המכונה הרצויה של Cloud SQL מהתפריט.
    • אם משתמשים במכונה של Cloud SQL מפרויקט אחר, בוחרים בתפריט באפשרות custom connection string ומזינים את השם המלא של החיבור למכונה בפורמט PROJECT-ID:REGION:INSTANCE-ID.
    • כדי למחוק חיבור, מציבים את הסמן מימין לחיבור עד שמופיע הסמל Delete ולוחצים עליו.
  4. לוחצים על Create או על Deploy.

שורת הפקודה

לפני שמשתמשים בפקודות הבאות, צריך להחליף את הערכים בשדות הבאים:

  • IMAGE עם קובץ האימג' שפורסים
  • ‫SERVICE_NAME בשם של שירות Cloud Run
  • ‫INSTANCE_CONNECTION_NAME בשם החיבור של המכונה ב-Cloud SQL, או ברשימה של שמות חיבורים שמופרדים בפסיקים.

    אם אתם פורסים מאגר חדש, השתמשו בפקודה הבאה:

    gcloud run deploy \
      --image=IMAGE \
      --add-cloudsql-instances=INSTANCE_CONNECTION_NAME
    אם מעדכנים שירות קיים, משתמשים בפקודה הבאה:
    gcloud run services update SERVICE_NAME \
      --add-cloudsql-instances=INSTANCE_CONNECTION_NAME

Terraform

הקוד הבא יוצר קונטיינר בסיסי של Cloud Run, עם מכונה מחוברת של Cloud SQL.

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

  deletion_protection = false # set to "true" in production

  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. מזינים terraform apply כדי להחיל את השינויים.
  2. כדי לוודא שהשינויים בוצעו, לוחצים על השם של שירות Cloud Run, ואז בכרטיסייה Containers מאתרים את ההגדרה Cloud SQL connections.

כתובת IP פרטית

אם חשבון השירות המאשר שייך לפרויקט אחר מזה שמכיל את המכונה של Cloud SQL, מבצעים את הפעולות הבאות:

  • מפעילים את Cloud SQL Admin API בשני הפרויקטים.
  • מוסיפים את הרשאות ה-IAM לחשבון השירות בפרויקט שמכיל את המכונה של Cloud SQL.
תעבורת נתונים יוצאת ישירה ל-VPC ומחברים משתמשים בכתובות IP פרטיות כדי לטפל בתקשורת לרשת ה-VPC. כדי להתחבר ישירות לכתובות IP פרטיות באמצעות אחת משיטות תעבורת הנתונים היוצאת (egress) האלה:
  1. מוודאים שלמכונה של Cloud SQL שיצרתם קודם יש כתובת IP פרטית. כדי להוסיף כתובת IP פנימית, קראו את המאמר הגדרת כתובת IP פרטית.
  2. מגדירים את שיטת תעבורת הנתונים היוצאת כדי להתחבר לאותה רשת VPC של המכונה ב-Cloud SQL. שימו לב לתנאים הבאים:
    • Direct VPC egress ו-Serverless VPC Access תומכים בתקשורת לרשתות VPC שמחוברות באמצעות Cloud VPN וVPC Network Peering.
    • Direct VPC egress ו-Serverless VPC Access לא תומכים ברשתות מדור קודם.
    • אם אתם לא משתמשים ב- VPC משותף, המחבר צריך להיות באותו פרויקט ובאותו אזור כמו המשאב שמשתמש בו, אבל המחבר יכול לשלוח תנועה למשאבים באזורים שונים.
  3. מתחברים באמצעות כתובת ה-IP הפרטית של המכונה ויציאה 3306.

התחברות ל-Cloud SQL

אחרי שמגדירים את Cloud Run, אפשר להתחבר למכונה של Cloud SQL.

כתובת IP ציבורית (ברירת מחדל)

בנתיבים של כתובות IP ציבוריות, אפשר להגדיר את Cloud Run כך שישתמש ב-Cloud SQL Auth Proxy להצפנה בשתי דרכים:

שימוש ב-Secret Manager

‫Google ממליצה להשתמש ב-Secret Manager כדי לאחסן מידע רגיש כמו פרטי כניסה ל-SQL. ב-Cloud Run, אתם יכולים להעביר סודות כמשתני סביבה או לטעון אותם כנפח אחסון.

אחרי שיוצרים סוד ב-Secret Manager, מעדכנים שירות קיים באמצעות הפקודה הבאה:

שורת הפקודה

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

הקוד הבא יוצר משאבי סודות כדי לשמור באופן מאובטח את ערכי המשתמש, הסיסמה והשם של מסד הנתונים באמצעות google_secret_manager_secret ו-google_secret_manager_secret_version. שימו לב שצריך לעדכן את חשבון השירות של הפרויקט ב-Compute Engine כדי שתהיה לו גישה לכל סוד.


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

מעדכנים את המשאב הראשי של Cloud Run כך שיכלול את הסודות החדשים.

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

  deletion_protection = false # set to "true" in production

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

מזינים terraform apply כדי להחיל את השינויים.

בפקודה לדוגמה נעשה שימוש בגרסת הסוד latest, אבל Google ממליצה להצמיד את הסוד לגרסה ספציפית, SECRET_NAME:v1.

כתובת IP פרטית

בנתיבים של כתובות IP פרטיות, האפליקציה מתחברת ישירות למכונה דרך רשת VPC. בשיטה הזו משתמשים ב-TCP כדי להתחבר ישירות למכונה של Cloud SQL בלי להשתמש ב-Cloud SQL Auth Proxy.

התחברות באמצעות TCP

מתחברים באמצעות כתובת ה-IP הפרטית של מכונת Cloud SQL כמארח וליציאה 3306.

Python

כדי לראות את קטע הקוד הזה בהקשר של אפליקציית אינטרנט, אפשר לעיין ב-README ב-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

כדי לראות את קטע הקוד הזה בהקשר של אפליקציית אינטרנט, עיינו ב-README ב-GitHub.

הערה:


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

כדי לראות את קטע הקוד הזה בהקשר של אפליקציית אינטרנט, אפשר לעיין ב-README ב-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);
};

המשך

כדי לראות את קטע הקוד הזה בהקשר של אפליקציית אינטרנט, אפשר לעיין ב-README ב-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
}

C#‎

כדי לראות את קטע הקוד הזה בהקשר של אפליקציית אינטרנט, אפשר לעיין ב-README ב-GitHub.

using MySql.Data.MySqlClient;
using System;

namespace CloudSql
{
    public class MySqlTcp
    {
        public static MySqlConnectionStringBuilder NewMysqlTCPConnectionString()
        {
            // Equivalent connection string:
            // "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<INSTANCE_HOST>;Database=<DB_NAME>;"
            var connectionString = new MySqlConnectionStringBuilder()
            {
                // 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.
                Server = 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'
                Database = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'

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

        }
    }
}

Ruby

כדי לראות את קטע הקוד הזה בהקשר של אפליקציית אינטרנט, אפשר לעיין ב-README ב-GitHub.

tcp: &tcp
  adapter: mysql2
  # 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") { 3306 }%>

PHP

כדי לראות את קטע הקוד הזה בהקשר של אפליקציית אינטרנט, אפשר לעיין ב-README ב-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;
    }
}

שיטות מומלצות ומידע נוסף

אתם יכולים להשתמש ב-Cloud SQL Auth Proxy כשאתם בודקים את האפליקציה באופן מקומי. הוראות מפורטות מופיעות במאמר התחלה מהירה: שימוש ב-Cloud SQL Auth Proxy.

אפשר גם לבדוק באמצעות שרת proxy ל-Cloud SQL דרך קונטיינר של Docker.

מאגרי חיבורים

יכול להיות שהחיבורים למסדי הנתונים הבסיסיים ינותקו על ידי שרת מסד הנתונים עצמו או על ידי תשתית הפלטפורמה. מומלץ להשתמש בספריית לקוח שתומכת במאגרי חיבורים, שמחברים מחדש באופן אוטומטי חיבורי לקוח מנותקים. אתם יכולים להשתמש במאגר מנוהל של חיבורים במכונות של Cloud SQL, כדי לשנות את קנה המידה של עומסי העבודה באמצעות אופטימיזציה של ניצול המשאבים וזמן האחזור של החיבורים במכונות של Cloud SQL. סקירה כללית על מאגר מנוהל של חיבורים

דוגמאות מפורטות יותר לשימוש במאגרי חיבורים מופיעות בדף ניהול החיבורים למסד הנתונים.

מגבלות על החיבורים

גם במהדורת MySQL וגם במהדורת PostgreSQL של Cloud SQL יש מגבלה על מספר החיבורים בו-זמנית, והמגבלות האלה עשויות להשתנות בהתאם למנוע של מסד הנתונים שנבחר (ראו את הדף מכסות ומגבלות ב-Cloud SQL).

מכונות קונטיינר של Cloud Run מוגבלות ל-100 חיבורים למסד נתונים של Cloud SQL. לכל מכונה של שירות או משימה ב-Cloud Run יכולים להיות 100 חיבורים למסד הנתונים, וככל שהשירות או המשימה גדלים, המספר הכולל של החיבורים לכל פריסה יכול לגדול.

אתם יכולים להגביל את מספר החיבורים המקסימלי לכל מכונה באמצעות מאגר חיבורים. דוגמאות מפורטות יותר להגבלת מספר החיבורים מופיעות בדף ניהול החיבורים למסד הנתונים.

מגבלות המכסות של ה-API

ב-Cloud Run יש מנגנון שמתחבר באמצעות Cloud SQL Auth Proxy, שמשתמש ב-Cloud SQL Admin API. מגבלות המכסות של ה-API חלות על Cloud SQL Auth Proxy. המכסה של Cloud SQL Admin API שנעשה בה שימוש היא בערך פי שניים ממספר המכונות של Cloud SQL שהוגדרו, כפול מספר המכונות של Cloud Run של שירות מסוים שנפרסו בכל זמן נתון. אתם יכולים להגביל או להגדיל את מספר המכונות של Cloud Run כדי לשנות את מכסת ה-API הצפויה.

המאמרים הבאים