管理证书

选择文档版本:

借助自定义证书颁发者,您可以在基于 Kubernetes 的 AlloyDB Omni 数据库集群上管理传输层安全协议 (TLS) 证书。

默认情况下,AlloyDB Omni Kubernetes 操作器会使用 cert-manager 为每个数据库集群预配一组 TLS 证书。除了数据库服务器证书之外,Operator 还会为控制平面组件创建证书,以确保内部连接也安全。默认情况下,每个证书都由运营商管理的颁发者签名。

如果您希望所有证书(包括控制平面组件的证书)都链接回您自己的可信根证书授权机构 (CA),则可以将 Operator 配置为使用您选择的颁发者。这样,您就可以将所有证书(包括用于控制平面功能的证书)链接到您自己的公钥基础架构 (PKI),而无需公开每个内部实体的实现细节。

默认证书生命周期

默认情况下,AlloyDB Omni 操作器使用 cert-manager 为操作器、控制平面和数据库实例颁发并自动续订 TLS 证书。

下表列出了由 AlloyDB Omni 操作器管理的证书的默认有效期:

证书类型 证书说明 密文名称 命名空间 默认时长
Operator mTLS 客户端证书 由 local-controller-manager Deployment 用于高可用性 (HA) 健康检查以及 Operator 与控制平面代理之间的连接。 dbs-al-cert-l2-operator Operator 命名空间 1440h0m0s(60 天)
Operator 网络钩子服务器证书 由 Operator 准入网络钩子服务器用于验证和更改自定义资源。 fleet-webhook-server-cert

local-webhook-server-cert
Operator 命名空间 1440h0m0s(60 天)
每个实例的控制平面代理证书 供每个实例的数据库代理、节点管理器和备份守护程序用于控制平面连接。 dbs-al-cert-dbd-INSTANCE_ID-DB_CLUSTER_NAME

dbs-al-cert-al-INSTANCE_ID-DB_CLUSTER_NAME-nm

dbs-al-cert-backup-daemon-BACKUP_REPO_NAME
数据库集群命名空间 1440h0m0s(60 天)
备份证书 由备份服务用于备份和恢复连接。 dbs-al-cert-backup-client

dbs-al-cert-backup-client-DATA_PLANE_ISSUER_NAME

dbs-al-cert-backup-server-INSTANCE_ID-DB_CLUSTER_NAME

dbs-al-cert-standby-backup-server-INSTANCE_ID-DB_CLUSTER_NAME
数据库集群命名空间 1440h0m0s(60 天)
数据库服务器证书 保护数据平面客户端与数据库实例的连接。 dbs-al-cert-DB_CLUSTER_NAME 数据库集群命名空间 87600h0m0s(10 年)
PgBouncer 身份验证查询证书 PgBouncer Deployment 用于连接到数据库并执行连接池的数据库客户端证书。仅在您创建 PgBouncer 资源时创建。 dbs-al-pgb-cert-PGBOUNCER_NAME 数据库集群命名空间 87600h0m0s(10 年)
运营商管理的自签名 CA 证书 操作器的默认自签名颁发者用于为操作器、控制平面代理、备份和数据库服务器证书签名的根 CA 证书。 dbs-al-ca-l2-operator

dbs-al-ca-DB_CLUSTER_NAME

dbs-al-ca-dbd-INSTANCE_ID-DB_CLUSTER_NAME

dbs-al-ca-backup-server

dbs-al-ca-backup-daemon-BACKUP_REPO_NAME
Operator 命名空间和数据库集群命名空间 87600h0m0s(10 年)

在此表中,Secret 名称使用以下占位符:

  • INSTANCE_ID:为数据库实例生成的 4 字符标识符。
  • DB_CLUSTER_NAME:您的 DBCluster 资源的名称。
  • DATA_PLANE_ISSUER_NAME:在 spec.primarySpec.tls.dataPlaneCertIssuer.name 中配置的自定义 cert-manager 颁发者的名称(如果已指定)。
  • BACKUP_REPO_NAME:您的 BackupRepository 资源的名称(如果已配置)。
  • PGBOUNCER_NAME:您的 PgBouncer 资源的名称。

配置自定义颁发者

您可以为数据库集群、AlloyDB Omni 操作器和 PgBouncer 配置自定义证书颁发机构。

如需配置证书颁发者,您必须先创建与您希望为证书签名的 CA 关联的 ClusterIssuer 或 Issuer 类型的 cert-manager 颁发者。AlloyDB Omni 操作器在创建证书时会引用此颁发者。

数据库集群证书

有两个数据库集群规范字段可用于配置证书颁发者:

  • spec.primarySpec.tls.dataPlaneCertIssuer:对预配数据平面证书的 cert-manager 颁发者的引用。颁发者 CA 是数据库客户端在 TLS 连接期间可以信任的 CA,用于验证数据库。

  • spec.primarySpec.tls.controlPlaneAgentsCertIssuer:对预配控制平面证书的 cert-manager 颁发者的引用。这些证书用于内部连接。

spec:
  primarySpec:
    tls:
      dataPlaneCertIssuer:
        name: DATA_PLANE_ISSUER_NAME
        kind: DATA_PLANE_ISSUER_KIND
      controlPlaneAgentsCertIssuer:
        name: CONTROL_PLANE_ISSUER_NAME
        kind: CONTROL_PLANE_ISSUER_KIND

替换以下内容:

  • DATA_PLANE_ISSUER_NAME:预配数据平面证书(例如数据库服务器证书)的 cert-manager 颁发者的名称。

  • DATA_PLANE_ISSUER_KIND:cert-manager 颁发者的 API 种类,必须是 Issuer 或 ClusterIssuer。默认值为 Issuer。

  • CONTROL_PLANE_ISSUER_NAME:为内部组件预配控制平面证书的 cert-manager 颁发者的名称。

  • CONTROL_PLANE_ISSUER_KIND:cert-manager 颁发者的 API 种类,必须是 Issuer 或 ClusterIssuer。默认值为 Issuer。

运营商证书

为操作器证书配置 cert-manager 颁发者的步骤取决于用于安装 AlloyDB Omni 操作器的方法。

使用 Helm 进行配置

如果您是首次安装 AlloyDB Omni 操作器,请使用 helm install 并设置适当的值。这假定您按照使用 Helm 部署 Operator 的说明操作。

helm install alloydbomni-operator alloydbomni-operator-OPERATOR_VERSION.tgz \
--create-namespace \
--namespace alloydb-omni-system \
--set operatorCertIssuer.certManagerIssuerName="OPERATOR_CERT_ISSUER_NAME" \
--set operatorCertIssuer.certManagerIssuerKind="OPERATOR_CERT_ISSUER_KIND" \
--atomic \
--timeout 5m

如果您已安装 Operator,并且需要设置证书颁发者,请使用 helm upgrade 设置适当的值:

helm upgrade alloydbomni-operator alloydbomni-operator-OPERATOR_VERSION.tgz \
--create-namespace \
--namespace alloydb-omni-system \
--set operatorCertIssuer.certManagerIssuerName="OPERATOR_CERT_ISSUER_NAME" \
--set operatorCertIssuer.certManagerIssuerKind="OPERATOR_CERT_ISSUER_KIND" \
--atomic \
--timeout 5m

替换以下内容:

  • OPERATOR_VERSION:要安装的 AlloyDB Omni 操作器的版本。

  • OPERATOR_CERT_ISSUER_NAME:预配操作器证书(用于内部连接)的 cert-manager 颁发者的名称。

  • OPERATOR_CERT_ISSUER_KIND:cert-manager 颁发者的 API 种类,必须是 Issuer 或 ClusterIssuer。默认值为 Issuer。

使用 Operator Lifecycle Manager 进行配置

如果您使用 Operator Lifecycle Manager (OLM) 安装了 AlloyDB Omni 操作器,则可以修改 Subscription 资源 spec.config.env 字段,以设置操作器 Deployment 的 CERT_MANAGER_ISSUER_NAME 和 CERT_MANAGER_ISSUER_KIND 环境变量。

spec:
  config:
    env:
    - name: CERT_MANAGER_ISSUER_NAME
      value: OPERATOR_CERT_ISSUER_NAME
    - name: CERT_MANAGER_ISSUER_KIND
      value: OPERATOR_CERT_ISSUER_KIND

替换以下内容:

  • OPERATOR_CERT_ISSUER_NAME:预配操作器证书(用于内部连接)的 cert-manager 颁发者的名称。

  • OPERATOR_CERT_ISSUER_KIND:cert-manager 颁发者的 API 种类,必须是 Issuer 或 ClusterIssuer。默认值为 Issuer。

PgBouncer 证书

为了支持自定义颁发者,PgBouncer 控制器会检查 DBCluster spec.primarySpec.tls.dataPlaneCertIssuer 字段,并使用该字段预配 PgBouncer 证书。PgBouncer 控制器还会使用 spec.primarySpec.tls.dataPlaneCertRequest 中配置的属性来预配 PgBouncer 证书。这有助于确保 PgBouncer 使用来自同一 CA 且具有与数据库相同属性的证书。

配置自定义证书属性

您可以自定义由 Operator 生成的 TLS 证书的属性,例如证书有效期、续订窗口、主体备用名称 (SAN)、通用名称和私钥配置。

您可以在 DBCluster 清单中配置自定义证书属性:

  • spec.primarySpec.tls.dataPlaneCertRequest:指定数据平面证书的属性,包括 pgBackRest 服务器、PgBouncer 身份验证查询和数据库服务器证书。
  • spec.primarySpec.tls.controlPlaneAgentsCertRequest:指定用于预配控制平面证书的属性。这些证书用于内部连接。

配置证书请求

按以下格式指定请求属性:

spec:
  primarySpec:
    tls:
      dataPlaneCertRequest:
        commonName: DATABASE_COMMON_NAME
        dnsNames:
        - DATABASE_DNS_NAME_1
        - DATABASE_DNS_NAME_2
        duration: DATA_PLANE_DURATION
        renewBefore: DATA_PLANE_RENEW_BEFORE
        privateKey:
          algorithm: DATA_PLANE_ALGORITHM
          size: DATA_PLANE_KEY_SIZE
          rotationPolicy: DATA_PLANE_ROTATION_POLICY
      controlPlaneAgentsCertRequest:
        duration: CONTROL_PLANE_DURATION
        renewBefore: CONTROL_PLANE_RENEW_BEFORE
        privateKey:
          algorithm: CONTROL_PLANE_ALGORITHM
          size: CONTROL_PLANE_KEY_SIZE
          rotationPolicy: CONTROL_PLANE_ROTATION_POLICY

替换以下内容:

  • DATABASE_COMMON_NAME:(可选,仅限数据平面)数据库证书的通用名称。
  • DATABASE_DNS_NAME_1、DATABASE_DNS_NAME_2:(可选,仅限数据平面)数据库证书的主体备用名称 (SAN) 列表。
  • DATA_PLANE_DURATION 和 CONTROL_PLANE_DURATION:请求的证书有效期,以字符串时长表示,例如,720h0m0s 表示自定义的 30 天时长。在每个证书请求块中,您必须同时指定 duration 和 renewBefore(renewBefore 小于 duration),或同时省略这两个字段。如果省略这两个字段,则控制平面和备份证书的默认有效期为 1440h0m0s(即 60 天),数据库服务器和 PgBouncer 身份验证查询证书的默认有效期为 87600h0m0s(即 10 年)。
  • DATA_PLANE_RENEW_BEFORE 和 CONTROL_PLANE_RENEW_BEFORE:cert-manager 必须在到期前多久开始尝试续订,例如,120h0m0s 表示在到期前 5 天。在每个证书请求块中,您必须同时指定 duration 和 renewBefore(renewBefore 小于 duration),或同时省略这两个字段。如果省略这两个字段,则控制平面和备份证书的默认续订窗口为 120h0m0s(即 5 天),数据库服务器和 PgBouncer 身份验证查询证书的默认续订窗口为 1440h0m0s(即 60 天)。
  • DATA_PLANE_ALGORITHM 和 CONTROL_PLANE_ALGORITHM:私钥算法。有效值为 RSA、ECDSA 或 Ed25519。
  • DATA_PLANE_KEY_SIZE 和 CONTROL_PLANE_KEY_SIZE:私钥大小(以位为单位)。如果算法为 RSA,则有效值为 4096 或 8192(默认值为 4096)。如果算法为 ECDSA,则有效值为 384 或 521(默认值为 384)。如果算法为 Ed25519,则系统会忽略大小。
  • DATA_PLANE_ROTATION_POLICY 和 CONTROL_PLANE_ROTATION_POLICY:控制私钥重新生成的政策。有效值为 Always 或 Never。

操作员和备份客户端证书

如需为 Operator 和备份客户端自定义证书属性(这些属性在命名空间中的所有实例之间共享,不受数据库集群规范管理),请修改 Certificate 自定义资源。Operator 会保留这些手动修改。

清理证书 Secret

删除 DBCluster 资源时,AlloyDB Omni 操作器会删除关联的 Certificate 资源,但默认情况下,cert-manager 不会清理证书 Secret 资源。如需将 cert-manager 控制器配置为在删除证书时清理 Secret,请参阅 cert-manager 文档中的在删除证书时清理 Secret。

如果您已删除 DBCluster 资源,但未配置自动清理,请手动删除悬空证书 Secret:

kubectl delete secret CERTIFICATE_SECRET_NAME -n NAMESPACE

替换以下内容:

  • CERTIFICATE_SECRET_NAME:要删除的证书 Secret 的名称。
  • NAMESPACE:数据库集群的命名空间。

验证

如需验证 Operator Deployment 是否运行正常以及是否设置了环境变量 CERT_MANAGER_ISSUER_NAME 和 CERT_MANAGER_ISSUER_KIND,请运行以下命令:

kubectl get deployments local-controller-manager -n alloydb-omni-system -o yaml

如需验证是否使用了正确的颁发者,请按如下方式检查 Certificate 对象:

kubectl get certificate -n NAMESPACE

将 NAMESPACE 替换为数据库集群的命名空间,或将 alloydb-omni-system 替换为 Operator 证书。

检查每个证书的输出中的 issuerRef 字段,确认其与您的自定义颁发者匹配。

缓解 1.8.2 之前的 Operator 版本中的 Operator 客户端证书过期问题

在 1.8.2 之前的 AlloyDB Omni 操作器版本中,local-controller-manager Deployment 会将 60 天的 dbs-al-cert-l2-operator mTLS 客户端证书缓存在内存中,以便与控制平面代理建立高可用性健康检查连接。虽然 cert-manager 会在 dbs-al-cert-l2-operator Secret 到期前五天自动续订,但 local-controller-manager Deployment 在 Operator Pod 重启之前不会重新加载续订的证书。当缓存的证书在第 60 天过期时,后续健康检查重新连接会失败,并显示 tls: expired certificate 错误,这可能会触发计划外的高可用性故障切换。

如需永久解决此问题,请将 AlloyDB Omni 操作器升级到 1.8.2 版或更高版本。

如果您无法立即升级到 Operator 1.8.2 版或更高版本,请在证书到期前至少 10 天轮替 dbs-al-cert-l2-operator Secret 并重启 local-controller-manager Deployment。此过程不会重启数据库 Pod,也不会中断数据库流量。

准备工作

在运行 rotate_cert.sh 脚本之前,请确认您的环境满足以下要求:

  • 在 PATH 中安装 bash、kubectl、openssl 和 base64。
  • 配置对 Kubernetes 集群的访问权限,并将活跃 kubectl 上下文设置为目标集群。如需确认活跃上下文,请运行 kubectl config current-context。针对运行 1.8.2 之前 Operator 版本的每个集群重复此过程。
  • 确认您的账号在 Operator 命名空间(默认为 alloydb-omni-system)中具有 Kubernetes 基于角色的访问权限控制 (RBAC) 权限:
    • Certificate 资源和 Pod 日志上的 get
    • Pod 资源上的 get 和 list
    • dbs-al-cert-l2-operator Secret 的 get 和 delete 权限(以及用于恢复已备份 Secret 的 create 和 patch 权限)
    • 针对 local-controller-manager Deployment 的 get 和 patch
    • delete 资源上的 CertificateRequest(用于恢复备份的 Secret)

轮替 Operator 客户端证书

rotate_cert.sh 脚本支持两种模式和一个可选的命名空间参数,默认为 alloydb-omni-system:

  • ./rotate_cert.sh check:执行只读检查并输出以下信息:
    • 当前证书序列号和有效期
    • 建议的轮替截止日期,设置为到期前 10 天
    • local-controller-manager 容器启动时间
    • 内存中证书状态为 [OK] 或 [WARNING]
    • kubectl 备份命令
  • ./rotate_cert.sh rotate:执行以下操作:
    • 删除 dbs-al-cert-l2-operator Secret
    • 等待 cert-manager 颁发新的证书序列号并更新 dbs-al-cert-request-l2-operator Certificate 资源
    • 重启 local-controller-manager Deployment
    • 检查新 Pod 的日志并输出新的失效日期

如需检查和轮替 Operator 客户端证书,请按以下步骤操作:

  1. 将以下脚本保存到名为 rotate_cert.sh 的文件中,然后使该文件可执行:

    cat << 'EOF' > rotate_cert.sh
    #!/usr/bin/env bash
    set -euo pipefail
    MODE="${1:-}"
    NS="${2:-alloydb-omni-system}"
    SECRET="dbs-al-cert-l2-operator"
    CERT="dbs-al-cert-request-l2-operator"
    DEPLOY="local-controller-manager"
    get_cert_info() {
      kubectl get secret "$SECRET" -n "$NS" -o jsonpath='{.data.tls\.crt}' 2>/dev/null \
        | base64 -d 2>/dev/null | openssl x509 -noout -serial -enddate 2>/dev/null || true
    }
    calc_rotate_by() {
      date -u -d "$1 - 10 days" +"%Y-%m-%d" 2>/dev/null \
        || date -u -j -v-10d -f "%Y-%m-%dT%H:%M:%SZ" "$1" +"%Y-%m-%d" 2>/dev/null || echo "unknown"
    }
    get_container_name() {
      local names
      names="$(kubectl get pods -n "$NS" -l local-control-plane=controller-manager \
        --field-selector=status.phase=Running --sort-by=.metadata.creationTimestamp \
        -o jsonpath='{.items[-1].spec.containers[*].name}' 2>/dev/null || true)"
      if [[ " $names " == *" local-manager "* ]]; then
        echo "local-manager"
      else
        echo "manager"
      fi
    }
    case "$MODE" in
      check)
        INFO="$(get_cert_info)"
        SERIAL="$(echo "$INFO" | sed -n 's/^serial=//p')"
        ENDDATE="$(echo "$INFO" | sed -n 's/^notAfter=//p')"
        NOT_BEFORE="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.notBefore}')"
        NOT_AFTER="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.notAfter}')"
        CONTAINER="$(get_container_name)"
        STARTED_AT="$(kubectl get pods -n "$NS" -l local-control-plane=controller-manager \
          --field-selector=status.phase=Running --sort-by=.metadata.creationTimestamp \
          -o jsonpath="{.items[-1].status.containerStatuses[?(@.name==\"$CONTAINER\")].state.running.startedAt}")"
        echo "Certificate Serial      : $SERIAL"
        echo "Certificate Start Date  : $NOT_BEFORE"
        echo "Certificate End Date    : $ENDDATE ($NOT_AFTER)"
        echo "Recommended Rotate By   : $(calc_rotate_by "$NOT_AFTER") (10 days before expiry)"
        echo "Operator Started At     : $STARTED_AT"
        if [[ "$STARTED_AT" < "$NOT_BEFORE" ]]; then
          echo "[WARNING] Operator started ($STARTED_AT) BEFORE current cert was issued ($NOT_BEFORE). It is still caching the old cert in memory! Run './rotate_cert.sh rotate $NS' now."
        else
          echo "[OK] Operator is running with the current certificate in memory."
        fi
        echo "Optional Backup Command : kubectl get secret $SECRET -n $NS -o yaml > $SECRET-backup.yaml"
        ;;
      rotate)
        OLD_SERIAL="$(get_cert_info | sed -n 's/^serial=//p')"
        OLD_REV="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.revision}' 2>/dev/null || true)"
        echo "Current Certificate Serial: ${OLD_SERIAL:-none}"
        kubectl delete secret "$SECRET" -n "$NS" --ignore-not-found
        NEW_SERIAL=""
        NOT_AFTER=""
        for _ in {1..30}; do
          sleep 2
          NEW_SERIAL="$(get_cert_info | sed -n 's/^serial=//p')"
          NEW_REV="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.revision}' 2>/dev/null || true)"
          READY_COND="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || true)"
          NOT_AFTER="$(kubectl get certificate "$CERT" -n "$NS" -o jsonpath='{.status.notAfter}' 2>/dev/null || true)"
          [[ -n "$NEW_SERIAL" && "$NEW_SERIAL" != "$OLD_SERIAL" && "$NEW_REV" != "$OLD_REV" && "$READY_COND" == "True" && -n "$NOT_AFTER" ]] && break
        done
        [[ -n "$NEW_SERIAL" && "$NEW_SERIAL" != "$OLD_SERIAL" && "$READY_COND" == "True" ]] || { echo "[ERROR] Timed out waiting for new cert."; exit 1; }
        kubectl rollout restart "deployment/$DEPLOY" -n "$NS"
        kubectl rollout status "deployment/$DEPLOY" -n "$NS" --timeout=180s
        NEW_POD="$(kubectl get pods -n "$NS" -l local-control-plane=controller-manager \
          --field-selector=status.phase=Running --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}')"
        CONTAINER="$(get_container_name)"
        READY=false
        for _ in {1..40}; do
          LOGS="$(kubectl logs "pod/$NEW_POD" -n "$NS" -c "$CONTAINER" 2>/dev/null || true)"
          grep -q "tls: expired certificate" <<<"$LOGS" && { echo "[ERROR] Found 'tls: expired certificate' in operator logs!"; exit 1; }
          grep -q "L2 controller cert generation completed successfully" <<<"$LOGS" && { READY=true; break; }
          sleep 3
        done
        [[ "$READY" == "true" ]] || { echo "[ERROR] Timed out waiting for L2 controller cert generation log."; exit 1; }
        echo "[SUCCESS] New Serial: $NEW_SERIAL | End Date: $NOT_AFTER | Next Rotate By: $(calc_rotate_by "$NOT_AFTER") (10 days before expiry)"
        ;;
      *)
        echo "Usage: $0 <check|rotate> [namespace]"
        echo "  check       : Validate current certificate status and operator start time."
        echo "  rotate      : Trigger immediate certificate rotation and restart the operator."
        echo "  [namespace] : Namespace of the operator (defaults to 'alloydb-omni-system')."
        exit 1 ;;
    esac
    EOF
    chmod +x rotate_cert.sh
    
  2. 在 check 模式下运行 rotate_cert.sh 脚本,以检查当前证书到期日期、建议的轮替日期和 Operator 内存中状态:

    ./rotate_cert.sh check
    
  3. 可选:在轮替证书之前备份 dbs-al-cert-l2-operator Secret:

    kubectl get secret dbs-al-cert-l2-operator -n alloydb-omni-system \
      -o yaml > dbs-al-cert-l2-operator-backup.yaml
    
  4. 如果 check 输出显示 [WARNING],或者当前日期在 Recommended Rotate By 日期当天或之前,请在 rotate 模式下运行 rotate_cert.sh 脚本:

    ./rotate_cert.sh rotate
    

    确认输出以 [SUCCESS] 结尾,并显示新的证书序列号、失效日期和下一个建议的轮替日期。如果输出显示 [ERROR] 或脚本以非零状态退出,请重新运行 ./rotate_cert.sh check,并通过运行 kubectl logs deployment/local-controller-manager -n alloydb-omni-system -c local-manager(或在 1.6.0 之前的操作器版本中运行 -c manager)来检查操作器日志。

  5. 可选:如果您在第 3 步中创建了备份文件,请在确认轮替成功后删除本地备份文件,因为该文件包含旧私钥:

    rm -f dbs-al-cert-l2-operator-backup.yaml
    

恢复已备份的证书

如果 cert-manager 在轮替期间未能颁发新证书,并且您需要回滚到未过期的 dbs-al-cert-l2-operator-backup.yaml 文件,请按照以下步骤操作:

  1. 删除 dbs-al-cert-request-l2-operator 证书的待处理或失败的 CertificateRequest 资源,以便 cert-manager 不会因 SecretMismatch 原因拒绝恢复的私钥并覆盖恢复的 Secret:

    REV="$(kubectl get certificate dbs-al-cert-request-l2-operator -n alloydb-omni-system -o jsonpath='{.status.revision}')"
    kubectl delete certificaterequest \
      "dbs-al-cert-request-l2-operator-$((REV + 1))" \
      -n alloydb-omni-system --ignore-not-found
    
  2. 从 dbs-al-cert-l2-operator-backup.yaml 文件中移除顶级 metadata.resourceVersion 和 metadata.uid 字段,然后使用服务器端应用来应用 Secret:

    grep -vE '^  (resourceVersion|uid):' dbs-al-cert-l2-operator-backup.yaml \
      | kubectl apply --server-side --force-conflicts -f -
    
  3. 重启 local-controller-manager Deployment,将恢复的证书加载到内存中:

    kubectl rollout restart deployment/local-controller-manager -n alloydb-omni-system
    kubectl rollout status deployment/local-controller-manager -n alloydb-omni-system --timeout=180s
    
  4. 在 check 模式下运行 rotate_cert.sh 脚本,以确认 Certificate Serial 值与备份的证书序列号匹配,并且脚本报告 [OK]:

    ./rotate_cert.sh check
    

    恢复的证书会保留其原始失效日期,因此您仍必须在 Recommended Rotate By 日期当天或之前轮替证书。

  5. 确认恢复后,删除本地备份文件:

    rm -f dbs-al-cert-l2-operator-backup.yaml