升级 Spanner Omni 部署

本文档介绍了如何将 Spanner Omni 部署从早期版本升级到较新版本。

Spanner Omni 使用异步分阶段发布状态机,以帮助确保安全升级,而不会中断服务。分阶段升级可让您执行以下操作:

升级工作流

Spanner Omni 升级流程包含多个连续阶段:

  1. 架构阶段:通过使用目标二进制版本运行内部数据库架构迁移来准备部署。架构迁移无法回滚,但可向后兼容之前的二进制版本。
  2. 二进制阶段:使用滚动重启更新部署中所有服务器的服务器二进制文件或容器映像。如果您检测到错误,可以在最终确定开始之前的任何时间将二进制文件或容器映像回滚到较早的版本。
  3. 启用功能阶段:启用版本兼容的功能,并在您升级所有服务器上的二进制文件后开始。如果升级不包含版本兼容的功能,则可能不适用此阶段;如果功能相互依赖,则可能需要进行多轮测试。对于支持回滚的可选阶段,您可以使用 Spanner Omni CLI 发起回滚。
  4. 完成阶段:完成发布,确定目标版本。在最终确定阶段开始后,无法再进行回滚。

准备工作

在升级 Spanner Omni 部署之前,请确保您满足以下前提条件:

  • 您有一个正在运行的 Spanner Omni 部署。如需了解详情,请参阅在 Kubernetes 上创建部署或在虚拟机上创建部署。
  • 您已下载并安装 Spanner Omni CLI。
  • 您可以通过运行 CLI 命令的机器访问所有 Spanner Omni 内部端口(TCP 15000 到 15027),也可以访问部署端点。
  • 如果您的部署使用传输层安全协议 (TLS) 或双向 TLS (mTLS) 加密,请确保基本目录 BASE_DIR/tls 中或集群中已装载有效的证书。
  • 您已确定目标发布版本:
    • 对于虚拟机部署:下载目标版本软件包 spanner-omni-server-TARGET_VERSION.tar.gz。
    • 对于 Helm 和 Kubernetes 部署:在 Artifact Registry 中标识目标容器映像,例如 us-docker.pkg.dev/spanner-omni/images/spanner-omni:TARGET_VERSION。

第 1 步:准备架构升级

如需启动升级,请为目标版本准备发布。在此阶段,Spanner Omni 会运行内部数据库架构迁移,而现有服务器会继续处理流量。

选择您的部署环境对应的标签页:

虚拟机

在虚拟机部署中,下载并解压缩目标版本软件包,然后使用解压缩的 Spanner Omni CLI 启动发布准备。

  1. 登录到部署中可访问所有 Spanner Omni 内部端口(TCP 15000 到 15027)的服务器。

  2. 下载并解压缩目标版本软件包:

    tar -xzf spanner-omni-server-TARGET_VERSION.tar.gz -C EXTRACT_DIR
    

    替换以下内容:

    • TARGET_VERSION:要升级到的目标版本,例如 2026.r4-lts。
    • EXTRACT_DIR:您将发布软件包解压缩到的目录,例如 /tmp/target_spanner/。
  3. 通过运行提取的 CLI 中的 rollouts prepare 命令来启动发布准备工作:

    EXTRACT_DIR/bin/spanner deployment rollouts prepare \
      --target-server-binary=EXTRACT_DIR/bin/spanner_server \
      --root-server=ROOT_SERVERS \
      --base-dir=BASE_DIR
    

    替换以下内容:

    • EXTRACT_DIR:包含目标 bin/spanner CLI 和 bin/spanner_server 二进制文件的提取目录。
    • ROOT_SERVERS:一个根服务器端点或多个根服务器的英文逗号分隔列表,例如 localhost:15000 或 server1:15000,server2:15000,server3:15000。
    • BASE_DIR:Spanner Omni 的基本目录,例如 /spanner。
    • 如果您的部署使用 TLS 或 mTLS 加密,请附加指向有效证书的 --ca-certificate-file=CA_CERT_FILE 和 --client-certificate-directory=CERT_DIR。

Helm

在 Helm 部署中,架构准备取决于您运行的是多服务器部署还是单服务器部署:

  • 多服务器部署(高可用性 / 生产环境):Helm 会自动处理架构准备工作。在第 3 步:更新二进制文件或容器映像中运行 helm upgrade 时,Helm 图表会触发 spanner-prepare-for-upgrade 预升级钩子作业,以在更新任何 StatefulSet 之前运行架构迁移。直接前往第 2 步:验证有效发布状态。

  • 单服务器部署 (deployment.singleServer=true):由于单服务器模式将内部服务严格绑定到环回接口 (127.0.0.1),因此网络作业无法访问这些服务。使用目标容器映像通过临时调试容器在运行的 pod 内本地运行架构迁移:

    kubectl debug pod/POD_NAME -n NAMESPACE \
      --image=us-docker.pkg.dev/spanner-omni/images/spanner-omni:TARGET_VERSION \
      --container=upgrade-prepare -i \
      -- /google/spanner/bin/spanner_server prepare_for_upgrade --root_server=127.0.0.1
    

    替换以下内容:

    • POD_NAME:服务器 pod 的名称,例如 spanner-a-0。
    • NAMESPACE:相应部署的 Kubernetes 命名空间,例如 spanner-ns。
    • TARGET_VERSION:要升级到的目标版本,例如 2026.r4-lts。

独立 Kubernetes

如果您在 Kubernetes 上部署 Spanner Omni 时未使用 Helm,请运行独立的 Kubernetes 批量作业,以使用目标映像针对活跃的根服务器执行架构迁移。

  1. 创建一个名为 spanner-prepare-upgrade.yaml 的文件,其中包含以下作业清单:

    apiVersion: batch/v1
    kind: Job
    metadata:
      namespace: NAMESPACE
      name: spanner-prepare-for-upgrade
    spec:
      # Fail fast on the first error to stop the rollout immediately.
      backoffLimit: 0
      template:
        metadata:
          namespace: NAMESPACE
        spec:
          restartPolicy: Never
          containers:
            - name: spanner-upgrade
              image: us-docker.pkg.dev/spanner-omni/images/spanner-omni:TARGET_VERSION
              command: ["/google/spanner/bin/spanner_server"]
              args:
                - "prepare_for_upgrade"
                - "--root_server=ROOT_SERVER_ENDPOINT"
              volumeMounts:
                - name: tls-certs
                  mountPath: "/spanner/tls"
                  readOnly: true
                - name: spanner-data
                  mountPath: /spanner
          volumes:
            - name: tls-certs
              secret:
                secretName: tls-certs
                optional: true
                defaultMode: 256
            - name: spanner-data
              emptyDir: {}
    

    替换以下内容:

    • NAMESPACE:相应部署的 Kubernetes 命名空间,例如 spanner-ns。
    • TARGET_VERSION:要升级到的目标版本,例如 2026.r4-lts。
    • ROOT_SERVER_ENDPOINT:有效根服务器 pod 的端点,例如 spanner-a-0.pod.spanner-ns。
  2. 应用清单以运行准备作业:

    kubectl apply -f spanner-prepare-upgrade.yaml
    

第 2 步:验证有效发布状态

准备步骤完成后,验证发布是否已创建并检查其阶段状态。

  1. 列出有效发布,以检索发布 ID:

    spanner deployment rollouts list \
      --deployment-endpoint=DEPLOYMENT_ENDPOINT
    

    将 DEPLOYMENT_ENDPOINT 替换为部署中服务器的端点,例如 localhost:15000 或 spanner-a-0.pod.spanner-ns:15000。

    输出类似于以下内容:

    NAME                         STATE          TARGET_VERSION    START_TIME                     END_TIME
    rollouts/1788942172101727    IN_PROGRESS    2026.r3-beta      2026-09-09T08:22:52.101727Z    -
    
  2. 检查详细的发布阶段状态:

    spanner deployment rollouts describe ROLLOUT_ID \
      --deployment-endpoint=DEPLOYMENT_ENDPOINT
    

    替换以下内容:

    • ROLLOUT_ID:数字推出 ID,例如 1788942172101727。
    • DEPLOYMENT_ENDPOINT:部署中服务器的端点。

    输出类似于以下内容:

    name: rollouts/1788942172101727
    phases:
        - name: rollouts/1788942172101727/phases/schema
          startTime: "2026-09-09T08:22:52.101727Z"
          state: SUCCEEDED
        - name: rollouts/1788942172101727/phases/binary
          startTime: "2026-09-09T08:23:29.585375Z"
          state: IN_PROGRESS
        - name: rollouts/1788942172101727/phases/finalize
          state: PENDING
    sourceVersion: 2026.r2-beta.3
    startTime: "2026-09-09T08:22:52.101727Z"
    state: IN_PROGRESS
    targetVersion: 2026.r3-beta
    

    在继续操作之前,请验证以下阶段状态:

    • schema:显示 SUCCEEDED,表示内部数据库架构迁移已完成。
    • binary:显示 IN_PROGRESS,表示推出引擎已准备好进行二进制更新。
    • finalize:显示 PENDING,等待二进制阶段完成。

第 3 步:更新二进制文件或容器映像

架构阶段成功完成后,将部署中所有节点的正在运行的服务器二进制文件或容器映像更新为目标版本。

选择您的部署环境对应的标签页:

虚拟机

在虚拟机部署中,使用滚动重启更新所有虚拟机中的 spanner_server 二进制文件:

  • 一次更新一个故障域或可用区:在多可用区部署中,先更新一个可用区中的服务器,验证稳定性,然后再更新下一个可用区。这样可确保 Paxos 一致性群组保持法定人数。
  • 逐步重启:同时重启的服务器不超过 5%,以确保持续查询可用。
  • 验证服务器运行状况:在更新下一个故障域之前,请确保所有重新启动的服务器运行状况良好,并且已重新加入集群。

Helm

在 Helm 部署中,运行 helm upgrade,同时通过传递 --reuse-values 或提供值文件来保留现有配置值:

  • 多服务器部署(生产环境 / 高可用性):

    helm upgrade spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni \
      --version CHART_VERSION \
      -n NAMESPACE \
      --reuse-values \
      --set image.tag=TARGET_VERSION \
      --timeout 30m
    

    Helm 会使用升级前钩子自动执行第 1 阶段,然后按顺序逐个可用区启动 StatefulSet (rollout.staggered: true) 的滚动更新。

  • 单服务器部署 (deployment.singleServer=true):

    明确传递 --set skipPrepareUpgrade=true,以便 Helm 跳过升级前钩子作业,因为您已在本地完成第 1 阶段:

    helm upgrade spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni \
      --version CHART_VERSION \
      -n NAMESPACE \
      --reuse-values \
      --set skipPrepareUpgrade=true \
      --set image.tag=TARGET_VERSION \
      --timeout 30m
    

替换以下内容:

  • CHART_VERSION:目标 Helm 图表版本,例如 1.0。
  • NAMESPACE:相应部署的 Kubernetes 命名空间,例如 spanner-ns。
  • TARGET_VERSION:目标容器映像标记,例如 2026.r4-lts。

独立 Kubernetes

在没有 Helm 的自定义 Kubernetes 部署中,将 StatefulSet 或 Deployment 规范中的容器映像更新为 TARGET_VERSION。

跨故障网域执行滚动更新,一次更新一个可用区,同时重启的 Pod 不超过 5%,以保持法定人数。

第 4 步:验证二进制阶段进展

将所有服务器或 pod 更新为目标版本后,验证二进制阶段是否成功完成。

检查发布阶段状态:

spanner deployment rollouts describe ROLLOUT_ID \
  --deployment-endpoint=DEPLOYMENT_ENDPOINT

替换以下内容:

  • ROLLOUT_ID:数字推出 ID,例如 1788942172101727。
  • DEPLOYMENT_ENDPOINT:部署中服务器的端点。

输出类似于以下内容:

name: rollouts/1788942172101727
phases:
    - name: rollouts/1788942172101727/phases/schema
      startTime: "2026-09-09T08:22:52.101727Z"
      state: SUCCEEDED
    - name: rollouts/1788942172101727/phases/binary
      startTime: "2026-09-09T08:23:29.585375Z"
      state: SUCCEEDED
    - name: rollouts/1788942172101727/phases/finalize
      state: PENDING
sourceVersion: 2026.r2-beta.3
startTime: "2026-09-09T08:22:52.101727Z"
state: IN_PROGRESS
targetVersion: 2026.r3-beta

确认 binary 阶段状态已更改为 SUCCEEDED。在所有剩余阶段完成之前,整体发布状态将保持为 IN_PROGRESS。在 phases/binary 转换为 SUCCEEDED 后,部署即可继续进行剩余阶段。

第 5 步:安排并执行剩余阶段

当二进制阶段成功完成且您验证部署稳定后,请安排剩余的发布阶段,直至 finalize 阶段。finalize 阶段(发布流程的最后一个阶段)会在整个部署中封存新版本。您可以通过指定 --deployment-endpoint,从任何可访问 Spanner Omni 服务的机器运行此命令。

对于处于 PENDING 状态的每个剩余阶段(例如,如果存在 ,则为 enable_features,然后是 finalize),请完成以下步骤:

  1. 安排阶段:

    spanner deployment rollouts phases schedule PHASE_NAME \
      --rollout=ROLLOUT_ID \
      --deployment-endpoint=DEPLOYMENT_ENDPOINT
    

    替换以下内容:

    • PHASE_NAME:要安排的阶段的名称,例如 finalize 或 enable_features。
    • ROLLOUT_ID:数字推出 ID,例如 1788942172101727。
    • DEPLOYMENT_ENDPOINT:部署中服务器的端点。

    输出表明预定阶段为 IN_PROGRESS:

    name: rollouts/1788942172101727
    phases:
        - name: rollouts/1788942172101727/phases/schema
          startTime: "2026-09-09T08:22:52.101727Z"
          state: SUCCEEDED
        - name: rollouts/1788942172101727/phases/binary
          startTime: "2026-09-09T08:23:29.585375Z"
          state: SUCCEEDED
        - name: rollouts/1788942172101727/phases/finalize
          state: IN_PROGRESS
    sourceVersion: 2026.r2-beta.3
    startTime: "2026-09-09T08:22:52.101727Z"
    state: IN_PROGRESS
    targetVersion: 2026.r3-beta
    
  2. 等待阶段成功完成,并验证其状态:

    spanner deployment rollouts describe ROLLOUT_ID \
      --deployment-endpoint=DEPLOYMENT_ENDPOINT
    

    针对每个剩余阶段重复执行上述步骤,直到完成所有阶段(包括 finalize)。

    最终阶段 (finalize) 完成后,所有阶段和整体发布状态都会转换为 SUCCEEDED:

    endTime: "2026-09-09T08:45:43.949702Z"
    name: rollouts/1788942172101727
    phases:
        - name: rollouts/1788942172101727/phases/schema
          startTime: "2026-09-09T08:22:52.101727Z"
          state: SUCCEEDED
        - name: rollouts/1788942172101727/phases/binary
          startTime: "2026-09-09T08:23:29.585375Z"
          state: SUCCEEDED
        - name: rollouts/1788942172101727/phases/finalize
          startTime: "2026-09-09T08:45:43.898111Z"
          state: SUCCEEDED
    sourceVersion: 2026.r2-beta.3
    startTime: "2026-09-09T08:22:52.101727Z"
    state: SUCCEEDED
    targetVersion: 2026.r3-beta
    
  3. 在发布列表中确认“已完成”状态:

    spanner deployment rollouts list \
      --deployment-endpoint=DEPLOYMENT_ENDPOINT
    

    输出内容会确认发布已完成:

    NAME                         STATE        TARGET_VERSION    START_TIME                     END_TIME
    rollouts/1788942172101727    SUCCEEDED    2026.r3-beta      2026-09-09T08:22:52.101727Z    2026-09-09T08:45:43.949702Z
    

回滚升级

如果您在升级期间遇到问题,是否可以回滚升级取决于其当前的分阶段发布阶段:

  • 架构阶段:无法回滚。准备期间应用了内部数据库架构迁移,这些迁移是单向的,无法恢复。不过,架构迁移向后兼容源版本,因此较早的服务器二进制文件可以继续正常运行。
  • 二进制阶段:在开始最终确定之前,可以随时回滚到之前的版本。如需了解详情,请参阅回滚二进制文件或容器映像。
  • 可选的发布阶段:对于支持自动回滚的可选阶段(例如启用功能),请使用 Spanner Omni CLI 启动回滚。
  • 最终确定阶段:无法回滚。最终确定开始后,目标版本会在整个部署过程中永久封存,无法回滚。

回滚二进制文件或容器映像

如需在最终确定开始之前回滚二进制阶段,请在所有服务器或 pod 上执行滚动重启,以恢复到之前的(源)版本。

虚拟机

在虚拟机部署中,回滚所有虚拟机上的 spanner_server 二进制文件:

  1. 将较早的 spanner_server 二进制文件版本部署到主机。
  2. 在各个故障网域中逐步重启服务器,一次更新一个可用区,同时重启的服务器不超过 5%,以保持 Paxos 仲裁。
  3. 在继续处理下一个故障域之前,请验证所有重新启动的服务器是否运行正常并已重新加入集群。

Helm

在 Helm 部署中,将容器映像标记更新回之前的版本:

helm upgrade spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni \
  --version CHART_VERSION \
  -n NAMESPACE \
  --reuse-values \
  --set image.tag=SOURCE_VERSION \
  --timeout 30m

替换以下内容:

  • CHART_VERSION:Helm 图表版本,例如 1.0。
  • NAMESPACE:相应部署的 Kubernetes 命名空间,例如 spanner-ns。
  • SOURCE_VERSION:要恢复到的较早的容器映像标记,例如 2026.r2-beta.3。

独立 Kubernetes

在没有 Helm 的自定义 Kubernetes 部署中,将 StatefulSet 或 Deployment 规范中的容器映像更新回 SOURCE_VERSION。

跨故障网域执行滚动更新,一次更新一个可用区,同时重启的 Pod 不超过 5%,以保持法定人数。

回滚可选的发布阶段

对于支持回滚的可选发布阶段(例如功能启用阶段),请运行 rollouts rollback 命令来启动回滚:

spanner deployment rollouts rollback ROLLOUT_ID \
  --deployment-endpoint=DEPLOYMENT_ENDPOINT

替换以下内容:

  • ROLLOUT_ID:数字发布 ID。
  • DEPLOYMENT_ENDPOINT:部署中服务器的端点。

后续步骤