启动 PGAdapter

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

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

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

准备工作

在启动 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、--expos)

-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

您不能将 PGAdapter 部署为独立服务 Cloud Run,但您可以将其部署为边车代理。

建议在 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
          

Sidecar 代理

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

与将 PGAdapter 作为单独的服务运行相比,建议在 Sidecar 模式下运行 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. <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-spanner-pgadapter</artifactId>
      <version>0.39.0</version>
    </dependency>
  • 使用 com.google.cloud.spanner.pgadapter.ProxyServer 类构建一个服务器。
  • /**
      * 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 代码库包含一个完整的示例应用

    后续步骤