启动 PGAdapter

本页介绍了如何在 Spanner 中启动 PGAdapter。如需了解 PGAdapter,请参阅 关于 PGAdapter。如需获取 PGAdapter 二进制文件,请参阅获取 PGAdapter

您可以通过以下方式启动 PGAdapter:

  • 作为独立进程
  • 在 Docker 容器中
  • 在 Cloud Run 上
  • 将 PGAdapter 用作边车代理(例如在 Kubernetes 集群中)
  • 在 Java 应用进程中

准备工作

在启动 PGAdapter 之前,请确保您已在将要运行 PGAdapter 的机器上使用用户账号或服务账号进行身份验证。如果您使用的是服务账号,则必须知道 JSON 密钥文件(凭据文件)的位置。然后,您可以使用 PGAdapter -c 选项或通过设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量来指定凭据路径。

如需了解详情,请参阅以下主题:

选择运行 PGAdapter 的方法

您可以将 PGAdapter 作为独立进程启动、在 Docker 容器内启动、在 Cloud Run 上启动,或者是在 Java 应用的进程内启动。启动 PGAdapter 时,您需要指定要连接到的项目、Spanner 实例和数据库。您还可以指定 JSON 格式的凭据文件(密钥文件)的路径。

独立

使用以下命令下载 PGAdapter。

    wget https://storage.googleapis.com/pgadapter-jar-releases/pgadapter.tar.gz \
    && tar -xzvf pgadapter.tar.gz
    

使用以下命令启动 PGAdapter。

    java -jar pgadapter.jar -p PROJECT_NAME -i INSTANCE_NAME -d DATABASE_NAME \
    -c CREDENTIALS_FILE_PATH \
    ADDITIONAL_OPTIONS
    

以下选项为必需:

-p project_name
Spanner 数据库在其中运行的项目的名称。
-i instance_name
Spanner 实例的名称。
-d database_name
要连接到的数据库的名称。

以下选项为可选:

-r databaseRole=database_role
要为会话使用的数据库角色。 如需了解详情,请参阅使用 PGAdapter 进行授权
-c credentials_file_path
包含 JSON 格式的服务账号凭据的密钥文件完整路径。如果未设置此选项,则系统会从 GOOGLE_APPLICATION_CREDENTIALS 环境变量指定的路径中读取凭据。

如需了解如何创建服务账号并下载 JSON 格式的密钥文件,请参阅 创建服务账号

请确保您向服务账号授予足够的凭据,以允许其访问数据库。

如果您先使用以下命令通过 Google Cloud CLI 进行身份验证,则可以省略此选项:

gcloud auth application-default login

如需了解详情,请参阅 设置身份验证和授权

-s port
PGAdapter 侦听的端口。默认为 5432(即默认的 PostgreSQL 端口)。
-v version_number

要在连接过程中公开给客户端的 PostgreSQL 的版本号。默认值为 14.1

某些 PostgreSQL 应用和驱动程序会根据此版本号启用额外的功能。Spanner 可能并不支持这些功能。 如需查看受支持的客户端的完整列表,请参阅 驱动程序和客户端

-x

启用 localhost 以外的主机发起的连接。在独立模式下启动 PGAdapter 时,请勿使用此项。只有在 Docker 容器内启动时才能使用。

默认情况下,出于安全考虑,PGAdapter 仅接受 localhost 发起的连接。

以下示例使用默认的应用凭据在端口 5432 上以独立模式启动 PGAdapter。

java -jar pgadapter.jar \
-p my-project \
-i my-instance \
-d my-database \
-s 5432

Docker

使用以下命令启动 PGAdapter。

docker run -d -p HOST-PORT:DOCKER-PORT \
-v CREDENTIALS_FILE_PATH:/acct_credentials.json \
gcr.io/cloud-spanner-pg-adapter/pgadapter:latest \
-p PROJECT_NAME -i INSTANCE_NAME -d DATABASE_NAME  \
-c /acct_credentials.json -x OTHER_PGAdapter_OPTIONS

除了用于指定项目、实例、数据库和凭据的 PGAdapter 选项之外,还需要使用以下选项:

-p 127.0.0.1:HOST-PORT:DOCKER-PORT

此 Docker 选项会将 Docker 容器内部的端口 DOCKER-PORT 映射到容器外部的端口 HOST-PORTDOCKER-PORT 必须与 PGAdapter 在容器内部的配置方式相匹配。默认值为 5432。HOST-PORT 是 Docker 应在容器外部侦听连接请求的端口。它必须始终是 localhost 上的可用端口。

如需了解详情,请参阅 Docker 文档中的 发布或公开端口(-p、--expose)

-v CREDENTIALS_FILE_PATH:in_container_mount_point

此 Docker 选项绑定会装载一个共享卷。它将容器外部的主机路径映射到容器内的一个卷(装载点)。主机路径和容器路径之间使用英文冒号 (:) 分隔。

通过此选项,PGAdapter 可以访问容器之外的 JSON 凭据文件。在前面的示例中,-c 选项引用容器内的装载点。此示例将容器内装载点命名为 /acct_credentials.json。您可以随意为其命名。

如需了解详情,请参阅 Docker 文档中的卷(共享文件系统)

-x

启用 localhost 以外的主机发起的连接。之所以需要这样做,是因为映射到主机端口的容器内部端口不会对 PGAdapter 显示为 localhost。

以下选项为可选:

-r databaseRole=database_role
要为会话使用的数据库角色。 如需了解详情,请参阅使用 PGAdapter 进行授权

在以下示例中,Docker 端口和主机端口均设置为 PostgreSQL 数据库服务默认端口 5432。

docker run -d -p 127.0.0.1:5432:5432 \
-v /tmp/credentials.json:/acct_credentials.json \
gcr.io/cloud-spanner-pg-adapter/pgadapter:latest \
-p my_project -i my_instance -d my_database \
-c /acct_credentials.json -x

Cloud Run

您无法在 Cloud Run 上将 PGAdapter 部署为独立服务,但可以将其部署为边车代理。

建议以 Sidecar 模式运行 PGAdapter,而不是将其作为单独的服务运行,原因如下:
  • 防止单点故障。每个应用对数据库的访问都独立于其他应用,从而提高其弹性。
  • PGAdapter 实例的数量会自动与应用实例数量成线性比例关系。

PGAdapter GitHub 代码库包含多种 使用 Cloud Run 和 PGAdapter 作为边车代理的有效示例应用,适用于各种编程语言。

以下配置文件展示了如何将 PGAdapter 添加为 Cloud Run 的边车代理:

  apiVersion: serving.knative.dev/v1
  kind: Service
  metadata:
  annotations:
    # This example uses an in-memory volume for Unix domain sockets.
    # This is a Cloud Run beta feature.
    run.googleapis.com/launch-stage: BETA
  name: pgadapter-sidecar-example
  spec:
  template:
    metadata:
      annotations:
        run.googleapis.com/execution-environment: gen1
        # This registers 'pgadapter' as a dependency of 'app' and ensures that pgadapter starts
        # before the app container.
        run.googleapis.com/container-dependencies: '{"app":["pgadapter"]}'
    spec:
      # Create an in-memory volume that can be used for Unix domain sockets.
      volumes:
        - name: sockets-dir
          emptyDir:
            # This directory contains the virtual socket files that are used to
            # communicate between your application and PGAdapter.
            sizeLimit: 50Mi
            medium: Memory
      containers:
        # This is the main application container.
        - name: app
          # Example: europe-north1-docker.pkg.dev/my-test-project/cloud-run-source-deploy/pgadapter-sidecar-example
          image: MY-REGION.pkg.dev/MY-PROJECT/cloud-run-source-deploy/pgadapter-sidecar-example
          # The PGADAPTER_HOST variable is set to point to /sockets, which is the shared in-memory
          # volume that is used for Unix domain sockets.
          env:
            - name: SPANNER_PROJECT
              value: my-project
            - name: SPANNER_INSTANCE
              value: my-instance
            - name: SPANNER_DATABASE
              value: my-database
            - name: PGADAPTER_HOST
              value: /sockets
            - name: PGADAPTER_PORT
              value: "5432"
          ports:
            - containerPort: 8080
          volumeMounts:
            - mountPath: /sockets
              name: sockets-dir
        # This is the PGAdapter sidecar container.
        - name: pgadapter
          image: gcr.io/cloud-spanner-pg-adapter/pgadapter
          volumeMounts:
            - mountPath: /sockets
              name: sockets-dir
          args:
            - -dir /sockets
            - -x
          # Add a startup probe that checks that PGAdapter is listening on port 5432.
          startupProbe:
            initialDelaySeconds: 10
            timeoutSeconds: 10
            periodSeconds: 10
            failureThreshold: 3
            tcpSocket:
              port: 5432
  

边车代理

例如,您可以在 Kubernetes 集群中将 PGAdapter 用作 Sidecar 代理。Kubernetes 边车容器与 pod 中的主容器并行运行。

建议以辅助程序模式运行 PGAdapter,而不是将其作为单独的服务运行,原因如下:

  • 防止单点故障。每个应用对数据库的访问都独立于其他应用,从而提高其弹性。
  • 由于 PGAdapter 会根据用量以线性方式使用资源,因此此模式可让您更准确地确定资源范围并请求资源以匹配应用扩缩情况。

以下配置文件展示了如何将 PGAdapter 添加为 Kubernetes 集群的边车代理:

containers:
- name: pgadapter
image: gcr.io/cloud-spanner-pg-adapter/pgadapter
ports:
  - containerPort: 5432
args:
  - "-p my-project"
  - "-i my-instance"
  - "-d my-database"
  - "-x"
resources:
  requests:
    # PGAdapter's memory use scales linearly with the number of active
    # connections. Fewer open connections will use less memory. Adjust
    # this value based on your application's requirements.
    memory: "512Mi"
    # PGAdapter's CPU use scales linearly with the amount of IO between
    # the database and the application. Adjust this value based on your
    # application's requirements.
    cpu: "1"

PGAdapter GitHub 代码库包含分步指南和示例应用。 此示例包含有关如何将 适用于 GKE 的工作负载身份联合与 PGAdapter 搭配使用的说明。

Java 进程内

使用您的 Java 代码创建并启动 PGAdapter 实例。这是适用于 Java 应用的推荐设置。

如果您使用的是服务账号进行身份验证,请确保将 GOOGLE_APPLICATION_CREDENTIALS 环境变量设置为凭据文件的路径。

  1. google-cloud-spanner-pgadapter 作为依赖项添加到您的项目中。如需了解详情,请参阅获取 PGAdapter
  2. 使用 com.google.cloud.spanner.pgadapter.ProxyServer 类构建一个服务器。
  3. /**
    * Starts PGAdapter in-process and returns a reference to the server. Use this reference to
    * gracefully shut down the server when your application shuts down.
    *
    * @param project the Google Cloud project that PGAdapter should connect to
    * @param instance the Spanner instance that PGAdapter should connect to
    * @param credentialsFile the full path of a credentials file that PGAdapter should use, or 
    *     null if PGAdapter should use the application default credentials
    */
    static Server startPGAdapter(String project, String instance, String credentialsFile) {
    OptionsMetadata.Builder builder =
        OptionsMetadata.newBuilder()
            .setProject(project)
            .setInstance(instance)
            // Start PGAdapter on any available port.
            .setPort(0);
    if (credentialsFile != null) {
      builder.setCredentialsFile(credentialsFile);
    }
    ProxyServer server = new ProxyServer(builder.build());
    server.startServer();
    server.awaitRunning();
    
    return new PGAdapter(server);
    }

PGAdapter GitHub 代码库包含一个完整的示例应用

后续步骤