חיבור באמצעות מחברי שפה של Cloud SQL

המחברים של Cloud SQL הם ספריות שמספקות הצפנה והרשאה שמבוססת על ניהול זהויות והרשאות גישה (IAM) כשמתחברים למכונה של Cloud SQL. הם לא יכולים לספק נתיב רשת למופע Cloud SQL אם הוא לא קיים.

דרכים אחרות להתחבר למכונה של Cloud SQL כוללות שימוש בלקוח מסד נתונים או בשרת proxy ל-Cloud SQL Auth. מידע נוסף על חיבור למופע Cloud SQL זמין במאמר אפשרויות חיבור.

בדף הזה נסביר על מחברי Cloud SQL הבאים:

  • מחבר Java ל-Cloud SQL
  • המחבר של Cloud SQL Python (פתיחה ב-Colab)
  • מחבר Go ל-Cloud SQL
  • מחבר Node.js של Cloud SQL

יתרונות

השימוש במחבר Cloud SQL מספק את היתרונות הבאים:

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

לפני שמתחילים

  • מפעילים את Cloud SQL Admin API.

    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

  • יצירת מכונה של Cloud SQL, כולל הגדרת משתמש ברירת המחדל.

    מידע נוסף על יצירת מופעים זמין במאמר יצירת מופעים.

    מידע נוסף על הגדרת משתמש ברירת המחדל זמין במאמר בנושא הגדרת הסיסמה לחשבון משתמש ברירת המחדל.

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

הגדרה

Java

‫Cloud SQL Java Connector היא ספרייה שמספקת הרשאה והצפנה מבוססות-IAM כשמתחברים למכונת Cloud SQL. הוא לא יכול לספק נתיב ברשת למופע Cloud SQL אם הוא לא קיים.

התקנה

הוראות ליצירה ולשימוש במנהלי התקנים עבור JDBC ו-R2DBC באמצעות מחבר Java של Cloud SQL זמינות בקישורים הבאים:

כדי לראות דוגמאות לשימוש בספרייה הזו בהקשר של אפליקציה, אפשר לעיין באפליקציות לדוגמה.

אמת

הספרייה הזו משתמשת בApplication Default Credentials כדי לאמת את החיבור לשרת Cloud SQL.

כדי להפעיל את פרטי הכניסה באופן מקומי, משתמשים בפקודה הבאה של gcloud:

    gcloud auth application-default login
    

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

כדי לקשר את IntelliJ למופע Cloud SQL, צריך להוסיף את הספרייה כקובץ JAR עם תלות בקטע Additional Files בדף ההגדרות של מנהל ההתקן. לדוגמה, קובצי JAR גדולים מוכנים מראש זמינים בדף Cloud SQL Java Connector Releases למטרה הזו.

Python

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

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

הדרייברים ש-PostgreSQL תומך בהם הם pg8000 ו-asyncpg.

התקנה

כדי להתקין את הגרסה האחרונה של Cloud SQL Python Connector, משתמשים בפקודה pip install ומציינים את מנהל ההתקנים pg8000 או asyncpg למסד הנתונים:

    pip install "cloud-sql-python-connector[pg8000]"
    

או

    pip install "cloud-sql-python-connector[asyncpg]"
    

אמת

הספרייה הזו משתמשת בApplication Default Credentials כדי לאמת את החיבור לשרת Cloud SQL.

כדי להפעיל את פרטי הכניסה באופן מקומי, משתמשים בפקודה הבאה של gcloud:

    gcloud auth application-default login
    

Go

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

התקנה

אפשר להתקין את המאגר הזה באמצעות go get:

    go get cloud.google.com/go/cloudsqlconn
    

Node.js

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

התקנה

אפשר להתקין את הספרייה באמצעות npm install:

    npm install @google-cloud/cloud-sql-connector
    

שימוש

Java

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

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 INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
  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 URL is equivalent to setting the config options below:
    // jdbc:postgresql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
    // socketFactory=com.google.cloud.sql.postgres.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:postgresql:///%s", DB_NAME));
    config.setUsername(DB_USER); // e.g. "root", _postgres"
    config.setPassword(DB_PASS); // e.g. "my-password"

    config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
    config.addDataSourceProperty("cloudSqlInstance", INSTANCE_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");

    // cloudSqlRefreshStrategy set to "lazy" is used to perform a
    // refresh when needed, rather than on a scheduled interval.
    // This is recommended for serverless environments to
    // avoid background refreshes from throttling CPU.
    config.addDataSourceProperty("cloudSqlRefreshStrategy", "lazy");

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

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

Python

הוראות מפורטות לשימוש בספרייה מופיעות במאמר How to use this Connector. אפשר לראות קוד לדוגמה של בדיקת חיבור ב-GitHub.

import os

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

import sqlalchemy


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

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

    # initialize Cloud SQL Python Connector object
    connector = Connector(refresh_strategy="LAZY")

    def getconn() -> pg8000.dbapi.Connection:
        conn: pg8000.dbapi.Connection = connector.connect(
            instance_connection_name,
            "pg8000",
            user=db_user,
            password=db_pass,
            db=db_name,
            ip_type=ip_type,
        )
        return conn

    # The Cloud SQL Python Connector can be used with SQLAlchemy
    # using the 'creator' argument to 'create_engine'
    pool = sqlalchemy.create_engine(
        "postgresql+pg8000://",
        creator=getconn,
        # ...
    )
    return pool

Go

הוראות מפורטות לשימוש בספרייה מופיעות במאמר בנושא שימוש. אפשר לראות קוד לדוגמה של בדיקת חיבור ב-GitHub.

package cloudsql

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

	"cloud.google.com/go/cloudsqlconn"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/stdlib"
)

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 passwords and other 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")
	)

	dsn := fmt.Sprintf("user=%s password=%s database=%s", dbUser, dbPwd, dbName)
	config, err := pgx.ParseConfig(dsn)
	if err != nil {
		return nil, err
	}
	var opts []cloudsqlconn.Option
	if usePrivate != "" {
		opts = append(opts, cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPrivateIP()))
	}
	// WithLazyRefresh() Option is used to perform refresh
	// when needed, rather than on a scheduled interval.
	// This is recommended for serverless environments to
	// avoid background refreshes from throttling CPU.
	opts = append(opts, cloudsqlconn.WithLazyRefresh())
	d, err := cloudsqlconn.NewDialer(context.Background(), opts...)
	if err != nil {
		return nil, err
	}
	// Use the Cloud SQL connector to handle connecting to the instance.
	// This approach does *NOT* require the Cloud SQL proxy.
	config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
		return d.Dial(ctx, instanceConnectionName)
	}
	dbURI := stdlib.RegisterConnConfig(config)
	dbPool, err := sql.Open("pgx", dbURI)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

Node.js

הוראות מפורטות לשימוש בספרייה מופיעות במאמר בנושא שימוש.

const Knex = require('knex');
const {Connector} = require('@google-cloud/cloud-sql-connector');

// In case the PRIVATE_IP environment variable is defined then we set
// the ipType=PRIVATE for the new connector instance, otherwise defaults
// to public ip type.
const getIpType = () =>
  process.env.PRIVATE_IP === '1' || process.env.PRIVATE_IP === 'true'
    ? 'PRIVATE'
    : 'PUBLIC';

// connectWithConnector initializes connection pool for a Cloud SQL instance
// of Postgres using the Cloud SQL Node.js Connector.
const connectWithConnector = 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 connector = new Connector();
  const clientOpts = await connector.getOptions({
    instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME,
    ipType: getIpType(),
  });
  const dbConfig = {
    client: 'pg',
    connection: {
      ...clientOpts,
      user: process.env.DB_USER, // e.g. 'my-user'
      password: process.env.DB_PASS, // e.g. 'my-user-password'
      database: process.env.DB_NAME, // e.g. 'my-database'
    },
    // ... Specify additional properties here.
    ...config,
  };
  // Establish a connection to the database.
  return Knex(dbConfig);
};

לאכוף

באמצעות אכיפת מחברים, אתם יכולים לאכוף שימוש רק בשרת proxy ל-Cloud SQL Auth או במחברים של Cloud SQL Language כדי להתחבר למכונות Cloud SQL. עם אכיפת מחבר, Cloud SQL דוחה חיבורים ישירים למסד הנתונים.

אם אתם משתמשים במכונה עם Private Service Connect, יש מגבלה. אם האכיפה של המחבר מופעלת במופע, אי אפשר ליצור רפליקות לקריאה עבור המופע. באופן דומה, אם למופע יש עותקים לקריאה, אי אפשר להפעיל את האכיפה של המחבר במופע.

gcloud

כדי לאכוף שימוש רק בשרת proxy ל-Cloud SQL Auth או במחברי שפות ל-Cloud SQL כדי להתחבר למכונה, משתמשים בפקודה gcloud sql instances patch:

gcloud sql instances patch INSTANCE_NAME \
--connector-enforcement=REQUIRED

מחליפים את INSTANCE_NAME בשם של מופע Cloud SQL.

REST

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

  • PROJECT_ID: המזהה או מספר הפרויקט של Google Cloud הפרויקט שמכיל את המופע
  • INSTANCE_NAME: השם של מכונת Cloud SQL

ה-method של ה-HTTP וכתובת ה-URL:

PATCH https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_NAME

תוכן בקשת JSON:

{
  "kind": "sql#instance",
  "name": INSTANCE_NAME,
  "project": PROJECT_ID,
  "settings": {
  "connectorEnforcement": "REQUIRED",
  "kind": "sql#settings"
  }
}

כדי לשלוח את הבקשה צריך להרחיב אחת מהאפשרויות הבאות:

אתם אמורים לקבל תגובת JSON שדומה לזו:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_NAME",
  "status": "PENDING",
  "user": "user@example.com",
  "insertTime": "2020-01-16T02:32:12.281Z",
  "operationType": "UPDATE",
  "name": "OPERATION_ID",
  "targetId": "INSTANCE_NAME",
  "selfLink": "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/operations/OPERATION_ID",
  "targetProject": "PROJECT_ID"
}

פתרון בעיות

גרסאות מנהלי ההתקנים

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

נתיבי המרות

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

ניפוי באגים בבעיות בחיבור

לקבלת עזרה נוספת בפתרון בעיות בחיבור, אפשר לעיין בדפים פתרון בעיות וניפוי באגים בבעיות בחיבור.

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