为 Kubernetes 上的 Spanner Omni 创建多集群部署

本文档介绍如何在多个 Kubernetes 集群中设置 Spanner Omni 部署。您可以部署 Spanner Omni,无论是否使用 TLS 加密。如果您使用加密,则 Spanner Omni 会使用传输层安全 (TLS) 1.3 对部署内部以及与客户端之间的通信进行加密和身份验证。

不使用 TLS 加密的部署存在以下安全风险:

  • 如果任何人可以访问部署的 IP 地址,则可以访问该部署。
  • 客户端与服务器之间或 pod 之间没有网络加密。

由于存在这些风险,请避免在生产环境中使用未配置 TLS 加密的部署。

Spanner Omni 的 预览版 不支持 TLS 加密,并且会在您 创建部署 90 天后停止写入数据。如需提前访问具有完整功能的版本, 请与 Google 联系

准备工作

如需为部署做准备,请满足以下要求:

  • 在部署的每个位置创建多个 Kubernetes 集群。 如果您仅在该集群中的一个可用区进行部署,则集群可以是可用区级的。 Spanner Omni 支持针对 Google Kubernetes Engine (GKE) 和 Amazon Elastic Kubernetes Service (Amazon EKS) 环境的 Helm 图表配置。其他环境可能需要自定义配置。

  • 获取对 Artifact Registry 中托管的容器映像的访问权限。

  • 安装和配置 kubectl 命令行工具Helm

  • 如果您在 vSphere 虚拟化平台机器上设置 Kubernetes 环境,请通过将 monitor_control.virtual_rdtsc = FALSE 添加到虚拟机的 .vmx 配置文件来停用时间戳计数器 (TSC) 虚拟化。这有助于 TrueTime 正常运行。

  • 配置 Kubernetes 集群网络,以便一个集群中的 pod 可以与另一个集群中的 pod 连接。默认情况下,Spanner Omni 使用 TCP 端口 15000 到 15025 进行内部通信。如需在这两个集群中的 pod 之间启用通信,请打开这些端口以进行流量传输。

  • 配置集群 DNS,以将 pod 的主机名(例如 spanner-a-0.pod.spanner-ns-r1)解析为其 IP 地址。 Spanner Omni 需要主机名解析,以便在不同集群中的 pod 之间建立 TCP 连接。

准备 Helm 图表配置

创建 Helm 配置。如需了解详情,请参阅 创建 Helm 配置

每个可用区的根服务器数量必须是介于 1 到 9 之间的奇数(含 1 和 9),以确保一致性仲裁。如果服务器数量是偶数,部署可能会失败。配置可用区时,请将服务器指定为根服务器。我们建议您在开发或测试时使用 1 个,在具有高可用性的生产可用区中使用 3 个。

由于这是多集群部署,请确保您的 Helm 配置 YAML 文件包含以下内容:

# This is required for a multi-cluster deployment setup.

deployment:
  multiCluster: true

多集群部署的 Helm 图表示例配置

以下是为 Spanner Omni 多集群部署配置的 Helm 图表示例。此配置会在三个区域(us-west1us-west2us-west3)中创建一个部署。 Google Cloud 该部署分布在五个可用区中,每个可用区代表一个副本。us-west1us-west2 中的副本是读写副本,而 us-west3 中的单个副本是见证者副本。

# The platform of the deployment
global:
  platform: gke

# This is required for a multi-cluster deployment setup.
deployment:
  multiCluster: true

# Locations and zones where clusters are created for the deployment
locations:
  - name: us-west1
    namespace: spanner-ns-usw1
    zones:
      - name: "us-west1-a"
        shortName: "a"
      - name: "us-west1-b"
        shortName: "b"
  - name: us-west2
    namespace: spanner-ns-usw2
    zones:
      - name: "us-west2-a"
        shortName: "a"
      - name: "us-west2-b"
        shortName: "b"
  - name: us-west3
    namespace: spanner-ns-usw3
    zones:
      - name: "us-west3-a"
        shortName: "a"
        replicaType: WITNESS

# Remaining configuration like storage, resources, isn't included in this sample.

配置 kubectl 以连接到多个集群

在继续操作之前,请使用 kubectl 上下文创建集群。例如,在您的 Helm 配置 YAML 文件中,您可以 根据位置命名上下文,例如 ctx-usw1ctx-usw2ctx-usw3

配置 TLS 加密

如果您要设置不使用加密的部署,请跳至 为每个集群安装 Helm 图表

如需在多集群部署中配置 TLS 加密,您必须创建证书授权机构 (CA),并为每个集群生成证书。如需了解详情,请参阅 向 Kubernetes 部署添加 TLS 加密

生成证书

为服务器和 API 创建 CA 和证书。服务器和 API 证书必须包含来自所有集群的主机。

创建 Spanner Omni 服务器证书

Spanner Omni 服务器使用服务器证书对服务器间通信进行加密。

如需创建服务器证书,请运行以下命令。将 SERVER_LIST替换为 Spanner Omni 服务器 pod FQDN 的英文逗号分隔列表,或使用通配符。

SERVER_NAMES=*.pod.spanner-ns-usw1,*.pod.spanner-ns-usw2,*.pod.spanner-ns-usw3
Spanner Omni CLI certificates create-server --hostnames=${SERVER_NAMES} --ca-certificate-directory certs --output-directory certs

创建 API 证书

API 证书会对与部署交互的系统的通信进行加密。

如需创建 API 证书,请运行以下命令。将 OMNI_ENDPOINT 替换为每个集群的服务端点。

OMNI_ENDPOINT=spanner.spanner-ns-usw1,spanner.spanner-ns-usw2,spanner.spanner-ns-usw3
Spanner Omni CLI certificates create-server --filename-prefix=api --hostnames=${OMNI_ENDPOINT} --ca-certificate-directory certs --output-directory certs

将证书推送到每个 Kubernetes 集群

对于每个集群,创建命名空间和一个包含证书的通用 Secret。

# Repeat for each context (for example, ctx-usw1, ctx-usw2, ctx-usw3)
# Replace NAMESPACE with the appropriate namespace for each region

kubectl create namespace <var>NAMESPACE</var> --context <var>CONTEXT</var>
kubectl create secret generic tls-certs \
  --from-file=ca.crt="certs/ca.crt" \
  --from-file=ca-api.crt="certs/ca-api.crt" \
  --from-file=server.crt="certs/server.crt" \
  --from-file=server.key="certs/server.key" \
  --from-file=api.crt="certs/api.crt" \
  --from-file=api.key="certs/api.key" \
  -n <var>NAMESPACE</var> \
  --context <var>CONTEXT</var>

为每个集群安装 Helm 图表

创建 Helm 配置。如需了解详情,请参阅 创建 Helm 配置

对于多集群部署,请将 Helm 配置文件中的 Helm 图表配置应用于每个 Kubernetes 集群。在每个命令中,以特定位置及其命名空间为目标,将其绑定到 Spanner Omni 部署。按照 Helm 配置文件中列出的相同顺序将配置应用于每个位置。当您将配置应用于最终位置时,系统会在该集群中创建一个部署启动作业。

在为每个集群安装 Helm 之前,请在计划托管可观测性堆栈的集群上创建监控命名空间:

kubectl create namespace monitoring --context ctx-usw1

Helm 图表安装命令示例

以下命令会在集群上安装 Helm 图表。在每个命令中, PATH_TO_HELM_CONFIG_FILE 是您为部署创建的 Helm 图表配置 YAML 文件的路径。

us-west1 中安装启用了监控的图表

helm upgrade --install spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni --version 0.2.0 \
  -f PATH_TO_HELM_CONFIG_FILE \
  --namespace spanner-ns-usw1 \
  --set currentLocation=us-west1 \
  --set monitoring.enabled=true \
  --create-namespace \
  --kube-context ctx-usw1

us-west2 中安装未启用监控的图表

helm upgrade --install spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni --version 0.2.0 \
  -f  PATH_TO_HELM_CONFIG_FILE \
  --namespace spanner-ns-usw2 \
  --set currentLocation=us-west2 \
  --create-namespace \
  --kube-context ctx-usw2

us-west3 中安装未启用监控的图表

helm upgrade --install spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni --version 0.2.0 \
  -f  PATH_TO_HELM_CONFIG_FILE \
  --namespace spanner-ns-usw3 \
  --set currentLocation=us-west3 \
  --create-namespace \
  --kube-context ctx-usw3

跟踪部署进度

应用 Helm 图表配置后,每个 Kubernetes 集群中都会启动一个启动作业。在最后一个集群中启动启动作业后,运行以下命令以跟踪部署过程:

kubectl logs -n spanner-ns-usw3 -l app.kubernetes.io/component=bootstrap -f

如果日志表明部署无法访问所有服务器,请确保每个 集群上的 DNS 服务配置正确

配置集群 DNS 服务

如果您将外部 DNS 与 Kubernetes 集群搭配使用,并且该 DNS 管理无头服务的 DNS 条目,则可以跳过此步骤。

Spanner 将 pod 主机名用于所有内部通信。 配置 DNS,以便 pod 即使在不同的 Kubernetes 集群中运行,也可以解析主机名。为此,请在每个集群中公开 kube-dns 服务,以便其他集群可以通过运行 dns-setup.sh 脚本来访问该服务。

此脚本会在每个集群中为 kube-dns 应用部署负载均衡器服务,并更新 DNS 配置以指向负载均衡器服务。虽然 dns-setup.sh 会在 GKE 和 Amazon EKS 中配置 kube-dnsCoreDNS,但您可能需要针对您的环境进行配置。

如需配置集群 DNS 服务,请执行以下操作:

  1. 如果尚未下载 dns-setup.sh 脚本,请从 spanner-omni Cloud Storage 存储桶下载。

    前往 Spanner Omni 存储桶

  2. 运行 dns-setup.sh 脚本:

    dns-setup.sh -n CSV_NAME_SPACE_LIST CONTEXTS
    
    • CSV_NAME_SPACE_LIST 替换为您的 命名空间的英文逗号分隔列表。

    • CONTEXTS 替换为上下文列表。

    以下是使用 dns-setup.sh 脚本的示例:

    dns-setup.sh -n spanner-ns-usw1,spanner-ns-usw2,spanner-ns-usw3 ctx-usw1 ctx-usw2 ctx-usw3
    

运行脚本后,检查部署作业的日志。消息表明部署正在进行中,并显示 Deployment created successfully 消息。

更新 API 证书

如果您要设置不使用 TLS 加密的部署,请继续与 Spanner Omni 交互

如需实现 TLS 加密,您必须使用每个集群的负载平衡器的外部 IP 地址或 DNS 名称更新 API 证书。这可确保客户端可以通过安全通道连接到部署。

  1. 获取每个集群的服务详细信息:

    kubectl get service spanner -n spanner-ns-usw1 --context ctx-usw1
    kubectl get service spanner -n spanner-ns-usw2 --context ctx-usw2
    kubectl get service spanner -n spanner-ns-usw3 --context ctx-usw3
    
  2. 使用外部 IP 地址更新 API 证书:

    # Replace <var>EXTERNAL_IP_USW1</var>, <var>EXTERNAL_IP_USW2</var>, and <var>EXTERNAL_IP_USW3</var>
    # with the actual external IP addresses or DNS names.
    
    OMNI_ENDPOINT=<var>EXTERNAL_IP_USW1</var>,<var>EXTERNAL_IP_USW2</var>,<var>EXTERNAL_IP_USW3</var>,spanner.spanner-ns.svc
    Spanner Omni CLI certificates update --filename_prefix=api --hostnames=${OMNI_ENDPOINT} --ca-certificate-directory certs --output_directory certs --overwrite
    
  3. 使用新的 API 证书更新每个 Kubernetes 集群中的 Secret:

    # Repeat for each context
    kubectl patch secret tls-certs -n spanner-ns-usw1 --context ctx-usw1 -p "{\"data\":{\"api.crt\":\"$(base64 -w 0 certs/api.crt)\"}}"
    kubectl patch secret tls-certs -n spanner-ns-usw2 --context ctx-usw2 -p "{\"data\":{\"api.crt\":\"$(base64 -w 0 certs/api.crt)\"}}"
    kubectl patch secret tls-certs -n spanner-ns-usw3 --context ctx-usw3 -p "{\"data\":{\"api.crt\":\"$(base64 -w 0 certs/api.crt)\"}}"
    

与 Spanner Omni 交互

在多集群设置中,每个集群都有一个负载均衡器服务。您可以使用任何服务的外部 IP 地址与 Spanner Omni 交互。对于写入和强读取,请使用充当主要区域的地址。对于过时数据读取请求,请使用离您的应用最近的区域,以实现最佳性能。

  1. 运行以下命令以获取服务地址:

    kubectl get service spanner -n spanner-ns-usw1 --context ctx-usw1
    

    EXTERNAL-IP:PORT 是部署的 DEPLOYMENT_ENDPOINT

  2. 如果尚未下载 Spanner Omni CLI,请从 spanner-omni Cloud Storage 存储桶下载。

    前往 Spanner Omni 存储桶

  3. 如果您创建了使用 TLS 加密的部署,则必须在每个命令中添加 CA 证书,以建立加密连接。如果您为客户端启用了 mTLS,还需添加客户端证书目录。

    • --ca-certificate-file=certs/ca-api.crt
    • --client-certificate-directory=clientcerts
  4. 使用 Spanner Omni CLI 创建 GoogleSQL 或 PostgreSQL 数据库并与之交互。

    GoogleSQL

    如需创建 GoogleSQL 数据库并与之交互,请运行以下命令:

    Spanner Omni CLI databases create DATABASE_NAME \
      --deployment-endpoint=dns:///DEPLOYMENT_ENDPOINT \
      --ca-certificate-file=certs/ca-api.crt
    Spanner Omni CLI sql --database=DATABASE_NAME \
      --deployment-endpoint=dns:///DEPLOYMENT_ENDPOINT \
      --ca-certificate-file=certs/ca-api.crt
    

    PostgreSQL

    如需创建 PostgreSQL 数据库并与之交互,请运行以下命令:

    Spanner Omni CLI databases create POSTGRESQL_DATABASE_NAME \
      --database_dialect POSTGRESQL \
      --deployment-endpoint=dns:///DEPLOYMENT_ENDPOINT \
      --ca-certificate-file=certs/ca-api.crt
    Spanner Omni CLI sql --database=POSTGRESQL_DATABASE_NAME \
      --deployment-endpoint=dns:///DEPLOYMENT_ENDPOINT \
      --ca-certificate-file=certs/ca-api.crt
    

    您还可以按照 使用 PGAdapter 进行连接 中的说明与 PostgreSQL 数据库交互,以配置 PGAdapter 并将 PostgreSQL 工具(例如 psql)与 PostgreSQL 方言数据库搭配使用。

后续步骤