在多可用区部署中执行升级

在多可用区部署中,可用区会逐个升级,并且彼此独立。没有跨可用区的全局升级编排。IO 必须在他们想要升级到新版本的组织的每个可用区中执行升级。因此,不同可用区的组织在特定时刻可能使用不同的版本。

本页中概述的升级顺序是先升级一个可用区中的根组织和所有租户组织,然后再升级另一个可用区。在所有可用区都升级完毕后,最后升级全球资源。

本页面介绍了如何通过提供以下类型的信息来继续进行多区域 Google Distributed Cloud (GDC) 隔离升级:

  • 所需访问权限以及获取方式。
  • 您需要的工具。
  • 在执行升级之前应采取哪些步骤。
  • 如何以及以何种顺序为各种 Distributed Cloud 组件执行升级。

以下列表定义了升级的各个组成部分:

目标版本:所有区域都使用相同的目标版本。

一次一个:一次升级一个可用区。在一个可用区中触发升级之前,请确保没有其他可用区正在运行升级。

全局资源:指部署在全局 kube-apiserver 上的 Kubernetes 资源,与每个可用区都有一份副本的可用区资源相对。全球资源遵循不同的生命周期。请注意,它们只需在最后升级一次。

准备

这些网址用于在气隙环境之外进行访问。

在开始升级之前,请确保您已做好以下准备工作:

生成合规性报告

合规性报告会列出以下组织:

  • 已停止支持
  • 错过关键安全补丁

生成合规性报告是一个可选步骤,需要经过身份验证且具有 organization-admin role 的 IO。如需生成报告,请运行以下命令:

  gdcloud system upgrade report-compliance

如需详细了解准备要求,请参阅前提条件部分。

Identity and Access Management

在开始升级之前,请在每个可用区中执行以下操作:

  1. 通过运行 gdcloud auth login 来获取根管理员集群以及所有组织管理员集群的 kubeconfig 文件。

  2. 按照“访问权限和权限提升流程”IAM-R0005 运行手册中的说明添加:

    1. ClusterRoleBinding,其中包含每个区域的根管理员集群中的 cluster-admin ClusterRole
    2. 组织管理员集群,以便获取临时管理员访问权限。

暂停所有可用区中的全球性资源升级

使用获得的 kubeconfig 文件暂停每个可用区中的所有全球性资源升级。

# Pause upgrades to global root admin resources.
kubectl patch kubeapiserver global-root-admin -n global-kube-system -p='{"spec":{"deploymentPolicy":"LocalOnly"}}' --type=merge --kubeconfig=ROOT_ADMIN_KUBECONFIG

# Pause upgrades to global org admin resources.
kubectl patch kubeapiserver global-org-admin -n global-kube-system -p='{"spec":{"deploymentPolicy":"LocalOnly"}}' --type=merge --kubeconfig=ORG_MGMT_API_KUBECONFIG

升级全局根组织

从高层级来看,升级全局根组织包括以下步骤:

  1. 升级所有可用区中的根组织。每个可用区都会单独升级。

    检查当前区域是否为主区域。以下命令在主要可用区中返回“true”,在非主要可用区中不返回任何内容。

    kubectl get ObjectStorageAdminNode -o jsonpath='{.items[*].status.isPrimary}' --kubeconfig=ROOT_ADMIN_KUBECONFIG; echo
    
  2. 升级需要跨区域协调的组件。

  3. 升级全局根管理员资源。

升级前检查

一次升级一个可用区。在开始升级单区域组织之前,请连接到所有其他区域,然后运行以下命令,确保该命令在所有区域中都返回“ready”。如果任何可用区报告未就绪,请勿继续升级。检查相应时区中的组织,以诊断问题。

ORG_NAME=root

[[ $(kubectl --kubeconfig=ROOT_ADMIN_KUBECONFIG get org ${ORG_NAME} -n gpc-system -ojsonpath='{.status.conditions[?(@.type=="Ready")].status}') == 'True' ]] && echo ready || echo not ready

1. 下载并复制更新软件包

以下说明介绍了如何开始使用:

  • 将更新软件包下载到可访问互联网的设备,以便复制到 USB 驱动器。
  • 将更新软件包从 USB 驱动器复制到您的隔离环境。

如需了解更多相关信息,请参阅下载文件,了解如何下载 Distributed Cloud 分发版详细信息;另请参阅转移下载,了解用于将文件转移到气隙环境的可移动存储设备。

  1. 与您的 Google POC 合作,确定升级是否适用于合作伙伴运营的 Distributed Cloud 部署,因此是否应使用合作伙伴模型发布文件。

    PARTNER_OPERATED="IS_PARTNER_OPERATED"
    if [[ ${PARTNER_OPERATED:?} == "true" ]]; then
      RELEASE_SUFFIX="_partner"
      export GCS_BUCKET=private-cloud-release-partner
    else
      RELEASE_SUFFIX=""
      export GCS_BUCKET=private-cloud-release
    fi
    
  2. 从可访问互联网的设备上下载更新软件包到 U 盘。使用您的 Google 联系人 (POC) 提供的版本和摘要详细信息。

    1. 运行 gcloud auth login 以访问 Cloud Storage 存储桶。
    2. 运行带有 --skip-unzip 的脚本,以将更新软件包和下载器脚本提取到当前目录,例如 /home/download

      VERSION=VERSION
      DOWNLOADER=gdch-downloader-prod${RELEASE_SUFFIX}-$VERSION.sh
      gcloud storage cp "gs://${GCS_BUCKET:-private-cloud-release}/$VERSION/$DOWNLOADER*" .
         PUBLIC_KEY=$(cat <<-PUBEND
      -----BEGIN PUBLIC KEY-----
      MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEn46iVSyFXsvuKLZ4dVOr2AqlXDnR
      5cKztkpraexHDxn/ozq03EvrdkRmZkSACFfcaEFyitpraidgAx8sPjvzXQ==
      -----END PUBLIC KEY-----
      PUBEND
      )
      echo "${PUBLIC_KEY}" > "key.pub" openssl dgst -sha256 -verify "key.pub" -signature "${DOWNLOADER}.sig" ${DOWNLOADER} && chmod +x $DOWNLOADER && ./$DOWNLOADER --skip-unzip
      
    3. 如果您要使用合作伙伴模型版本文件进行升级,请按照相关说明准备用于合作伙伴模型分发的软件包。

  3. 将下载器脚本和 gdch 目录都复制到 USB 驱动器。

  4. 将更新从 U 盘复制到 OCIT。将文件放在类似的位置,例如 /home/download/

  5. 在 OCIT 上重新定义这些变量,并提取更新:

    cd /root
    VERSION=VERSION
    DOWNLOADER=gdch-downloader-prod${RELEASE_SUFFIX}-$VERSION.sh
    PUBLIC_KEY=$(cat <<-PUBEND
    -----BEGIN PUBLIC KEY-----
    MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEn46iVSyFXsvuKLZ4dVOr2AqlXDnR
    5cKztkpraexHDxn/ozq03EvrdkRmZkSACFfcaEFyitpraidgAx8sPjvzXQ==
    -----END PUBLIC KEY-----
    PUBEND
    )
    echo "${PUBLIC_KEY}" > "key.pub" openssl dgst -sha256 -verify "key.pub" -signature "${DOWNLOADER}.sig" ${DOWNLOADER} && chmod +x $DOWNLOADER && ./$DOWNLOADER --skip-download
    
  6. 下载器会将发布版本解压缩到 gdch/full-release-1.2.0-gdch.243(例如 /home/download/gdch/full-release-1.2.0-gdch.243)。将此变量分配给完整路径:

    export ARTIFACTS_ROOT='/home/download/gdch/full-release-RELEASE_VERSION'-gdch.BUILD_NUMBER'
    

2. 配置工件注册表升级

如需成功执行升级,您必须完成以下操作:

将制品推送到容器注册表

  1. KUBECONFIG 设置为根管理员集群的 kubeconfig 文件。

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    
  2. 创建所需的 ClusterRoleBindings

    kubectl create clusterrolebinding io-upgrade-admin --clusterrole=upgrade-admin-dc --user=USER_EMAIL
    
    kubectl create clusterrolebinding io-upgrade-debugger --clusterrole=upgrade-debugger --user=USER_EMAIL
    
  3. 创建所需的 RoleBindings

    kubectl create rolebinding io-system-artifact-management-secrets-admin --role=system-artifact-management-secrets-admin --user=USER_EMAIL -n anthos-creds
    
    kubectl create rolebinding io-system-artifact-management-admin --role=system-artifact-management-admin --user=USER_EMAIL -n gpc-system
    
    kubectl create rolebinding io-dnssuffix-viewer --role=dnssuffix-viewer --user=USER_EMAIL -n gpc-system
    
  4. 创建推送 OCI 软件包所需的 RoleBindings

    kubectl create rolebinding infrastructure-operator-sar-harbor-admin --user=gdch-infra-operator-USER_EMAIL --role=sar-harbor-admin -n gpc-system
    

    输出类似于以下内容:

    rolebinding.rbac.authorization.k8s.io/infrastructure-operator-sar-harbor-admin created
    
  5. 按照调整 Artifact Registry 存储空间大小中的说明执行以下操作:

    1. 检查管理员集群中 Artifact Registry 的存储空间使用情况,并验证是否有足够的空间来存储您要推送的制品。
    2. 如果您需要增加可用空间,请按照调整 Artifact Registry 存储空间大小中的步骤操作。
  6. 设置 Docker 配置:

    cp ${ARTIFACTS_ROOT}/docker-credential-gdcloud /usr/bin
    
  7. 配置 Docker 以信任信任库软件包。

    REGISTRY=$(kubectl get harborcluster harbor -n harbor-system -o jsonpath='{.spec.externalURL}' 2>/dev/null);
    if [[ -z "$REGISTRY" ]]; then echo "Harbor external URL not found" >&2; exit 1; fi;
    
    HOST=$(echo "$REGISTRY" | sed 's#https://##');
    if [[ -z "$HOST" ]]; then echo "Invalid registry URL" >&2; exit 1; fi;
    
    DIR="/etc/docker/certs.d/$HOST"; FILE="$DIR/ca.crt"; mkdir -p "$DIR"; chmod 755 "$DIR";
    if [[ ! -f "$FILE" ]]; then
       CERT=$(kubectl get secret trust-store-internal-only -n istio-system -o jsonpath='{.data.ca\.crt}' 2>/dev/null);
       if [[ -z "$CERT" ]]; then echo "Certificate secret not found" >&2;
       exit 1;
       fi;
       echo "$CERT" | base64 -d > "$FILE"; chmod 644 "$FILE";
    else echo "Certificate $FILE already exists"; fi
    
  8. 将制品加载到根管理员集群中的制品注册表中:

    export VERSION=VERSION
    export KUBECONFIG=KUBECONFIG_PATH
    export ARTIFACTS_ROOT=/home/download/gdch/full-release-VERSION
    export PACKAGE_VALIDATION_ROOT_CERT=PACKAGE_VALIDATION_ROOT_CERT_PATH
    
    ${ARTIFACTS_ROOT}/gdcloud auth configure-docker
    ${ARTIFACTS_ROOT}/gdcloud system container-registry load-oci ${ARTIFACTS_ROOT}/oci --pv-root-cert-path=PACKAGE_VALIDATION_ROOT_CERT_PATH --kubeconfig=KUBECONFIG_PATH --use-ip-port=true --show-progress=false
    

    替换以下内容:

    • VERSION:Distributed Cloud 发布版本。例如 1.x.y-gdch.z
    • KUBECONFIG_PATH:通过在根管理员集群中运行 gdcloud auth login 获取的 kubeconfig 文件的路径。
    • PACKAGE_VALIDATION_ROOT_CERT_PATH:软件包验证根证书的路径。您必须使用默认路径 ${ARTIFACTS_ROOT}/staging_root_ca_certificate.crt。包含此路径可验证软件包验证所使用的发布密钥证书。

    如果命令成功执行,最终输出将类似于以下示例:

    I0911 04:05:01.755927 3463529 monitor.go:94] Monitoring ManualDistribution 10.5.23.4-1.12.4.96-bg4ck, starting time: 04:05:01.                                                  │·······
    I0911 04:05:02.002637 3463529 monitor.go:100] [2/2] artifacts distributed and [0/0/0] inProgress/failed/stopped after 246.689693ms                                              │·······
    I0911 04:05:02.002723 3463529 monitor.go:38] Monitoring DistributionPolicy 10.5.23.4-1.12.4.96-jv5p9, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.039545 3463529 monitor.go:44] Created after 36.820059ms.                                                                                                         │·······
    I0911 04:05:02.039599 3463529 monitor.go:94] Monitoring ManualDistribution 10.5.23.4-1.12.4.96-jv5p9, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.045964 3463529 monitor.go:100] [3/3] artifacts distributed and [0/0/0] inProgress/failed/stopped after 6.360571ms                                                │·······
    I0911 04:05:02.045997 3463529 monitor.go:38] Monitoring DistributionPolicy 10.5.23.4-1.12.4.96-bhckh, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.077418 3463529 monitor.go:44] Created after 31.408176ms.                                                                                                         │·······
    I0911 04:05:02.077464 3463529 monitor.go:94] Monitoring ManualDistribution 10.5.23.4-1.12.4.96-bhckh, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.239086 3463529 monitor.go:100] [2/2] artifacts distributed and [0/0/0] inProgress/failed/stopped after 161.610475ms                                              │·······
    I0911 04:05:02.239138 3463529 monitor.go:38] Monitoring DistributionPolicy 10.5.23.4-1.12.4.96-xvlbt, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.248366 3463529 monitor.go:44] Created after 9.220575ms.                                                                                                          │·······
    I0911 04:05:02.248415 3463529 monitor.go:94] Monitoring ManualDistribution 10.5.23.4-1.12.4.96-xvlbt, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.532191 3463529 monitor.go:100] [1/1] artifacts distributed and [0/0/0] inProgress/failed/stopped after 283.756574ms                                              │·······
    I0911 04:05:02.532236 3463529 monitor.go:38] Monitoring DistributionPolicy 10.5.23.4-1.12.4.96-7k4s4, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.544529 3463529 monitor.go:44] Created after 12.282657ms.                                                                                                         │·······
    I0911 04:05:02.544579 3463529 monitor.go:94] Monitoring ManualDistribution 10.5.23.4-1.12.4.96-7k4s4, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.641252 3463529 monitor.go:100] [1/1] artifacts distributed and [0/0/0] inProgress/failed/stopped after 96.652179ms                                               │·······
    I0911 04:05:02.641332 3463529 monitor.go:38] Monitoring DistributionPolicy 10.5.23.4-1.12.4.96-dpj7n, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.645509 3463529 monitor.go:44] Created after 4.169293ms.                                                                                                          │·······
    I0911 04:05:02.645575 3463529 monitor.go:94] Monitoring ManualDistribution 10.5.23.4-1.12.4.96-dpj7n, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.839587 3463529 monitor.go:100] [3/3] artifacts distributed and [0/0/0] inProgress/failed/stopped after 194.004999ms                                              │·······
    I0911 04:05:02.839639 3463529 monitor.go:38] Monitoring DistributionPolicy 10.5.23.4-1.12.4.96-fn94p, starting time: 04:05:02.                                                  │·······
    I0911 04:05:02.844001 3463529 monitor.go:44] Created after 4.361378ms.                                                                                                          │·······
    I0911 04:05:02.844034 3463529 monitor.go:94] Monitoring ManualDistribution 10.5.23.4-1.12.4.96-fn94p, starting time: 04:05:02.                                                  │·······
    I0911 04:05:03.041615 3463529 monitor.go:100] [2/2] artifacts distributed and [0/0/0] inProgress/failed/stopped after 197.567981ms                                              │·······
    I0911 04:05:03.041675 3463529 monitor.go:38] Monitoring DistributionPolicy 10.5.23.4-1.12.4.96-4cxxf, starting time: 04:05:03.                                                  │·······
    I0911 04:05:03.047192 3463529 monitor.go:44] Created after 5.499407ms.                                                                                                          │·······
    I0911 04:05:03.047292 3463529 monitor.go:94] Monitoring ManualDistribution 10.5.23.4-1.12.4.96-4cxxf, starting time: 04:05:03.                                                  │·······
    I0911 04:05:03.241688 3463529 monitor.go:100] [76/76] artifacts distributed and [0/0/0] inProgress/failed/stopped after 194.395913ms
    

    如果您的输出与此示例不同,请按照以下步骤解决最常见的问题:

    • 如果输出包含消息 Package validation root certificate requires upgrade!,请按照轮替软件包验证证书中详述的步骤轮替根证书。
    • 如果 load-oci 失败,请再次运行该操作。如果错误仍然存在,请查看此列表中的其他解决方案。
    • 如果输出中包含消息 Error: unable to create k8sclient: Unauthorized,您必须重新进行身份验证。重复准备步骤以验证 kubeconfig 文件,或运行命令 ${ARTIFACTS_ROOT}/gdcloud auth login 并重试 load-oci 操作。
    • 如果您的输出包含 UNAUTHORIZED: unauthorized to access repository 消息,则表示您没有运行 load-oci 命令所需的权限。请上报此问题,以获取运行此命令所需的角色,或者让拥有所需角色的用户代表您运行此命令。
  9. 对于仅使用合作伙伴型号发布文件进行的升级,请按照相关说明加载合作伙伴型号分发的软件包。

  10. 验证新发布版本的 ReleaseMetadata 对象是否位于根管理员集群中:

    kubectl get releasemetadata.artifact.private.gdc.goog VERSION
    

    VERSION 替换为 Distributed Cloud 版本。例如 1.x.y-gdch.z

    输出示例:

    NAME             AGE
    1.x.y-gdch.z     2m
    
  11. 验证新版本是否在要升级的根组织的可用升级列表中:

    ROOT_NAME=root
    kubectl get organization -n gpc-system ${ROOT_NAME} -ojsonpath='{.status.availableUpgrades}{"\n"}'
    

    例如,对于 1.x.y-gdch.z,我们预期会获得以下输出:

    ["1.x.y-gdch.z"]
    

根组织升级到新版本后,租户组织便可升级到该版本。

3. 升级根组织

3.1. 预升级

  1. KUBECONFIG 设置为根管理员集群的 kubeconfig 文件。

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    
  2. 创建所需的 ClusterRoleBindings

    kubectl create clusterrolebinding io-organization-admin --clusterrole=organization-admin --user=USER_EMAIL
    
  3. 验证根组织的健康状态,如响应 True 所示:

    kubectl get organization -n gpc-system root \
        -ojsonpath='{.status.conditions[?(@.type=="Ready")].status}{"\n"}'
    

    输出示例:

    True
    
  4. 按照 runbook HSM-P0003 中的说明重启所有 HSM。

3.2. 执行根组织的自动升级

升级需要通过 IaC 流程。升级是通过更新相应组织在相应区域中的 OrganizationZonalConfig 对象的版本字段来触发的。

  1. 更新 OrganizationZonalConfig YAML 文件中的版本。删除文件中的 spec.capacities.workloadServers 部分(如果存在)。

    ORG_NAME=root
    ZONE=$(kubectl --kubeconfig ROOT_ADMIN_KUBECONFIG get controlplane cp -n mz-system -ojsonpath='{.spec.zone}')
    sed -i 's/version: .*$/version: VERSION/' IAC_REPO_PATH/iac/infrastructure/global/orgs/${ORG_NAME}/${ORG_NAME}-${ZONE}.yaml
    
  2. 暂存并提交文件更改。

    git add "IAC_REPO_PATH/iac/infrastructure"
    git commit
    
  3. 创建合并请求。

    git checkout -b ${USERNAME1}-branch
    git -c http.sslVerify=false push -o merge_request.create origin ${USERNAME1}-branch
    

升级开始时,系统会创建一个 OrganizationUpgrade 对象。验证是否已在根管理员集群的可用区中创建根 OrganizationUpgrade 对象。

kubectl get -n gpc-system organizationupgrade root -o yaml --kubeconfig ROOT_ADMIN_KUBECONFIG

如果找不到 OrganizationUpgrade,请按照 IAC-R0001 运行手册进行问题排查。

3.3. 升级后检查

  1. 验证升级结果:

    1. 检查根组织的 Organization 对象。验证您是否看到状态条件 READYTrue

      kubectl -n gpc-system get organization root
      

      输出示例:

      NAME   READY
      root   True
      
    2. 验证 Organization.Status.Version 是否显示确切的字符串 1.x.y-gdch.z

      kubectl -n gpc-system get organization root -o jsonpath='{.status.version}{"\n"}'
      

      验证的输出示例:

      1.13.3-gdch.5548
      
  2. 检查根组织中的子组件故障:

    1. 检查显示 ReconciliationErrorReconciling 状态的子组件。将 kubeconfig 指向 ROOT_ADMIN_KUBECONFIG

      export KUBECONFIG=/root/release/root-admin/root-admin-kubeconfig
      export CLUSTER_NAMESPACE=root
      echo "Subcomponents with failures"
      kubectl get subcomponent -n ${CLUSTER_NAMESPACE} -o json | jq -r '.items[] |  select(.status.conditions[]?.reason == "ReconciliationError") | select(.status.featureDisabled != true) |  "Sub-Component: \(.metadata.name) - \(.status.conditions[]?.message)"'
      echo "Subcomponents still reconciling"
      kubectl get subcomponent -n ${CLUSTER_NAMESPACE} -o json | jq -r '.items[] |  select(.status.conditions[]?.reason == "Reconciling") | select(.status.featureDisabled != true) | select( "\(.status)" | contains("PreinstallPending") | not) | "Sub-Component: \(.metadata.name) - \(.status.conditions[]?.message)"'
      
    2. 如需了解错误,请查看版本说明已知问题,了解是否有解决方法;否则,请与 Distributed Cloud 联系以进行问题排查。

  3. 如果跳过了预检或后检,请在升级完成后移除注释:

    示例:

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    kubectl annotate -n gpc-system organization ORG_NAME \
        upgrade.private.gdc.goog/skip-preflight-check-
    
    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    kubectl annotate -n gpc-system organization ORG_NAME \
        upgrade.private.gdc.goog/skip-postflight-check-
    

完成所有可用区中的根组织升级

在一个地区完成升级后,建议先检查该地区是否仍在正常运行,然后再继续升级下一个地区。

针对其余区域中的根组织重复执行第 1 步到第 3 步。当所有可用区的根组织都已升级时,请继续执行后续步骤。

4. 升级全局资源

全局资源应位于所有可用区中的最低版本。连接到锚定区域并运行以下命令,以启动全球性资源升级流程。

# Annotate appropriate versions for all the operable components.
MAP=$(kubectl get kubeapiserver root-admin -n root -ojsonpath='{.metadata.annotations}' --kubeconfig ROOT_ADMIN_KUBECONFIG | jq -r 'to_entries | map("\(.key) \(.value)") | .[] | select(startswith("lcm.private.gdc.goog/oc-version-"))')

echo "${MAP}" | while read KV; do
   SPLIT=(${KV}); KEY=${SPLIT[0]}; VALUE=${SPLIT[1]}
   echo "Annotating global KubeAPIServer with ${KEY}: ${VALUE}"
   kubectl annotate kubeapiserver global-root-admin -n global-kube-system --overwrite ${KEY}=${VALUE} --kubeconfig ROOT_ADMIN_KUBECONFIG
done

# Trigger the global resource upgrade on global root admin.
kubectl annotate kubeapiserver global-root-admin -n global-kube-system --overwrite lcm.private.gdc.goog/paused-remote=false --kubeconfig ROOT_ADMIN_KUBECONFIG
kubectl patch kubeapiserver global-root-admin -n global-kube-system -p='{"spec":{"deploymentPolicy":"AllowAll"}}' --type=merge --kubeconfig ROOT_ADMIN_KUBECONFIG

此过程可能需要几分钟时间。运行以下命令,验证全球性资源升级是否已完成。该命令不应报告任何失败。

# Verify that Components are all successfully rolled out on global root admin.
echo "${MAP}" | while read KV; do
   SPLIT=(${KV}); VALUE=${SPLIT[1]}; OC=$(echo ${VALUE} | cut -d- -f1)
   [[ -n ${OC} ]] || continue
   ROLLOUT=$(kubectl get componentrollout ${OC} -n global-kube-system -o json --ignore-not-found --kubeconfig ROOT_ADMIN_KUBECONFIG)
   [[ -n ${ROLLOUT} ]] || continue
   if [[ $(echo ${ROLLOUT} | jq -r '.spec.componentRef.name') != ${VALUE} ]] ; then
      echo "${OC} rollout trigger failed"; continue
   fi
   if [[ $(echo ${ROLLOUT} | jq -r '.status.allSubcomponentsReady') != 'true' ]] ; then
      echo "${OC} rollout completion failed. Use 'kubectl describe componentrollout ${OC} -n global-kube-system --kubeconfig ROOT_ADMIN_KUBECONFIG' to check for error messages."
   fi
done && echo "Global component rollout check finished."

5. 跨可用区组件升级

在 GDC 多可用区宇宙中,某些可操作的组件需要跨可用区协调才能完成升级。

在此步骤中,以下可操作组件会升级。

范围 可操作的组件
基础架构 IAC
基础架构 SIEM

如需升级 IAC 可操作组件,请按照 IAC-R0016 运行手册操作。

如需升级 SIEM 可操作组件,请按照 SIEM-G0008 运行手册操作。

6. Anycast 子网的手动升级

运行以下脚本,将必要的标签添加到全局根 API 服务器中的任播子网:

#!/bin/bash

# Description:
# This script ensures that specific Subnet resources in Kubernetes have the
# correct label applied. This is necessary for anycast features to function correctly.
#
# The script is idempotent and can be run multiple times safely.
# It requires the path to a valid global root kubeconfig file as a command-line argument.

# --- Configuration ---
set -o nounset

# The names of the Subnet resources to update.
readonly SUBNET_NAMES=(
  "infra-vpc-anycast-cidr"
  "data-global-anycast-cidr"
  "admin-global-anycast-cidr"
)

# The label that will be applied to the subnets.
readonly LABEL_KEY="ipam.gdc.goog/usage"
readonly LABEL_VALUE="global-anycast-root-range"

# The Kubernetes resource type for the subnets.
readonly SUBNET_RESOURCE_TYPE="subnets"

# Timeout for kubectl commands in seconds.
readonly KUBECTL_TIMEOUT="30s"

log_error() {
  echo "[ERROR] $(date +'%Y-%m-%dT%H:%M:%S%z'): $*" >&2
}

main() {
  # --- Argument Validation ---
  if [[ $# -ne 1 ]]; then
    echo "Usage: $0 <path-to-kubeconfig-file>"
    echo "Example: $0 /root/release/root-admin/global-root-admin-kubeconfig"
    exit 1
  fi

  local KUBECONFIG_PATH="$1"

  if [[ ! -f "${KUBECONFIG_PATH}" ]]; then
      log_error "Kubeconfig file not found at: ${KUBECONFIG_PATH}"
      exit 1
  fi

  if ! command -v kubectl &> /dev/null; then
    log_error "kubectl command not found. Please ensure it is installed and in your system's PATH."
    exit 1
  fi

  if ! command -v timeout &> /dev/null; then
    log_error "timeout command not found. Please ensure 'coreutils' is installed."
    exit 1
  fi

  if ! command -v jq &> /dev/null; then
    log_error "jq command not found. Please ensure it is installed and in your system's PATH."
    exit 1
  fi

  echo "Starting Subnet labeling process using kubeconfig: ${KUBECONFIG_PATH}"

  # --- Pre-flight Check and Data Fetch ---
  echo "Verifying access and fetching all Subnet resources (timeout in ${KUBECTL_TIMEOUT})..."
  local all_subnets_json

  if ! all_subnets_json=$(timeout "${KUBECTL_TIMEOUT}" kubectl get --kubeconfig="${KUBECONFIG_PATH}" "${SUBNET_RESOURCE_TYPE}" --all-namespaces -o json 2>/dev/null); then
      log_error "Failed to list Subnet resources. The command timed out or returned an error. Please check cluster connectivity and permissions."
      exit 1
  fi

  if [[ -z "${all_subnets_json}" ]] || [[ $(jq '.items | length' <<< "${all_subnets_json}") -eq 0 ]]; then
      echo "No subnet resources found in the cluster. Exiting."
      exit 0
  fi
  echo "Access verified. Processing subnets..."

  local processed_count=0
  local found_count=0
  local subnet_regex
  subnet_regex=$(printf "|%s" "${SUBNET_NAMES[@]}")
  subnet_regex="^(${subnet_regex:1})$"

  # jq query to output: namespace  name  label_value (or null)
  echo "${all_subnets_json}" | jq -r ".items[] | [.metadata.namespace, .metadata.name, (.metadata.labels | .[\"${LABEL_KEY}\"] // \"\")] | @tsv" |
  while IFS=$'\t' read -r namespace name current_value; do
    if [[ -z "${name}" ]]; then continue; fi

    if [[ ! "${name}" =~ ${subnet_regex} ]]; then
        continue
    fi

    ((found_count++))
    echo "Found target subnet: '${name}' in namespace '${namespace}'"

    if [[ "${current_value}" == "${LABEL_VALUE}" ]]; then
        echo "  - Subnet already has the correct label. Skipping."
        ((processed_count++))
        continue
    fi

    echo "  - Applying label '${LABEL_KEY}=${LABEL_VALUE}'..."
    if ! timeout "${KUBECTL_TIMEOUT}" kubectl label --kubeconfig="${KUBECONFIG_PATH}" --namespace="${namespace}" "${SUBNET_RESOURCE_TYPE}" "${name}" "${LABEL_KEY}=${LABEL_VALUE}" --overwrite > /dev/null; then
        log_error "Failed to apply label to subnet '${name}' in namespace '${namespace}'. The command timed out or returned an error."
    else
        echo "  - Successfully labeled subnet."
        ((processed_count++))
    fi
  done

  # --- Final Summary ---
  echo "---"
  if [[ ${found_count} -eq 0 ]]; then
    echo "No target anycast subnets were found in the cluster."
  else
    echo "Finished processing. Found ${found_count} and validated ${processed_count} target subnet(s)."
  fi

  echo "Subnet labeling process completed."
}

# Execute the main function with command-line arguments.
main "$@"

脚本成功执行后,如果之前应用过手动任播解决方法,请还原该解决方法。

7. SyncServer 的手动升级

在此步骤中,以下可操作组件会升级。

范围 可操作的组件
基础架构 NTP

此固件升级不依赖于任何其他步骤,可以在任何时间完成。

集群只有一个 SyncServer,因此无法在高可用性模式下运行。升级会导致 SyncServer 在一段时间内不可用。集群将继续使用自己的不太精确的时钟来计时,这不会产生任何明显的影响。

建议您一次性完成此流程(不要留到晚上或周末),以免出现时间漂移。

7.1. SyncServer 升级流程

以下命令应从提取的更新软件包的发布目录运行。

  1. 找到要提取的最新固件:

    ${ARTIFACTS_ROOT}/gdcloud artifacts tree ${ARTIFACTS_ROOT}/oci/ | grep syncserver | grep -v .sig$
    

    文件名包含固件的版本。

    输出示例:

    │   ├── gdch-syncserver-firmware/syncserver:5.1.2
    
  2. 仅复制文件名并将其分配给以下变量:

    export SYNCSERVER_VERSION=syncserver:5.1.2
    
  3. 从 OCI 映像中提取固件:

    ${ARTIFACTS_ROOT}/gdcloud artifacts extract ${ARTIFACTS_ROOT}/oci syncserver_firmware --image-name=gdch-syncserver-firmware/${SYNCSERVER_VERSION:?}
    
  4. 提取固件:

    tar -xvzf syncserver_firmware/gdch-syncserver-firmware/syncserver.tar.gz
    

    您必须在输出目录中看到一个 *.dat 文件和一个 *updater.zip 文件。

  5. 按照 runbook NTP-P0002 - 访问 SyncServer 界面操作。

    1. 依次前往帮助 -> 关于 -> 软件版本。如果已安装的软件版本等于或高于所提供的固件版本,则无需更新固件,可以跳过后续步骤。

    2. 在 SyncServer 界面中,依次前往 Admin -> Upgrade。上传了 Authorization File 中的 syncserver_s650_license.datUpgrade File 中的 syncserver_s650_updater.zip。然后点击“安装”。

    在信息中心内验证

升级全球租户组织

从全局租户组织升级到全球组织的大致步骤如下:

  1. 在所有可用区中升级租户组织。每个可用区都会单独升级。

    检查当前区域是否为主区域。以下命令在主要可用区中返回“true”,在非主要可用区中不返回任何内容。

    kubectl get ObjectStorageAdminNode -o jsonpath='{.items[*].status.isPrimary}' --kubeconfig=ROOT_ADMIN_KUBECONFIG; echo
    
  2. 升级全局租户组织资源。

升级前检查

一次升级一个可用区。在开始升级单区域组织之前,请连接到所有其他区域,然后运行以下命令,确保该命令在所有区域中都返回“ready”。如果任何可用区报告未就绪,请勿继续升级。检查相应时区中的组织,以诊断问题。

ORG_NAME=ORG_NAME

[[ $(kubectl --kubeconfig=ROOT_ADMIN_KUBECONFIG get org ${ORG_NAME} -n gpc-system -ojsonpath='{.status.conditions[?(@.type=="Ready")].status}') == 'True' ]] && echo ready || echo not ready

确保所有集群都处于运行状态,并且所有节点池都处于就绪状态。如果存在,请先修正这些问题,然后再开始升级。

ORG_NAME=ORG_NAME
kubectl get nodepools -n ${ORG_NAME} --kubeconfig ROOT_ADMIN_KUBECONFIG -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,READY:.status.conditions[?(@.type=="Ready")].status'
# Example output
# NAMESPACE   NAME                                        READY
# org1        admin-control-plane-node-pool               True
# org1        data-plane-pool-o2-standard1-96-gdc-metal   True

kubectl get cluster -n mks-system --kubeconfig ORG_MGMT_API_KUBECONFIG
# Example output
# NAME                    STATE     K8S VERSION
# g-org1-perimeter        Running   1.30.6-gke.300
# g-org1-shared-service   Running   1.30.6-gke.300

kubectl get nodepool -A --kubeconfig ORG_INFRA_KUBECONFIG -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,READY:.status.conditions[?(@.type=="Ready")].status'
# Example output
# NAMESPACE                       NAME                                                     READY
# g-org1-perimeter-cluster        control-plane-node-pool                                  True
# g-org1-perimeter-cluster        perimeter-admin-node-pool                                True
# g-org1-perimeter-cluster        perimeter-data-node-pool                                 True
# g-org1-shared-service-cluster   control-plane-node-pool                                  True
# g-org1-shared-service-cluster   dbs-billing-system-billing-dbcluster-n2-standard-4-gdc   True
# g-org1-shared-service-cluster   shared-service-default-worker                            True

1. 升级租户组织

此步骤会升级租户组织(组织管理员、系统和服务集群)中管理平面集群上的 Kubernetes 版本、插件和可操作组件。

升级的总时长取决于升级的阶段数。租户组织的自动升级可能会造成中断,并且需要维护窗口。

1.1. 准备工作

如需配置维护窗口,请参阅为租户组织升级配置维护窗口

本文提供了有关如何使用 kubectl CLI 命令或基础设施即代码 (IaC) 命令来启动租户组织升级的说明。如需使用 IaC 命令,请先配置 IaC:

  • 基础设施即代码设置
  • 配置基础架构即代码

    如需使用 nomos 验证基于 IaC 的步骤中所述的状态(作为一种可选方案),您必须安装 nomos 命令行工具。如需获取 nomos 安装和使用说明,请在可访问互联网的计算机上访问 https://cloud.google.com/anthos-config-management/docs/how-to/nomos-command

IaC

使用 IAC 在开始租户组织升级之前设置 clusterrolebinding

  1. 进入 iac/infrastructure/zonal/zones/ZONE_NAME/{ORG} 目录。
  2. 进入已创建的 IO 目录。如果该目录不存在,请创建一个新目录。
  3. 添加一个 YAML 文件,以将 io-organization-admin 集群角色分配给 IO。例如:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: iac-binding-$USER-io-organization-admin
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: io-organization-admin
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: USER_EMAIL
    
  4. 更新 kustomatization.yaml 以包含新创建的文件。如果 kustomatization.yaml 不存在,请创建一个新文件:

    kind: Kustomization
    metadata:
      name: org-1-admin-kustomization
    resources:
    - FILE_NAME.yaml
    
  5. 提交 IAC 中的更改

kubectl

在开始使用 kubectl 升级租户组织之前,设置 clusterrolebinding

  1. KUBECONFIG 设置为根管理员集群的 kubeconfig 文件。

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG`
    
  2. 创建所需的 ClusterRoleBindings

    kubectl create clusterrolebinding io-organization-admin --clusterrole=organization-admin --user=USER_EMAIL`
    
  3. 在完成从较低版本的 Distributed Cloud 升级到 1.13.x 及更高版本之前,请按照 runbook BIL-R0014 中的说明手动生成本月费用账单,账单的费用范围为本月初到今天的开始时间。您将丢失在分布式云组织升级过程中创建的费用数据。

1.2. 启动升级

租户组织升级也是通过 IaC 触发的,方法是更新相应组织在区域中的 OrganizationZonalConfig 对象的版本字段。详细信息如下:

  1. 更新 OrganizationZonalConfig YAML 文件中的版本。

    ORG_NAME=ORG_NAME
    ZONE=$(kubectl --kubeconfig ROOT_ADMIN_KUBECONFIG get controlplane cp -n mz-system -ojsonpath='{.spec.zone}')
    sed -i 's/version: .*$/version: VERSION/' IAC_REPO_PATH/iac/infrastructure/global/orgs/root/${ORG_NAME}-${ZONE}.yaml
    
  2. 暂存并提交文件更改。

    git add "IAC_REPO_PATH/iac/infrastructure"
    git commit
    
  3. 创建合并请求。

    git checkout -b ${USERNAME1}-branch
    git -c http.sslVerify=false push -o merge_request.create origin ${USERNAME1}-branch
    

如果升级已启动,系统会创建 OrganizationUpgrade 对象。验证 OrganizationUpgrade 对象是否已在根管理员集群的可用区中创建。

kubectl get -n gpc-system organizationupgrade ORG_NAME -o yaml --kubeconfig ROOT_ADMIN_KUBECONFIG

如果找不到 OrganizationUpgrade,请按照 IAC-R0001 运行手册进行问题排查。

1.3. 升级

  1. 升级执行时间为具有 timeWindow 且该 timeWindow 位于管理员用户(也称为 PA)指定的维护窗口内时。查看预定的 timeWindow

    kubectl -n gpc-system get organizationupgrade ORG_NAME -o yaml
    

    以下是上述命令的典型响应:

    apiVersion: upgrade.private.gdc.goog/v1alpha1
    kind: OrganizationUpgrade
    metadata:
      creationTimestamp: "2022-08-22T01:09:03Z"
      generation: 1
      name: org-1
      namespace: gpc-system
      ownerReferences:
      - apiVersion: resourcemanager.gdc.goog/v1alpha1
        blockOwnerDeletion: true
        controller: true
        kind: Organization
        name: org-1
        uid: 6998cfc1-bee4-4f6d-baf2-9c0a90ef93bb
      resourceVersion: "1214182"
      uid: 1affc1df-b9ac-4343-8e61-18736781a990
    spec:
      currentVersion: 1.8.0-gdch.476
      organizationRef:
        name: org-1
      targetVersion: 1.8.1-gdch.0
      timeWindow:
        end: "2022-08-28T04:00:00Z"
        start: "2022-08-28T00:00:00Z"
    

    在上面的示例中,升级到 1.8.1-gdch.0 的时间安排是在 "2022-08-28T00:00:00Z""2022-08-28T04:00:00Z" 之间。

    升级开始时,系统会创建一个 OrganizationUpgrade 对象,如前面的输出示例中所示的 kind: OrganizationUpgrade

    kind: OrganizationUpgrade
    
  2. 通过将第 1 步中的命令附加 -w,使用相应的升级对象监控升级的总体状态。例如,如需持续查询 ORG_NAME 以了解升级状态,请运行以下命令:

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    kubectl get -n gpc-system organizationupgrade ORG_NAME -o yaml -w
    
  3. 您可以使用以下命令查看升级的各个阶段及其状态:

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    kubectl get -n gpc-system organizationupgrade ORG_NAME -o jsonpath='{.status.conditions}' | \
    jq -r '["Stage", "Status", "Reason", "Message"], ["---", "---", "---", "---"], (.[] | [.type, .status, .reason, .message]) | @tsv' | column -ts $'\t'
    

    Succeeded 阶段是指总体升级状态。Expired 阶段用于表示升级已超过原定计划时间。所有其他阶段均指正在进行的升级的步骤。 状态 True 表示已完成的步骤,状态 Unknown 表示升级的当前步骤。

    如果预检检查失败,但您确信此预检检查失败是误报,请替换并跳过预检检查选项:

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    kubectl annotate -n gpc-system organization ORG_NAME \
        upgrade.private.gdc.goog/skip-preflight-check=ok
    

    如果后检查失败,但您确信该失败是误报,请替换并跳过飞行后检查:

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    kubectl annotate -n gpc-system organization ORG_NAME \
        upgrade.private.gdc.goog/skip-postflight-check=ok
    
  4. 如果使用 IAC 升级了租户组织,且 organizationupgrade 状态显示为“成功”,但租户组织的 Organization 不处于“就绪”状态,请应用以下解决方法。

    添加此注解:configmanagement.gke.io/managed: disabled 使用 IAC 将用户添加到组织。 监控 Organization 状态处于就绪状态。

  5. 组织升级现在应进入下一阶段,服务或节点的状态将变为“完成”:

    Last Transition Time: 2024-08-27T22:44:09Z
      Message:             observed the following reason: [JobRunning]
      Observed Generation: 614
      Reason:              Complete
      Status:              True
      Type:                service/Node
    

    组织升级可能需要 15 分钟才能继续。

1.4. 升级后检查

  1. 检查组织的 Organization 对象。条件 READY 必须显示为 True

    kubectl -n gpc-system get organization ORG_NAME
    

    输出示例:

    NAME   READY
    org-1  True
    
  2. 勾选 Organization.Status.Version。它必须显示目标版本的确切字符串:

    kubectl -n gpc-system get organization ORG_NAME -o jsonpath='{.status.version}{"\n"}'
    

    输出示例:

    1.13.3-gdch.5548
    

    还原注解以忽略维护窗口:

    kubectl annotate organization ORG_NAME -n=gpc-system  \
        "upgrade.private.gdc.goog/ignore-maintenance-window-" \
        --kubeconfig=ROOT_ADMIN_KUBECONFIG
    
  3. 检查升级后的租户组织中是否存在子组件故障:

    1. 检查显示 ReconciliationErrorReconciling 状态的子组件。将 kubeconfig 指向 ORG_MGMT_API_KUBECONFIG

      export KUBECONFIG=ORG_MGMT_API_KUBECONFIG
      
      echo "Subcomponents with failures"
      kubectl get subcomponent -A -o json | jq -r '.items[] |  select(.status.conditions[]?.reason == "ReconciliationError") |  "Sub-Component: \(.metadata.name) - \(.status.conditions[]?.message)"'
      echo "Subcomponents still reconciling"
      kubectl get subcomponent -A -o json | jq -r '.items[] |  select(.status.conditions[]?.reason == "Reconciling") | select( "\(.status)" | contains("PreinstallPending") | not) | "Sub-Component: \(.metadata.name) - \(.status.conditions[]?.message)"'
      
    2. 如需了解错误,请查看版本说明已知问题,了解解决方法;否则,请与 Distributed Cloud 联系以进行问题排查。

  4. 如果跳过了预检或后检,请在升级完成后移除注释:

    示例:

    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    kubectl annotate -n gpc-system organization ORG_NAME \
        upgrade.private.gdc.goog/skip-preflight-check-
    
    export KUBECONFIG=ROOT_ADMIN_KUBECONFIG
    kubectl annotate -n gpc-system organization ORG_NAME \
        upgrade.private.gdc.goog/skip-postflight-check-
    

1.5. 启动非预定升级

如果您有紧急需求(例如紧急安全补丁要求),可以在 maintenanceWindow 之外触发即时租户-组织升级。这仅在租户组织中需要,因为根组织已立即触发升级。

使用根管理员 kubeconfig 运行此命令。您需要添加注释的组织自定义资源仅存在于根管理员集群中。您无需为此流程安排时间窗口。

  1. 为租户组织修补组织 spec/version

    export VERSION=$(kubectl get releasemetadata -ojson | jq -r '.items[] | select(.metadata.name | contains("1.13.3")) | .metadata.name')
    echo $VERSION
    
    # Example output
    # 1.13.3-gdch.5548
    
    kubectl patch -n gpc-system organization ORG_NAME --type='json' \
      -p='[{"op":"replace","path":"/spec/version","value":"'${VERSION}'"}]' \
        --kubeconfig=ROOT_ADMIN_KUBECONFIG
    
  2. 通过应用 ignore-maintenance-window 注解并重启 organizationupgrade,立即启动 tenant-org upgrade

  3. 监控升级状态:

    # kubectl -n gpc-system get organizationupgrade org-1 -o yaml
    
  4. 执行升级后检查

  5. 紧急升级完成后,请恢复使用预定的时间窗口:

    kubectl annotate organization ORG_NAME -n=gpc-system  \
          "upgrade.private.gdc.goog/ignore-maintenance-window-" \
          --kubeconfig=ROOT_ADMIN_KUBECONFIG
    

2. DNS 升级

2.1 创建转发地区

  1. 为根管理员集群导出 kubeconfig

    export KUBECONFIG=/root/release/root-admin/root-admin-kubeconfig
    
  2. 使用正向区域配置 OCIT_DOMAIN。 将 OCIT_DOMAIN 替换为您的 OCIT 域名,并将端点替换为 OC DNS IP 地址:

    kubectl apply -f - <<EOF
    apiVersion: network.private.gdc.goog/v1alpha1
    kind: DNSZone
    metadata:
      namespace: dns-system
      name: ocit-domain
    spec:
      domainName: OCIT_DOMAIN
      forwardingConfig:
        # Set to OC DNS IPs (the AD domain controllers)
        endpoints:
          - 192.0.2.0
          - 192.0.2.1
        replicateToTenantOrg: true
    EOF
    

    输出类似于以下示例:

    dnszone.network.private.gdc.goog/ocit-domain created
    
  3. 如果更改未应用,请重启部署:

    kubectl rollout restart deployment -n dns-system gpc-coredns-forwarder
    

    此 DNS 更改会传播到 GDC 中的所有集群。

  4. 使用根管理员 kubeconfig,验证 OCIT 网域解析是否按预期运行:

    NAMESERVER=$(kubectl -n dns-system get service gpc-coredns-forwarder-udp | \
      awk '/[0-9]\./ {print $4}')
    dig +short @${NAMESERVER} fs.OCIT_DOMAIN
    
  5. 为组织管理员集群导出 kubeconfig

    export KUBECONFIG=/root/release/org-admin/org-admin-kubeconfig
    
  6. 应用组织管理员 kubeconfig,并验证 OCIT 网域解析是否按预期运行:

    NAMESERVER=$(kubectl -n dns-system get service gpc-coredns-infra-forwarder | \
      awk '/[0-9]\./ {print $4}')
    dig +short @${NAMESERVER} fs.OCIT_DOMAIN
    

2.2 启用递归解析器

对于 v1 组织,请按照 DNS-R0027 运行手册中的步骤在组织管理员集群中启用递归解析器。

完成所有可用区中的租户组织升级

在一个地区完成升级后,建议先检查该地区是否仍在正常运行,然后再继续升级下一个地区。

针对其余可用区中的租户组织重复执行第 1 步到第 2 步。当所有可用区都已升级租户组织后,继续执行后续步骤。

3. 升级全局资源

全局资源应位于所有可用区中的最低版本。连接到锚定区域并运行以下命令,以启动全球性资源升级流程。

# Annotate appropriate versions for all the operable components.
ORG_NAME=ORG_NAME
MAP=$(kubectl get kubeapiserver ${ORG_NAME}-admin -n ${ORG_NAME} -ojsonpath='{.metadata.annotations}' --kubeconfig ROOT_ADMIN_KUBECONFIG | jq -r 'to_entries | map("\(.key) \(.value)") | .[] | select(startswith("lcm.private.gdc.goog/oc-version-"))')

# Trigger the global resource upgrade on global org admin.
kubectl annotate kubeapiserver global-org-admin -n global-kube-system --overwrite lcm.private.gdc.goog/paused-remote=false --kubeconfig ORG_MGMT_API_KUBECONFIG
kubectl patch kubeapiserver global-org-admin -n global-kube-system -p='{"spec":{"deploymentPolicy":"AllowAll"}}' --type=merge --kubeconfig ORG_MGMT_API_KUBECONFIG

此过程可能需要几分钟时间。运行以下命令,验证全球性资源升级是否已完成。该命令不应报告任何失败。

# Verify that Components are all successfully rolled out on global org admin.
echo "${MAP}" | while read KV; do
   SPLIT=(${KV}); VALUE=${SPLIT[1]}; OC=$(echo ${VALUE} | cut -d- -f1)
   [[ -n ${OC} ]] || continue
   ROLLOUT=$(kubectl get componentrollout ${OC} -n global-kube-system -o json --ignore-not-found --kubeconfig ORG_MGMT_API_KUBECONFIG)
   [[ -n ${ROLLOUT} ]] || continue
   if [[ $(echo ${ROLLOUT} | jq -r '.spec.componentRef.name') != ${VALUE} ]] ; then
      echo "${OC} rollout trigger failed"; continue
   fi
   if [[ $(echo ${ROLLOUT} | jq -r '.status.allSubcomponentsReady') != 'true' ]] ; then
      echo "${OC} rollout completion failed. Use 'kubectl describe componentrollout ${OC} -n global-kube-system --kubeconfig ORG_MGMT_API_KUBECONFIG' to check for error messages."
   fi
done && echo "Global component rollout check finished."

4. 升级 Tenable SC

  1. 运行 GDCH Doctor 以确定是否需要升级 -

      gdcloud system doctor diagnose instance --include-ocs=vuln --root-admin-kubeconfig=${ROOT_ADMIN_CLUSTER_KUBECONFIG:?}
    
  2. 如果 tenable_sc_upgrade_readiness 验证器失败,则需要升级映像,请按照以下步骤在 OI 服务组织中升级 Tenable SC -

    1. 获取虚拟机名称:

       VIRTUAL_MACHINE_NAME=$(kubectl --kubeconfig ${OI_SERVICES_ORG_INFRA_KUBECONFIG:?} get virtualmachine -n tenablesc-system -o custom-columns=NAME:.metadata.name | sort -r -k 1 | head -1)
      
    2. 将虚拟机的 runningState 标记为 Stopped

       kubectl --kubeconfig ${OI_SERVICES_ORG_MGMT_KUBECONFIG:?} patch virtualmachines.virtualmachine.gdc.goog ${VIRTUAL_MACHINE_NAME:?} -n tenablesc-system --type merge --patch '{"spec":{"runningState":"Stopped"}}'
      
    3. 卸载虚拟机的现有 Helm 图表:

       VIRTUAL_MACHINE_NAME=$(kubectl --kubeconfig ${OI_SERVICES_ORG_INFRA_KUBECONFIG:?} get virtualmachine -n tenablesc-system -o custom-columns=NAME:.metadata.name | sort -r -k 1 | head -1)
       kubectl --kubeconfig ${OI_SERVICES_ORG_MGMT_KUBECONFIG:?} patch virtualmachines.virtualmachine.gdc.goog ${VIRTUAL_MACHINE_NAME:?} -n tenablesc-system --type merge --patch '{"spec":{"runningState":"Stopped"}}'
       helm uninstall tenablesc-vms -n tenablesc-system --kubeconfig ${ORG_MGMT_KUBECONFIG:?}
      
    4. 按照安装 Tenable.SC 中的步骤全新设置 Tenable SC

升级后清理

移除在 Identity and Access Management 部分创建的 ClusterRoleBinding 资源。

为租户组织升级配置维护窗口

如需升级租户组织,请验证您是否已获分配正确的查看者和管理员角色,如预定义角色说明项目角色定义页面中所述,以便登录 kubectl 命令行界面 (CLI) 和控制台界面 (UI)。如果您没有这些角色,请按照授予对项目资源的访问权限页面上的说明授予这些角色,或请求授予这些角色。

如需配置维护窗口,您必须拥有必需的角色。确保您已被分配以下预定义角色:

默认情况下,次要升级有一个 MaintenanceWindow,补丁程序升级有一个 MaintenanceWindow。次要升级会增强功能或对之前的修订版本进行更改,这是一种软件包升级,例如修复 bug。补丁升级用于解决特定问题或漏洞。配置默认补丁 MaintenanceWindow,以根据定义的时间表开始补丁升级。

如需配置维护窗口,请使用 CLI 和 kubectl 命令修改 MaintenanceWindow 资源的 RRULETimeWindow 字段。这会安排升级。如需了解有关 RRULE 的信息,请访问 https://pkg.go.dev/github.com/teambition/rrule-go

如需使用 kubectl CLI 命令,请点击 kubectl 标签页。如需查看基于界面的说明,请点击“控制台”标签页。

控制台

  1. 登录组织界面

  2. 修改维护窗口时间表。前往维护标签页,然后点击修改

    维护窗口

    图 1. 维护窗口

  3. 系统会打开修改维护窗口界面。使用该窗口重新配置 PatchMinor 时间窗口:

    重新配置补丁和次要更新

    图 2. 重新配置补丁和次要更新

  4. 指定或修改补丁版本 开始时间时长,以及星期几。

    修改次要版本开始时间长度重复次数天数

    保存重新配置

    图 3.保存重新配置

  5. 点击保存以应用更改。

  6. 如果保存的更改会影响重复周期(例如,如果您更改了星期几或月份),系统会显示一个对话框。如需确认更改,请点击继续

    点击“继续”

    图 4. 点击“继续”

  7. 以下示例显示了根据您的配置更改更新后的预定升级。请注意,每个“待处理”状态旁边都有一个跳过链接。使用此命令可跳过预定的待处理升级。

    包含“跳过”按钮的预定升级视图
    图 5. 查看计划升级,并为每个升级提供跳过选项

kubectl

  1. 登录 kubectl CLI。 在“CLI”标签页中找到这些说明。 在继续之前,请确保您对组织管理员集群拥有正确的访问权限。

  2. 您可以修改 MaintenanceWindow 中的三个字段,以配置租户组织升级发生的 timeWindow。以下命令展示了对补丁升级维护窗口的修改。次要升级的修改类似。

    # 1. The first change is to the RRULE
    # For patch-upgrades to happen, for example, every Thursday instead of Sunday:
    kubectl patch -n gpc-system maintenancewindow patch-upgrade \
      --type='json' \
      -p='[{"op":"replace","path":"/spec/recurrence","value":"FREQ=WEEKLY;BYDAY=TH"}]'
    
    # 2. Modify the start time of the upgrade in UTC.
    export S_TIME = 2022-04-03T04:00:00Z
    kubectl patch -n gpc-system maintenancewindow patch-upgrade \
      --type='json' \
      -p='[{"op":"replace","path":"/spec/timeWindow/start","value":"'${S_TIME}'"}]'
    
    # 3. Modify the end time of the upgrade in UTC.
    export E_TIME = 2022-04-03T04:00:00Z
    kubectl patch -n gpc-system maintenancewindow patch-upgrade \
      --type='json' \
      -p='[{"op":"replace","path":"/spec/timeWindow/end","value":"'${E_TIME}'"}]'
    

    开始时间 /spec/timeWindow/start 和结束时间 /spec/timeWindow/end 必须分别包含过去的日期/月份/年份。时间窗口是根据您输入的值计算的。

分配的升级时长至少应为每种升级类型所示的最低时长。您可以按照以下建议分配更长的时长:

  • 次要升级:在 32 天的滚动期中,至少需要 12 小时的维护时间。
  • 补丁升级:在 32 天的滚动期内,至少需要 48 小时,并且包含 1 个或多个时间段。虽然控制台显示的最短时间窗口为 4 小时,但 Google 建议您为每个时间块分配至少 6 小时。

手动升级 Operations Suite Infrastructure Core

此升级过程仅适用于从 1.13.x 版升级到 1.14.3 版。

确保所有受管理的网域账号和本地账号均已启用,且密码未过期。如果账号状态不佳,可能会导致此流程出错。

执行虚拟机检查点和目录备份

  1. 执行虚拟机检查点。

    1. BM01 主机上,以管理员身份打开 PS 控制台。
    2. 针对集群中的每个 Hyper-V 主机运行以下命令。

      $servername = "<*hyperv-server-name*>"
      Get-VM -CimSession $servername  | ForEach-Object {
      $myargs = @{
      VMName = $_.Name
      SnapshotName = "Checkpoint_$($_.Name)_$(Get-Date -Format 'yyyyMMddHHmmss')"
      ComputerName = $servername
      }
      Checkpoint-VM @myargs
      }
      

      让 PowerShell 窗口保持打开状态,以便执行后续步骤

  2. 启用长文件路径

      $path = 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem'
      Set-ItemProperty -Path $path -Name 'LongPathsEnabled' -Value 1
    
  3. 备份 H:\operations_center 驱动器。(此操作支持回滚升级。)

      Rename-Item -Path H:\operations_center -NewName operations_center_backup
    
  4. CONFIG1 上的备份配置目录。(此备份在构建新的 config.ps1 配置时提供参考。)

    1. BM01 主机上,使用远程桌面协议 (RDP) 连接到 CONFIG1 虚拟机的 IP 地址,然后使用系统管理员账号登录。示例:mstsc /v 192.168.100.99

    2. 管理员身份运行打开 PS 控制台。

      • 创建备份文件夹
      mkdir c:\config1_backup
      
      • 备份 C:\dsc
      Move-Item -Path "C:\dsc\" -Destination "C:\config1_backup"
      
      • 备份 C:\config
      Move-Item -Path "C:\config\" -Destination "C:\config1_backup"
      
      • 备份 C:\operations_center
      Move-Item -Path "C:\release\operations_center\" -Destination "C:\config1_backup"
      
      • 确保已启用长文件路径
      $path = 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem'
      Set-ItemProperty -Path $path -Name 'LongPathsEnabled' -Value 1
      

加载第三方软件

第三方软件中执行任务。

升级现有虚拟机

  1. 获取安装目录。

    1. 按照下载文件部分中的说明下载 OIC 组件软件包。

    2. BM01 主机上,从下载的 prod_IT_component_bundle.tar.gz 中提取 operations_center 目录。

      Set-Location H:
      tar -zxvf prod_IT_component_bundle.tar.gz
      

      提取 TAR 文件后,应在 H: 的根目录中创建一个 release 文件夹

    3. operations_center 移动到 H 的根目录:

      Move-Item -Path H:\release\operations_center -Destination H:\
      
  2. 使用特定于网站的数据更新 config.ps1

    config.ps1 配置文件提供了构建和配置 Operations Suite 基础架构 (OI) 环境所需的所有信息。如需更新配置文件,您必须收集以下所有信息。备份现有的 config.ps1 可作为参考,以防止意外覆盖现有设置。 重要提示:请务必先完成并正确填写config.ps1,然后再继续操作。

    • occonfigtool 工具的网络配置输出,尤其是 ocinfo.common.opscenter.local.txt 文件。以下步骤中提及的网络名称(例如 OCCORE-SERVERS)引用了相应文档中的 Name 列。
    • 相应 OI 管理的每个 GDC 单元的域名和 DNS 服务器 IP 地址。此数据可在客户意见征询问卷 (CIQ) 的输出中找到。

    Administrator 身份在 BM01 主机上进行所有更改。

  3. 复制部署类型的正确配置示例代码:

    1. H:\operations_center\dsc\config.example.ps1 复制到 H:\operations_center\config\config.ps1
  4. 使用 VSCode 或 PowerShell ISE 验证并更新 config.ps1 中的值。

    1. 如果 OIC 部署为多站点

      1. 查找带有 ### Multi-Site: 标签的评论
      2. 执行您找到的注释中所述的操作。
    2. 更新 HardwareVersion,除非默认值 (3.0) 正确。

    3. 更新 PrimarySiteCode,除非默认值 (DC1) 正确。

    4. 网站代码用于许多名称中。搜索并替换 DC1 的所有实例,改为正确的网站代码。使用不区分大小写的搜索。查看每项变更,因为有些变更可能不是必需的。例如,如果网站代码为 AB1,则主机名 DC1-DC1 必须更改为 AB1-DC1而不能更改为 AB1-AB1

    5. 如果默认值不正确,请更新 DnsDomain如果更改此值,请在整个 config.ps1 文件中搜索并替换 opscenter.local。有多个位置硬编码了该默认值。

    6. 使用特定于网站的信息更新 DnsConditionalForwarder 中的对象。必须至少有一个转发对象。移除不必要的示例。

      如果已安装 gdcloudkubectl CLI,则可以在 CONFIG1 上的 WSL 中执行此步骤。

      如需从根管理员集群拉取特定于网站的信息,请使用以下命令:

      export KUBECONFIG=/root/release/root-admin/root-admin-kubeconfig
      kubectl get -n dns-system service gpc-coredns-external-udp \
                  -o jsonpath='{.status.loadBalancer.ingress[0].ip}{"\n"}'
      
      1. Domain - GDC Cell DNS 域名,例如 ciq.yaml 中的 dns.delegatedSubdomain
      2. Master - DNS 服务器 IP 的列表(通常只有一个)。在 cellcfg 中查找类型为 DNSReservation 的内容。如果已部署 GDC Cell,请在根管理集群的 dns-system 命名空间中查找 gpc-coredns-external-udp 服务的 EXTERNAL-IP 和 Cell 的 FQDN bert.sesame.street

      3. 在多站点部署中,每个单元都有一个哈希表对象。

    7. 请勿更改 UsersGroupsGroupPolicy 对象的任何内容。

    8. 更新 DNSServers,使其包含分配给主网域控制器和辅助网域控制器的 2 个 IP 地址,例如 <SITE>-DC1<SITE>-DC2

    9. NTPServers 更新为来自根管理员 TimeServer 自定义资源的 SyncServer IP 地址列表。您可以使用以下命令获取这组 IP 地址:

      kubectl get timeserver -A -o json | jq '.items[].address'
      

      您必须以 NTPServers 格式设置这些 IP 地址,如以下示例所示:

      NtpServers = @(
        '10.251.80.2',
        '10.251.80.3',
        '10.251.80.4',
        '10.251.80.5'
      )
      
    10. 根据需要,使用客户提供的 OCCORE-SERVERS 子网的前缀值更新 SubnetPrefix 默认值(即 24)。

    11. 使用客户为 OCCORE-SERVERS 子网提供的默认网关更新 DefaultGateway 默认值。

    12. 查找并更新 WorkstationCider 默认值,将客户提供的 OC-WORKSTATIONS 子网值(采用 IPv4 CIDR 表示法)替换为该默认值。

    13. 如果客户选择允许远程访问其工作站,则将 WorkstationAllowRemote 值更新为 $true

    14. 找到并替换示例子网前缀 172.21.0.,改为客户提供的 OCCORE-SERVERS 子网前缀。

    15. 将示例子网前缀 172.21.2. 替换为客户提供的 OCCORE-JUMPHOSTS 子网前缀。

    16. 找到示例子网前缀 172.21.32.,并将其替换为客户提供的 OC-WORKSTATIONS 子网前缀。

    17. 找到并替换 Pref caption 的示例每日消息 legalnoticecaption 值,改为使用客户提供的字幕。

    18. 找到并替换 Pref text 的示例每日一句话 legalnoticetext 值,改为客户提供的文本。

    19. 验证每个“节点”对象,并根据需要进行更新。

      1. NodeName - 确保主机名正确无误。有些名称在很多地方都会用到,例如网域控制器。如果您在此处更改了名称,请检查是否需要在配置中的其他位置进行更改。
      2. IPv4Addr - 这必须是主机的 IP 地址。通常情况下,最后一个八位字节可以保持原样。在之前的步骤中,我们已在网络搜索和替换过程中更新了部分八位字节。

      3. HyperVHost - 此值必须是托管相应虚拟机的 Hyper-V 服务器的 IP 地址。您可以在配置的“Hyper-V 服务器”部分中获取每个 BM?? 服务器的 IP 地址。请勿更改此字段中的 Hyper-V 主机分配,因为并非所有 Hyper-V 主机支持每种虚拟机类型,只需将 Hyper-V 主机名更改为相应的 IP 地址即可。

    20. 使用 Role=jumphost 验证所有节点上的第二个网络接口详细信息。为此接口使用 OCCORE-JUMPHOSTS 子网详细信息。检查:

      1. JumphostIPv4Cidr
      2. JumphostDefaultGateway
    21. 更新节点中 Role=adfs 的 ADFS 特有节。

      1. 找到 Name = 'SplunkTrust' # Must be unique to the farm. Append "Trust"
      2. 将此行后面的三个 opscenter.local 替换为您的 DNS 网域
    22. 根据需要更新 DHCP 范围,以匹配客户的 IP 方案。对于每个范围,验证以下值是否正确。范围中的名称与 ocinfo.common.opscenter.local.txt 网络方案中使用的名称一致,因此请在验证中使用以下内容:

      1. ScopeId
      2. IpStartRange
      3. IpEndRange
      4. Router
      5. SubnetMask
    23. 确认这些值与备份的 config1.ps1 中的值一致

    24. 请务必保存文件。

CONFIG1 虚拟机准备

BM01 上执行 CONFIG1 准备。所有其他升级均在登录 CONFIG1 虚拟机时进行。

  1. 将 operations_center 目录复制到 CONFIG1 虚拟机

    1. BM01 主机上,以管理员身份打开 PS 控制台。

    2. 复制 operations_center 以暂存 CONFIG1 虚拟机 (VM) 所需的文件。

      # Change name to match your config host
      $config = "DC1-CONFIG1"
      # Stage files for CONFIG1 VM
      Copy-Item  -Path H:\operations_center -Destination "\\$config\c$\" -Recurse -Force
      
    3. 停用 Hyper-V 时间同步

      1. 以管理员身份登录 BM01 主机。

      2. 以管理员身份在 Windows 上打开 PowerShell,然后运行以下命令:

      # Disabling Hyper-V Time Sync
      Disable-VMIntegrationService -VMName `<SITE>-CONFIG1` -Name 'Time Synchronization'
      
    4. CONFIG1 虚拟机准备和验证

      1. BM01 主机中,使用 -SA 账号登录 CONFIG1 虚拟机。 使用远程桌面 (RDP) 连接到虚拟机 IP 地址。示例: mstsc /v 192.168.100.99

      2. 使用“以其他用户身份运行”菜单打开 PowerShell 窗口,以 Marvin 用户身份运行。

      3. 在新 PowerShell 窗口中,启动管理会话:

        Start -Verb runas -FilePath powershell.exe
        

        关闭之前的 PowerShell 窗口,但保持管理员窗口处于打开状态。

      4. 验证管理 PowerShell 窗口是否以 Marvin 的身份运行

        whoami
        
      5. 列出从 BM01 主机暂存的文件。

        Move-Item -Path c:\operations_center -Destination c:\release
        C:\release\operations_center\dsc\Initialize-ConfigHostFiles.ps1
        
      6. 验证 c:\dscc:\config 是否存在。

      7. 从备份中复制凭据和证书文件

        Copy-Item -Path "C:\config1_backup\config\creds\" -Destination "C:\config\creds\" -Recurse
        Copy-Item -Path "C:\config1_backup\config\certs\" -Destination "C:\config\certs\" -Recurse
        
      8. 构建编译 MOF 所需的 MECM 数据

        C:\dsc\Build-MecmFiles.ps1
        
      9. 运行 Build-Mof.ps1 以验证构建环境是否已准备就绪,该命令会为所有 OI 机器生成 MOF 文件。

        C:\dsc\Build-Mof.ps1
        
    5. 填充凭据变量

      这些变量在整个升级过程中都会用到。在以管理员身份打开的 Marvin PowerShell 窗口中填充这些变量一次。

      . 'c:\config\config.ps1'
      
      $da_creds = (Get-Credential -Message "Provide domain admin credentials")
      $sa_creds = (Get-Credential -Message "Provide system admin credentials")
      
      $sa_args = @{
      Credential = $sa_creds
      SetLcm = $true
      RemoveExisting = $true
      CopyModules = $true
      }
      
      $da_args = @{
      Credential = $da_creds
      SetLcm = $true
      RemoveExisting = $true
      CopyModules = $true
      }
      
    6. 验证 DSC 是否正在运行,以及服务器是否可访问。

      $role = 'domain_controller'
      $ca = 'ca_root'
      $dcs = $config.AllNodes | Where-Object {$_.role -eq $role}
      $non_dcs = $config.AllNodes | Where-Object {$_.role -ne $role -and $_.role -ne $ca -and $_.NodeName -ne "*"}
      
      $dcs | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $da_creds
      Get-DscConfigurationStatus -CimSession $session | select HostName,Status,NumberOfResources,ResourcesNotInDesiredState}
      
      $non_dcs | ForEach-Object {
      Write-Output "Checking $($_.NodeName)"
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session | select HostName,Status,NumberOfResources,ResourcesNotInDesiredState | ft -AutoSize}
      

排查连接问题。

  1. 如果 New-CimSession 失败,请验证 config.ps1 中的 NodeName 值是否正确。 另请确认服务器处于在线状态且可访问。

    错误将以 Get-CimSession: WinRM cannot process the request 开头。

升级网域控制器

  1. 在登录 CONFIG1 的情况下,升级主网域控制器。

    填充变量、移除旧 GPO 并关联新 GPO。

    $dc2 = $dcs | Where-Object {$_.NodeName -like "*-DC2"}
    $dc1 = $dcs | Where-Object {$_.NodeName -like "*-DC1"}
    
    Invoke-Command -Computername $dc1.NodeName -Credential $da_creds -ScriptBlock {
    Remove-DscConfigurationDocument -Stage Current,Pending,Previous
    get-gpo -All | Where-Object { $_.DisplayName -like "OIC*" } | Remove-GPO
    get-gpo -All | Where-Object { $_.DisplayName -like "SITE*" -and $_.DisplayName -notlike "*SCCM*" } | Remove-GPO
    Get-Item "C:\config\domain_controller\oic_gpos"| Remove-Item -Recurse -Force
    Get-Item "C:\config\domain_controller\site_gpo*"| Remove-Item -Recurse -Force
    }
    

    取消关联组策略对象。升级完成后,这两个账号将关联起来。

    $gpolinks = (Get-Content C:\dsc\data\GpoLinkMapping.yaml -Raw).Replace("LinkEnabled: 'Yes'", "LinkEnabled: 'No'")
    $gpolinks | Out-File C:\dsc\data\GpoLinkMapping.yaml -Force
    

    升级主网域控制器。

    .\Update-RemoteHost.ps1 @da_args -ComputerName $DC1.NodeName
    
    New-PSDrive -Name DC1 -PsProvider FileSystem -Root "\\$($DC1.NodeName)\c$" -Credential $da_creds
    Invoke-Command -ComputerName $DC1.NodeName -Credential $da_creds -Scriptblock {Remove-DscConfigurationDocument -Stage Current,Pending}
    Remove-Item -Path DC1:\config\domain_controller\site_gpos -Recurse -Force
    Remove-Item -Path DC1:\config\domain_controller\site_gpos_source -Recurse -Force
    Copy-Item -Path C:\config\domain_controller\ -Destination DC1:\config\ -Verbose -Force -Recurse
    C:\dsc\Build-Mof.ps1 -Computername $DC1.NodeName
    Start-DscConfiguration -ComputerName $DC1.NodeName -Path 'c:\config\mofs' -Credential $da_creds -Verbose -Wait -Force
    Remove-PsDrive -Name DC1
    
    1. 验证与 SyncServer 的时间同步

    2. 使用 RDP 以网域管理员身份登录 DC1

      1. 管理员身份打开 Powershell 窗口。
      2. 运行以下命令以验证时间配置。

        w32tm /query /status /verbose
        
    1. 运行以下命令以测试时间重新同步:

       # Testing time resyncronization
       w32tm /resync
      
       # Desired output
       Sending resync command to local computer
       The command completed successfully.
      
    2. 重新验证时间配置是否正确且没有错误。

       w32tm /query /status /verbose
      
  2. 升级第二个网域控制器。

    1. 使用现有的 CONFIG1 PowerShell 窗口运行以下脚本。

      .\Update-RemoteHost.ps1 @da_args -ComputerName $dc2.NodeName
      
  3. 验证 Active Directory 复制。

    1. 第二个 DC 启动并运行后,从其中一个网域控制器运行以下命令,以验证 Active Directory 复制:

      repadmin /replsummary
      

      输出必须类似如下所示:

      PS C:\Users\Administrator.OpsCenter> repadmin /replsummary
      Replication Summary Start Time: 2023-11-29 19:16:59
      
      Beginning data collection for replication summary, this may take awhile:
      ......
      
      Source DSA          largest delta    fails/total %%   error
      OC1-DC1                   01m:49s    0 /  5    0
      
      Destination DSA     largest delta    fails/total %%   error
      OC1-DC2                   01m:49s    0 /  5    0
      

升级 CA-ISSUING1CA-WEB

  1. 使用 CONFIG1 上的现有 PowerShell 终端升级 CA-ISSUING1

      $ca_iss = $config.AllNodes | Where-Object {$_.role -eq "ca_issuing"}
      c:\dsc\Update-RemoteHost.ps1 @sa_args -ComputerName $ca_iss.NodeName
    
  2. 使用 CONFIG1 上的现有 PowerShell 终端升级 CA-WEB

      $ca_web = $config.AllNodes | Where-Object {$_.role -eq "ca_web"}
      c:\dsc\Update-RemoteHost.ps1 @sa_args  -Computername $ca_web.NodeName
    
  3. 验证升级

      $ca_iss,$ca_web | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

升级 CA-ROOT1

使用 CONFIG1 上现有的 PowerShell 终端

  1. 开启 CA-ROOT1

      $ca_root = $config.AllNodes | Where-Object {$_.role -eq "ca_root"}
      $session = New-CimSession -ComputerName $ca_root.HyperVHost -Credential $sa_creds
      Start-VM -CimSession $session  -Name $ca_root.NodeName
    
  2. 更新 CA-ROOT1

      $caroot_cred = Get-GeccoCredential -Name "$($ca_root.NodeName)\caadmin" -CredStore "c:\config\creds"
      c:\dsc\Update-RemoteHost.ps1 -Computername $ca_root.NodeName -RemoteHost $ca_root.Ipv4Addr -Credential $caroot_cred
    
  3. 如果 CA_ROOT1 在运行上一个脚本后未重新启动,请手动重新启动。

  4. 验证升级。

      $ca_root | ForEach-Object {
      $session = New-CimSession -ComputerName $_.Ipv4Addr -Credential $caroot_cred
      Get-DscConfigurationStatus -CimSession $session}
    
  5. 验证 Peer 设置是否为 <SITE>-DC1.<DNSDOMAIN>,以及 State 是否为 Active

    如果时间未正确同步,请勿继续。

      w32tm /query /peers
    
      #Peers: 1
    
      Peer: DC1-DC1.domain.local
      State: Active
      Time Remaining: 31.2997107s
      Mode: 3 (Client)
      Stratum: 1 (primary reference - syncd by radio clock)
      PeerPoll Interval: 6 (64s)
      HostPoll Interval: 6 (64s)
    
  6. 关闭 CA-Root

      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Stop-VM -CimSession $session  -Name $ca_root.NodeName
    

升级 ADFS

使用 CONFIG1 上现有的 PowerShell 终端

  1. 升级 ADFS1 虚拟机。

      $role = 'adfs'
      $adfs = $config.AllNodes | Where-Object {$_.role -eq $role}
    
      $adfs | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    
      $adfs | ForEach-Object {
      c:\dsc\Update-RemoteHost.ps1 @sa_args  -Computername $adfs.NodeName}
    
    1. Validate the upgrade.
    
      $adfs | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

升级 Jumphost

使用 CONFIG1 上现有的 PowerShell 终端

  1. 创建跳转主机的数组。

      $role = 'jumphost'
      $jumps = $config.AllNodes | Where-Object {$_.role -eq $role}
    
  2. 升级跳转主机。

      $jumps | ForEach-Object {
      c:\dsc\Update-RemoteHost.ps1 @sa_args -Computername $_.NodeName}
    
  3. 验证升级。

      $jumps | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

升级 Fileserver

使用 CONFIG1 上现有的 PowerShell 终端

  1. 创建一个包含 Fileserver 的数组。

      $role = 'file'
      $files = $config.AllNodes | Where-Object {$_.role -eq $role}
    
  2. 升级文件服务器。

      $files | ForEach-Object {
      c:\dsc\Update-RemoteHost.ps1 @sa_args -Computername $_.NodeName}
    
  3. 验证升级。

      $files | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

升级 DHCP 服务器。

使用 CONFIG1 上现有的 PowerShell 终端

  1. 升级 DHCP1。

      $role = 'dhcp_primary'
      $dhcp1 = $config.AllNodes | Where-Object {$_.role -eq $role}
      c:\dsc\Update-RemoteHost.ps1 @sa_args -Computername $dhcp1.NodeName
    
  2. 验证升级。

      $dhcp1 | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    
  3. 升级 DHCP2。

      $role = 'dhcp_failover'
      $dhcp2 = $config.AllNodes | Where-Object {$_.role -eq $role}
      c:\dsc\Update-RemoteHost.ps1 @sa_args -Computername $dhcp2.NodeName
    
  4. 验证升级。

      $dhcp2 | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

升级 Userlock 服务器。

使用 CONFIG1 上现有的 PowerShell 终端

  1. 创建包含 Userlock 服务器的 PowerShell 数组。

      $role = 'userlock_primary'
      $ulock1 = $config.AllNodes | Where-Object {$_.role -eq $role}
      $role = 'userlock_backup'
      $ulock2 = $config.AllNodes | Where-Object {$_.role -eq $role}
    
  2. 移除之前设置中的标记文件。

      Invoke-Command -ComputerName $ulock1.NodeName -Credential $sa_creds -Scriptblock { Remove-item "c:\config\userlock_primary\ServiceImpersonation.log" }
      Invoke-Command -ComputerName $ulock2.NodeName -Credential $sa_creds -Scriptblock { Remove-item "c:\config\userlock_backup\ServiceImpersonation.log" }
    
  3. 升级主 Userlock 服务器。

      c:\dsc\Update-RemoteHost.ps1 @sa_args -Computername $ulock1.NodeName
    
  4. 升级备份 Userlock 服务器。

      c:\dsc\Update-RemoteHost.ps1 @sa_args -Computername $ulock2.NodeName
    
  5. 验证升级。

      $ulock1,$ulock2 | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

升级 Nessus 服务器。

使用 CONFIG1 上现有的 PowerShell 终端

  1. 创建一个包含 Nessus 服务器的 PowerShell 数组。

      $role = 'nessus_'
      $nessus = $config.AllNodes | Where-Object {$_.role -match $role}
    
  2. 升级 Nessus 服务器。

      $nessus | ForEach-Object {
      c:\dsc\Update-RemoteHost.ps1 @sa_args  -Computername $_.NodeName}
    
  3. 验证升级。

      $nessus | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

升级 Hyper-V 服务器。

使用 CONFIG1 上现有的 PowerShell 终端

  1. 创建一个包含 Hyper-V 服务器的 PowerShell 数组。

      $role = 'hyper_v'
      $hyper = $config.AllNodes | Where-Object {$_.role -eq $role}
    
  2. 升级 Hyper-V 服务器。

      $hyper | ForEach-Object {
      c:\dsc\Update-RemoteHost.ps1 @sa_args -Computername $_.NodeName}
    
  3. 验证升级。

      $hyper | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

升级工具箱

使用 CONFIG1 上现有的 PowerShell 终端

  1. 创建一个包含 Toolbox 服务器的 PowerShell 数组。

      $role = 'toolbox'
      $tools = $config.AllNodes | Where-Object {$_.role -eq $role}
    
  2. 在 TOOLBOX1 服务器上创建其他驱动器

      $tools | ForEach-Object {
         if ($_.ExtraDiskSize) {
         Invoke-Command -ComputerName $_.HyperVHost -Credential $sa_creds -ScriptBlock {
            $additional_disk_path = Join-Path -Path $using:_.ExtraDiskFolder -ChildPath "$($using:_.NodeName)-2.vhdx"
            New-VHD -Path $additional_disk_path -Dynamic -SizeBytes $using:_.ExtraDiskSize
            Add-VMHardDiskDrive -VMName $using:_.NodeName -Path $additional_disk_path
            Get-VMHardDiskDrive -VMName $using:_.NodeName | select VMName,ControllerLocation,Path
         }}}
    

    验证输出是否显示已为虚拟机分配两个磁盘。示例:

      VMName       ControllerLocation Path
      ------       ------------------ ----
      DC1-TOOLBOX1                  0 H:\Hyper-V\Virtual Hard Disks\DC1-TOOLBOX1.vhdx
      DC1-TOOLBOX1                  1 Z:\Hyper-V\Virtual Hard Disks\DC1-TOOLBOX1-2.vhdx
    
  3. 升级 Toolbox 服务器。

      $tools | ForEach-Object {
      c:\dsc\Update-RemoteHost.ps1 @sa_args  -Computername $_.NodeName}
    
  4. 验证升级。

      $tools | ForEach-Object {
      $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
      Get-DscConfigurationStatus -CimSession $session}
    

使用 CONFIG1 上的现有 PowerShell 终端验证升级。

  1. 验证 DSC 是否正常运行,没有错误。

       $role = 'domain_controller'
       $ca = 'ca_root'
       $dcs = $config.AllNodes | Where-Object {$_.role -eq $role}
       $non_dcs = $config.AllNodes | Where-Object {$_.role -ne $role -and $_.role -ne $ca -and $_.NodeName -ne "*"}
    
       $dcs | ForEach-Object {
       $session = New-CimSession -ComputerName $_.NodeName -Credential $da_creds
       Get-DscConfigurationStatus -CimSession $session | select HostName,Status,NumberOfResources,ResourcesNotInDesiredState}
    
       $non_dcs | ForEach-Object {
       Write-Output "Checking $($_.NodeName)"
       $session = New-CimSession -ComputerName $_.NodeName -Credential $sa_creds
       Get-DscConfigurationStatus -CimSession $session | select HostName,Status,NumberOfResources,ResourcesNotInDesiredState | ft -AutoSize}
    

升级 Splunk 虚拟机

  1. CONFIG1 的 PowerShell 窗口中,设置并运行 DSC 配置:

    • 输入网站代码。示例:"DC1"

       $sitecode = Read-Host "Enter your site code"
       Set-Location c:\dsc
      
    • 配置重型转发器:

       $myargs = @{
       Computername = "$sitecode-HEAVYFWD"
       Credential = $sa_creds
       SetLcm = $true
       RemoveExisting = $true
       }
       .\Update-RemoteHost.ps1 @myargs
      
    • 配置索引器 1:

       $myargs = @{
       Computername = "$sitecode-INDEXER1"
       Credential = $sa_creds
       SetLcm = $true
       RemoveExisting = $true
       }
       .\Update-RemoteHost.ps1 @myargs
      
    • 配置索引器 2:

       $myargs = @{
       Computername = "$sitecode-INDEXER2"
       Credential = $sa_creds
       SetLcm = $true
       RemoveExisting = $true
       }
       .\Update-RemoteHost.ps1 @myargs
      
    • 配置索引器 3:

       $myargs = @{
       Computername = "$sitecode-INDEXER3"
       Credential = $sa_creds
       SetLcm = $true
       RemoveExisting = $true
       }
       .\Update-RemoteHost.ps1 @myargs
      
    • 配置管理器:

       $myargs = @{
       Computername = "$sitecode-SPLUNKMGR"
       Credential = $sa_creds
       SetLcm = $true
       RemoveExisting = $true
       }
       .\Update-RemoteHost.ps1 @myargs
      
    • 配置搜索头:

       $myargs = @{
       Computername = "$sitecode-SEARCHHEAD"
       Credential = $sa_creds
       SetLcm = $true
       RemoveExisting = $true
       }
       .\Update-RemoteHost.ps1 @myargs
      
  2. CONFIG1 的 PowerShell 窗口中:

      $servers = @()
      $config.AllNodes | Where-Object {$_.role -match "splunk_"} | Foreach { $servers += $_.NodeName }
      Invoke-Command -ComputerName $servers -Credential $sa_creds -ScriptBlock {Restart-Service -Name 'Splunkd'} -ErrorAction Continue
    
  3. 按照 SIEM-G0006 设置全局 Pass4SymmKey,并按照 SIEM-G0007 将每个可用区附加到 OIC 中的 Splunk。

升级 CONFIG1 主机

  1. CONFIG1 的 PowerShell 窗口中:

    Start-DscConfiguration -ComputerName $env:COMPUTERNAME -Path c:\config\mofs -Verbose -Wait -Force
    
  2. 如果计算机重启,请重新以 Marvin 的身份登录,然后再次以管理员身份启动 PowerShell。填充后续部分所需的变量。

    Set-Location c:\dsc
    . c:\config\config.ps1
    $da_creds = (Get-Credential -Message "Provide domain admin credentials")
    $sa_creds = (Get-Credential -Message "Provide system admin credentials")
    

Microsoft Configuration Manager (MCM)

由于 MCM 不是可升级的组件,因此唯一的选择是销毁现有的 MCM 主机并重新部署 MCM。

  • 确保当前 MCM 软件已按照 IT-T0023 进行水合。

  • 有关重新部署的程序,请参阅 IT-R0019

移除虚拟机检查点

升级完成后,应移除检查点。检查点可能会导致磁盘使用量随时间推移而过高。仅当因升级失败而需要恢复到检查点时,才保留这些文件。

使用 CONFIG1 上现有的 PowerShell 终端

  1. 移除虚拟机检查点。

      $config.AllNodes | Where-Object {$_.Role -eq "hyper_v"} | Foreach-Object {
      Invoke-Command -ComputerName $_.NodeName -Credential $sa_creds -Scriptblock {
        Get-VM | Get-VMSnapshot | Where-Object {$_.Name -like "Checkpoint_*"} | Remove-VMSnapshot -Verbose
      }}
    

重新启用网域的组策略对象

使用 CONFIG1 上现有的 PowerShell 终端

  1. 更改网域控制器角色配置,以启用受管理的 GPO 上的链接

      $gpolinks = (Get-Content C:\dsc\data\GpoLinkMapping.yaml -Raw).Replace("LinkEnabled: 'No'", "LinkEnabled: 'Yes'")
      $gpolinks | Out-File C:\dsc\data\GpoLinkMapping.yaml -Force
    
  2. 使用 ObjectOwner 角色更新网域控制器:

      c:\dsc\Update-RemoteHost.ps1 -Computername $config.AllNodes.DomainConfig.ObjectOwner -Credential $da_creds
    

与 Google 团队联系

如需了解与 Google 联系以获取进一步帮助的步骤,请参阅申请支持页面。