Как подключить приложения Java к AlloyDB для PostgreSQL с помощью аутентификации IAM

1. Подготовка

Java и AlloyDB: простое и безопасное подключение

AlloyDB для PostgreSQL – это полностью управляемый сервис баз данных Google Cloud, совместимый с PostgreSQL и предназначенный для требовательных корпоративных рабочих нагрузок. Безопасное и эффективное подключение приложения Java к AlloyDB выполняется через AlloyDB Java Connector (alloydb-jdbc-connector) – клиентскую библиотеку, которая выходит за рамки стандартного драйвера JDBC.

Магия AlloyDB Java Connector

alloydb-jdbc-connector работает как умная SocketFactory для стандартного драйвера JDBC PostgreSQL (org.postgresql:postgresql). Он абстрагирует установление безопасного подключения к базе данных, чтобы вы могли сосредоточиться на логике приложения, а не на сетевой безопасности или ротации учетных данных.

  • Шифрование mTLS 1.3. Автоматически устанавливает взаимно аутентифицированное соединение TLS 1.3 между JVM и экземпляром AlloyDB. Вам не нужно вручную управлять сертификатами клиента SSL/TLS.
  • Авторизация на основе IAM. Вместо статических паролей баз данных коннектор использует Google Cloud IAM и Application Default Credentials (ADC), чтобы автоматически получать краткосрочные токены доступа OAuth2.
  • Динамическое разрешение IP-адресов. Запрашивает AlloyDB Admin API для динамического разрешения текущего IP-адреса (PRIVATE, PUBLIC или Private Service Connect PSC) вашего экземпляра базы данных. Вам не нужно задавать в коде имена хостов или IP-адреса, что делает отработку отказа и обслуживание прозрачными.

Как работает AlloyDB Java Connector

Требования

  • Знание Java, Maven и основных концепций SQL/JDBC.
  • Базовые знания о Google Cloud CLI (gcloud) и ролях IAM.

Что вам предстоит сделать

  • Настройте экземпляр AlloyDB и сервисный аккаунт для беспарольной аутентификации базы данных IAM.
  • Предоставьте пользователю IAM минимальные привилегии для схемы и таблицы PostgreSQL.
  • Настройте DataSource промышленного уровня с помощью Plain JDBC и HikariCP, используя SocketFactory AlloyDB.
  • Интегрируйте AlloyDB Java Connector в приложения Spring Boot, Quarkus и Micronaut.
  • Зарегистрируйте AlloyDB SocketFactory для компиляции GraalVM Native Image и устраните распространенные проблемы с аутентификацией IAM.

Что вам понадобится

  • Проект Google Cloud с включенными платежными функциями и активным кластером AlloyDB и основным экземпляром (см. руководство по созданию кластера AlloyDB или запустите кластер AlloyDB Express менее чем за две секунды).
  • Роли IAM roles/alloydb.admin и roles/resourcemanager.projectIamAdmin в проекте.
  • Java 17 или более поздней версии (рекомендуется Java 17 или 21 LTS) и Apache Maven.
  • Установленный интерфейс командной строки gcloud и клиент psql (или доступ к Google Cloud Shell).

2. Как настроить аутентификацию базы данных IAM в AlloyDB

Прежде чем писать код Java, вам нужно настроить экземпляр AlloyDB так, чтобы он принимал токены IAM, и создать идентификационную информацию IAM, которую ваше приложение будет использовать на трех уровнях: Google Cloud IAM, уровень управления AlloyDB и движок PostgreSQL.

Трехуровневая настройка аутентификации базы данных AlloyDB IAM

Задайте переменные среды

В терминале экспортируйте переменные, соответствующие вашему облачному проекту Google Cloud и экземпляру AlloyDB (замените плейсхолдеры своими значениями):

export PROJECT_ID="<PROJECT_ID>"
export REGION="europe-west1"
export CLUSTER_ID="<CLUSTER_ID>"
export INSTANCE_ID="<INSTANCE_ID>"
export DB_NAME="dvdrental"

Включите необходимые API

Включите в проекте AlloyDB API, Compute Engine API, Cloud Resource Manager API, IAM API и Service Usage API.

gcloud services enable \
    alloydb.googleapis.com \
    compute.googleapis.com \
    cloudresourcemanager.googleapis.com \
    iam.googleapis.com \
    serviceusage.googleapis.com \
    --project="${PROJECT_ID}"

Создание сервисного аккаунта и назначение ролей IAM

Создайте специальный сервисный аккаунт, который будет использоваться в качестве идентификатора вашего приложения Java.

gcloud iam service-accounts create java-alloydb-connector \
    --project="${PROJECT_ID}" \
    --display-name="Java Application DB Connector"

Предоставьте сервисному аккаунту две роли IAM, необходимые для AlloyDB Java Connector:

  1. roles/alloydb.client: требуется для получения метаданных экземпляра и запроса временных сертификатов mTLS из AlloyDB Admin API.
  2. roles/serviceusage.serviceUsageConsumer – требуется для аутентификации базы данных IAM.
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:java-alloydb-connector@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/alloydb.client"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:java-alloydb-connector@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/serviceusage.serviceUsageConsumer"

Включите аутентификацию IAM в экземпляре AlloyDB

Обновите флаги экземпляра AlloyDB, чтобы задать alloydb.iam_authentication=on. Это динамический флаг, который вступает в силу немедленно без перезапуска экземпляра:

gcloud alloydb instances update "${INSTANCE_ID}" \
    --cluster="${CLUSTER_ID}" \
    --region="${REGION}" \
    --project="${PROJECT_ID}" \
    --database-flags=alloydb.iam_authentication=on

Зарегистрируйте пользователя базы данных IAM

Зарегистрируйте сервисный аккаунт как пользователя базы данных IAM_BASED в кластере AlloyDB с помощью gcloud:

gcloud alloydb users create "java-alloydb-connector@${PROJECT_ID}.iam" \
    --cluster="${CLUSTER_ID}" \
    --region="${REGION}" \
    --project="${PROJECT_ID}" \
    --type=IAM_BASED

Предоставьте разрешения для схемы и таблицы PostgreSQL

У новых пользователей базы данных IAM по умолчанию нет прав на таблицы. Подключитесь к экземпляру AlloyDB как администратор postgres (через psql или AlloyDB Studio в Cloud Console) и предоставьте доступ к целевой базе данных и таблицам (например, примеру базы данных DVD Rental):

-- Connect to your target database first
\c dvdrental

-- (Optional) Create a sample film table if your database is empty
CREATE TABLE IF NOT EXISTS public.film (
    film_id SERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    release_year INTEGER DEFAULT 2006,
    rating VARCHAR(10) DEFAULT 'PG',
    rental_rate NUMERIC(4,2) DEFAULT 2.99
);

INSERT INTO public.film (film_id, title, release_year, rating, rental_rate) VALUES
    (1, 'Academy Dinosaur', 2006, 'PG', 0.99),
    (2, 'Ace Goldfinger', 2006, 'G', 4.99),
    (3, 'Adaptation Holes', 2006, 'NC-17', 2.99),
    (4, 'Affair Prejudice', 2006, 'G', 2.99),
    (5, 'African Egg', 2006, 'G', 2.99)
ON CONFLICT (film_id) DO NOTHING;

-- Grant permissions to the IAM user (double quotes are required because of '@' and '.')
GRANT CONNECT ON DATABASE "dvdrental" TO "java-alloydb-connector@<PROJECT_ID>.iam";
GRANT USAGE ON SCHEMA public TO "java-alloydb-connector@<PROJECT_ID>.iam";
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "java-alloydb-connector@<PROJECT_ID>.iam";

При выполнении этих инструкций в AlloyDB Studio (или psql) вы можете проверить схему public.film и строки с примерами:

Предоставление разрешений IAM и проверка public.film в AlloyDB Studio

Настройте локальные Application Default Credentials (ADC)

При запуске в Cloud Run, Google Kubernetes Engine (GKE) или Compute Engine подключите сервисный аккаунт java-alloydb-connector непосредственно к рабочей нагрузке. При локальном запуске на рабочей станции выдайте себя за сервисный аккаунт, чтобы ADC создавал токены для этого идентификатора:

gcloud auth application-default login \
    --impersonate-service-account="java-alloydb-connector@${PROJECT_ID}.iam.gserviceaccount.com"

3. Подключение с помощью Plain JDBC и HikariCP

Для любого приложения Java производственного уровня необходим пул подключений, а HikariCP является отраслевым стандартом. На этом шаге вы создадите простое приложение JDBC + HikariCP, которое делегирует создание сокета com.google.cloud.alloydb.SocketFactory.

Создайте проект Maven (pom.xml)

Создайте каталог jdbc-app с файлом pom.xml, содержащим драйвер JDBC PostgreSQL (42.7.14), AlloyDB Java Connector (1.4.0) и HikariCP (7.1.0):

mkdir -p jdbc-app/src/main/java
cd jdbc-app

Создать pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example.alloydb</groupId>
    <artifactId>alloydb-jdbc-sample</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <exec.mainClass>AlloyDBConnectivity</exec.mainClass>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.7.14</version>
        </dependency>

        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>alloydb-jdbc-connector</artifactId>
            <version>1.4.0</version>
        </dependency>

        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>7.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>2.0.16</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.5.0</version>
                <configuration>
                    <cleanupDaemonThreads>false</cleanupDaemonThreads>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Создать AlloyDBConnectivity.java

Создайте файл src/main/java/AlloyDBConnectivity.java (посмотреть на GitHub Gist):

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class AlloyDBConnectivity {
    // Retrieve configuration from environment variables
    private static final String ALLOYDB_INSTANCE_URI = System.getenv("ALLOYDB_INSTANCE_NAME"); // e.g., projects/<PROJECT_ID>/locations/<REGION>/clusters/<CLUSTER_ID>/instances/<INSTANCE_ID>
    private static final String ALLOYDB_DB_NAME = System.getenv("ALLOYDB_DB"); // e.g., "dvdrental"
    private static final String ALLOYDB_USER = System.getenv("ALLOYDB_USER"); // e.g., "java-alloydb-connector@<PROJECT_ID>.iam"
    private static final String ALLOYDB_PASS = System.getenv("ALLOYDB_PASS"); // Database password if not using IAM auth

    public static HikariDataSource createDataSource() {
        HikariConfig config = new HikariConfig();

        // The JDBC URL does not need a host or port. The SocketFactory will resolve the IP address.
        config.setJdbcUrl(String.format("jdbc:postgresql:///%s", ALLOYDB_DB_NAME));
        config.setUsername(ALLOYDB_USER);

        // Only set the password if you are NOT using IAM authentication.
        if (System.getenv("ALLOYDB_ENABLE_IAM_AUTH") == null || !System.getenv("ALLOYDB_ENABLE_IAM_AUTH").equalsIgnoreCase("true")) {
            config.setPassword(ALLOYDB_PASS);
        }

        // 1. Set the SocketFactory to the AlloyDB Connector's implementation.
        config.addDataSourceProperty("socketFactory", "com.google.cloud.alloydb.SocketFactory");

        // 2. Tell the connector which AlloyDB instance to connect to.
        config.addDataSourceProperty("alloydbInstanceName", ALLOYDB_INSTANCE_URI);

        // 3. (Recommended) Enable IAM database authentication.
        if (System.getenv("ALLOYDB_ENABLE_IAM_AUTH") != null && System.getenv("ALLOYDB_ENABLE_IAM_AUTH").equalsIgnoreCase("true")) {
            config.addDataSourceProperty("alloydbEnableIAMAuth", "true");
        }

        // 4. (Optional) Specify IP type (e.g., "PRIVATE", "PUBLIC", "PSC"). Defaults to PRIVATE.
        String ipType = System.getenv("ALLOYDB_IP_TYPE");
        if (ipType != null) {
            config.addDataSourceProperty("alloydbIpType", ipType);
        }

        // Baseline HikariCP settings
        config.setMaximumPoolSize(10);
        config.setMinimumIdle(2);
        config.setConnectionTimeout(30000); // 30 seconds
        config.setIdleTimeout(600000);      // 10 minutes
        config.setMaxLifetime(1800000);     // 30 minutes

        return new HikariDataSource(config);
    }

    public static void main(String[] args) {
        String sql = "SELECT title, release_year FROM public.film ORDER BY film_id LIMIT 5";

        try (HikariDataSource pool = createDataSource();
             Connection conn = pool.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql);
             ResultSet rs = stmt.executeQuery()) {
            System.out.println("Successfully connected to AlloyDB via IAM! Sample films:");
            while (rs.next()) {
                System.out.printf(" - %s (%d)%n", rs.getString("title"), rs.getInt("release_year"));
            }
        } catch (SQLException e) {
            System.err.println("Database connection failed: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Структура URL-адреса AlloyDB JDBC и конфигурация HikariCP

Запустите приложение Plain JDBC

Экспортируйте переменные среды для экземпляра AlloyDB (установите ALLOYDB_IP_TYPE="PUBLIC", если подключение выполняется извне VPC через общедоступный IP-адрес, или "PRIVATE"/"PSC", если подключение выполняется внутри VPC) и запустите приложение:

export ALLOYDB_INSTANCE_NAME="projects/${PROJECT_ID}/locations/${REGION}/clusters/${CLUSTER_ID}/instances/${INSTANCE_ID}"
export ALLOYDB_DB="${DB_NAME}"
export ALLOYDB_USER="java-alloydb-connector@${PROJECT_ID}.iam"
export ALLOYDB_ENABLE_IAM_AUTH="true"
export ALLOYDB_IP_TYPE="PRIVATE" # Set to PUBLIC if connecting over Public IP from a local laptop

mvn compile exec:java

Вы должны увидеть примерно следующее:

[AlloyDBConnectivity.main()] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
[AlloyDBConnectivity.main()] INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@1998bf07
[AlloyDBConnectivity.main()] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
Successfully connected to AlloyDB via IAM! Sample films:
 - Academy Dinosaur (2006)
 - Ace Goldfinger (2006)
 - Adaptation Holes (2006)
 - Affair Prejudice (2006)
 - African Egg (2006)

Вывод терминала для примера с Plain JDBC и HikariCP

4. Подключение с помощью Spring Boot

Spring Boot упрощает подключение к базе данных, автоматически настраивая пул подключений HikariCP на основе свойств приложения. Для интеграции AlloyDB Java Connector не требуется пользовательский код компонента DataSource.

Создайте проект Spring Boot (pom.xml)

Создайте каталог spring-boot-app:

cd ..
mkdir -p spring-boot-app/src/main/java/com/example/alloydb
mkdir -p spring-boot-app/src/main/resources
cd spring-boot-app

Создайте pom.xml с помощью spring-boot-starter-jdbc (включает HikariCP), org.postgresql:postgresql и com.google.cloud:alloydb-jdbc-connector:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.0.5</version>
        <relativePath/>
    </parent>

    <groupId>com.example.alloydb</groupId>
    <artifactId>alloydb-spring-boot-sample</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>17</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.7.14</version>
        </dependency>

        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>alloydb-jdbc-connector</artifactId>
            <version>1.4.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Настройте application.properties или переменные среды

Вы можете настроить URL подключения в src/main/resources/application.properties:

# No host or port is needed; the SocketFactory handles it.
spring.datasource.url=jdbc:postgresql:///dvdrental?socketFactory=com.google.cloud.alloydb.SocketFactory&alloydbInstanceName=projects/<PROJECT_ID>/locations/<REGION>/clusters/<CLUSTER_ID>/instances/<INSTANCE_ID>&alloydbEnableIAMAuth=true
spring.datasource.username=java-alloydb-connector@<PROJECT_ID>.iam
# No password required when alloydbEnableIAMAuth is true

Чтобы в исходных файлах не было идентификаторов проектов и названий экземпляров, оставьте файл application.properties пустым и укажите следующие стандартные переменные среды Spring Boot во время выполнения:

Переменная среды

Значение

SPRING_DATASOURCE_URL

jdbc:postgresql:///dvdrental?socketFactory=com.google.cloud.alloydb.SocketFactory&alloydbInstanceName=projects//locations//clusters//instances/&alloydbEnableIAMAuth=true

SPRING_DATASOURCE_USERNAME

java-alloydb-connector@.iam

Создать AlloyDbTestApplication.java

Создайте файл src/main/java/com/example/alloydb/AlloyDbTestApplication.java (посмотреть на GitHub Gist):

package com.example.alloydb;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;

@SpringBootApplication
public class AlloyDbTestApplication {

    public static void main(String[] args) {
        System.exit(SpringApplication.exit(SpringApplication.run(AlloyDbTestApplication.class, args)));
    }

    @Bean
    CommandLineRunner testConnection(JdbcTemplate jdbcTemplate) {
        return args -> {
            String result = jdbcTemplate.queryForObject("SELECT 'Connection Successful!'", String.class);
            System.out.println(">>> ALLOYDB STATUS: " + result);
        };
    }
}

Запустите приложение Spring Boot

Экспортируйте переменные среды и запустите приложение с помощью mvn spring-boot:run:

export SPRING_DATASOURCE_URL="jdbc:postgresql:///${DB_NAME}?socketFactory=com.google.cloud.alloydb.SocketFactory&alloydbInstanceName=projects/${PROJECT_ID}/locations/${REGION}/clusters/${CLUSTER_ID}/instances/${INSTANCE_ID}&alloydbEnableIAMAuth=true"
export SPRING_DATASOURCE_USERNAME="java-alloydb-connector@${PROJECT_ID}.iam"

mvn spring-boot:run

Вы должны увидеть:

>>> ALLOYDB STATUS: Connection Successful!

Автоматическая настройка Spring Boot и вывод данных в реальном времени

5. Подключение с помощью Quarkus, Micronaut и GraalVM Native Image

Поскольку AlloyDB Java Connector работает на уровне драйвера JDBC, переключение между облачными фреймворками Java не влияет на то, как вы защищаете трафик базы данных или управляете идентификационными данными. Quarkus и Micronaut упаковывают базовый драйвер JDBC и делегируют шифрование mTLS, динамическое разрешение IP-адресов и аутентификацию IAM коннектору через ADC.

Облачные фреймворки Java и нативный образ GraalVM с AlloyDB

Конфигурация Quarkus (application.properties с Agroal)

В приложении Quarkus (quarkus-agroal и quarkus-jdbc-postgresql) добавьте com.google.cloud:alloydb-jdbc-connector:1.4.0 в зависимости и передайте параметры коннектора через quarkus.datasource.jdbc.additional-jdbc-properties в src/main/resources/application.properties:

quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=java-alloydb-connector@<PROJECT_ID>.iam
quarkus.datasource.jdbc.url=jdbc:postgresql:///dvdrental
quarkus.datasource.jdbc.additional-jdbc-properties.socketFactory=com.google.cloud.alloydb.SocketFactory
quarkus.datasource.jdbc.additional-jdbc-properties.alloydbInstanceName=projects/<PROJECT_ID>/locations/<REGION>/clusters/<CLUSTER_ID>/instances/<INSTANCE_ID>
quarkus.datasource.jdbc.additional-jdbc-properties.alloydbEnableIAMAuth=true

Конфигурация Micronaut (application.yml с HikariCP)

В приложении Micronaut (micronaut-jdbc-hikari) добавьте com.google.cloud:alloydb-jdbc-connector:1.4.0 и настройте src/main/resources/application.yml:

datasources:
  default:
    url: jdbc:postgresql:///dvdrental?socketFactory=com.google.cloud.alloydb.SocketFactory&alloydbInstanceName=projects/<PROJECT_ID>/locations/<REGION>/clusters/<CLUSTER_ID>/instances/<INSTANCE_ID>&alloydbEnableIAMAuth=true
    username: java-alloydb-connector@<PROJECT_ID>.iam
    driver-class-name: org.postgresql.Driver

Регистрация коннектора для GraalVM Native Image

При компиляции приложения в GraalVM Native Image (с Spring Boot 3+, Quarkus или Micronaut) есть одна важная деталь: Reflection.

Драйвер JDBC PostgreSQL динамически создает экземпляр com.google.cloud.alloydb.SocketFactory по имени класса с помощью рефлексии. Чтобы статический анализ GraalVM не удалил класс во время нативной компиляции, зарегистрируйте его явным образом:

  • Spring Boot 3+: добавьте @RegisterReflectionForBinding(com.google.cloud.alloydb.SocketFactory.class) в основное приложение или класс @Configuration:
    @SpringBootApplication
    @RegisterReflectionForBinding(com.google.cloud.alloydb.SocketFactory.class)
    public class AlloyDbTestApplication { ... }
    
  • Quarkus. Добавьте @RegisterForReflection(targets = com.google.cloud.alloydb.SocketFactory.class) в основной класс или bean-компонент CDI:
    @QuarkusMain
    @RegisterForReflection(targets = com.google.cloud.alloydb.SocketFactory.class)
    public class QuarkusAlloyDbApp implements QuarkusApplication { ... }
    

6. Устранение распространенных проблем с IAM и подключением

Если вы столкнулись с ошибкой FATAL: password authentication failed for user или AlloyDB IAM authentication failed, проверьте следующее:

Памятка по устранению неполадок с IAM и подключением в AlloyDB

1. Удалить .gserviceaccount.com из списка имен пользователей базы данных сервисного аккаунта

Самая частая причина ошибок аутентификации IAM – передача полного адреса электронной почты сервисного аккаунта в качестве имени пользователя базы данных. AlloyDB форматирует имена пользователей базы данных IAM по-разному в зависимости от типа субъекта:

  • Для сервисных аккаунтов IAM (удалите .gserviceaccount.com). Если адрес электронной почты вашего сервисного аккаунта Google Cloud – java-alloydb-connector@.iam.gserviceaccount.com, вам необходимо удалить суффикс .gserviceaccount.com и указать в качестве имени пользователя базы данных JDBC/AlloyDB java-alloydb-connector@.iam.
  • Для аккаунтов или групп пользователей IAM (сохраните полный адрес электронной почты). Если вы проходите аутентификацию как пользователь Google Workspace или Cloud Identity, используйте полный адрес электронной почты без изменений (например, ).

2. Проверьте, как был создан пользователь базы данных

Вы зарегистрировали пользователя через gcloud alloydb users create --type=IAM_BASED (или Console/Terraform)? Создание пользователя с помощью необработанного SQL-запроса CREATE USER не будет работать для аутентификации IAM, поскольку AlloyDB ограничивает GRANT alloydbiamuser уровнем управления.

3. Подтвердите активную идентификационную информацию ADC

Убедитесь, что среда, в которой выполняется процесс Java, аутентифицирована как целевой субъект IAM:

  • Локальная рабочая станция (подключение в качестве сервисного аккаунта). Выполните команду gcloud auth application-default login --impersonate-service-account=java-alloydb-connector@.iam.gserviceaccount.com, чтобы ADC создавал токены для сервисного аккаунта, а не для вашего личного адреса электронной почты.
  • Cloud Run/GKE. Убедитесь, что сервисный аккаунт прикреплен к рабочей нагрузке и имеет роли roles/alloydb.client и roles/serviceusage.serviceUsageConsumer.

4. Учет распространения IAM и сетевой маршрутизации

  • Задержка распространения IAM. Привязка правил IAM может занять 60–120 секунд. Если вы только что создали сервисный аккаунт или привязку роли, подождите минуту и повторите попытку.
  • Доступ к сети VPC. По умолчанию коннектор AlloyDB Java подключается к IP-адресу PRIVATE экземпляра. Если ваше приложение работает в Cloud Run, настройте прямой исходящий трафик VPC (рекомендуется для снижения задержки и затрат по сравнению с устаревшими коннекторами бессерверного доступа к VPC) или подключитесь через Private Service Connect (PSC). Если вы подключаетесь с локального компьютера за пределами VPC, включите общедоступный IP-адрес в экземпляре и передайте alloydbIpType=PUBLIC.

7. Организовать

Чтобы избежать ненужных расходов в аккаунте Google Cloud и удалить идентификационные данные IAM, созданные во время этой практической работы, очистите ресурсы, указанные ниже.

1. Как удалить пользователя базы данных IAM и сервисный аккаунт AlloyDB

Удалите пользователя базы данных IAM из кластера AlloyDB и удалите сервисный аккаунт:

# Delete the IAM database user from AlloyDB
gcloud alloydb users delete "java-alloydb-connector@${PROJECT_ID}.iam" \
    --cluster="${CLUSTER_ID}" \
    --region="${REGION}" \
    --project="${PROJECT_ID}" \
    --quiet

# Remove IAM policy bindings
gcloud projects remove-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:java-alloydb-connector@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/alloydb.client"

gcloud projects remove-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:java-alloydb-connector@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/serviceusage.serviceUsageConsumer"

# Delete the Service Account
gcloud iam service-accounts delete \
    "java-alloydb-connector@${PROJECT_ID}.iam.gserviceaccount.com" \
    --project="${PROJECT_ID}" \
    --quiet

2. Сбросить Application Default Credentials для локального приложения

Если вы настроили локальную имитацию ADC, сбросьте локальные учетные данные до идентификатора пользователя по умолчанию:

gcloud auth application-default login

3. Удаление кластера AlloyDB (необязательно)

gcloud alloydb clusters delete "${CLUSTER_ID}" \
    --region="${REGION}" \
    --project="${PROJECT_ID}" \
    --force \
    --quiet

8. Поздравляю!

Вы завершили практическую работу и установили безопасное беспарольное подключение Java к AlloyDB для PostgreSQL.

Что вы сделали

  1. Настроили аутентификацию базы данных IAM. Создали сервисный аккаунт с минимальными привилегиями, включили alloydb.iam_authentication=on, зарегистрировали пользователя IAM в кластере AlloyDB и предоставили привилегии таблицы PostgreSQL.
  2. Подключение с помощью Plain JDBC и HikariCP. Настройте HikariConfig с помощью com.google.cloud.alloydb.SocketFactory для автоматического шифрования mTLS 1.3, обновления токена IAM и динамического разрешения IP-адресов.
  3. Интегрированные облачные фреймворки. Настроены Spring Boot, Quarkus (Agroal) и Micronaut (HikariCP) без стандартного кода пула подключений, а также подсказки по рефлексии для GraalVM Native Image.
  4. Освоили устранение неполадок IAM. Вы научились диагностировать проблемы с форматированием имени пользователя, олицетворением ADC и маршрутизацией VPC.

Подробнее