×

收集信息以排除托管控制平面的故障

当您需要排除托管集群的问题时,您可以通过运行 `must-gather` 命令来收集信息。该命令会为管理集群和托管集群生成输出。

管理集群的输出包含以下内容:

  • **集群范围资源:**这些资源是管理集群的节点定义。

  • **`hypershift-dump` 压缩文件:**如果您需要与其他人共享内容,此文件非常有用。

  • **命名空间资源:**这些资源包括来自相关命名空间的所有对象,例如配置映射、服务、事件和日志。

  • **网络日志:**这些日志包括 OVN 北向和南向数据库以及每个数据库的状态。

  • **托管集群:**此级别的输出涉及托管集群内的所有资源。

托管集群的输出包含以下内容:

  • **集群范围资源:**这些资源包括所有集群范围的对象,例如节点和 CRD。

  • **命名空间资源:**这些资源包括来自相关命名空间的所有对象,例如配置映射、服务、事件和日志。

尽管输出不包含集群中的任何密钥对象,但它可能包含对密钥名称的引用。

先决条件
  • 您必须对管理集群具有 `cluster-admin` 访问权限。

  • 您需要 `HostedCluster` 资源的 `name` 值以及部署 CR 的命名空间。

  • 您必须安装 `hcp` 命令行界面。有关更多信息,请参阅“安装托管控制平面命令行界面”。

  • 您必须安装 OpenShift CLI (`oc`)。

  • 您必须确保已加载 `kubeconfig` 文件并指向管理集群。

步骤
  • 要收集故障排除的输出,请输入以下命令:

    $ oc adm must-gather \
      --image=registry.redhat.io/multicluster-engine/must-gather-rhel9:v<mce_version> \
      /usr/bin/gather hosted-cluster-namespace=HOSTEDCLUSTERNAMESPACE \
      hosted-cluster-name=HOSTEDCLUSTERNAME \
      --dest-dir=NAME ; tar -cvzf NAME.tgz NAME

    其中:

    • 您将 `` 替换为正在使用的多集群引擎操作符的版本;例如,`2.6`。

    • `hosted-cluster-namespace=HOSTEDCLUSTERNAMESPACE` 参数是可选的。如果您不包含它,则该命令将像托管集群位于默认命名空间(即 `clusters`)一样运行。

    • 如果您想将命令的结果保存到压缩文件中,请指定 `--dest-dir=NAME` 参数并将 `NAME` 替换为您想要保存结果的目录的名称。

在断开连接的环境中输入 must-gather 命令

完成以下步骤,在断开连接的环境中运行must-gather命令。

步骤
  1. 在断开连接的环境中,将Red Hat Operator Catalog镜像镜像到其镜像注册表中。更多信息,请参见在断开连接的网络上安装

  2. 运行以下命令提取日志,这些日志引用其镜像注册表中的镜像

    REGISTRY=registry.example.com:5000
    IMAGE=$REGISTRY/multicluster-engine/must-gather-rhel8@sha256:ff9f37eb400dc1f7d07a9b6f2da9064992934b69847d17f59e385783c071b9d8
    
    $ oc adm must-gather \
      --image=$IMAGE /usr/bin/gather \
      hosted-cluster-namespace=HOSTEDCLUSTERNAMESPACE \
      hosted-cluster-name=HOSTEDCLUSTERNAME \
      --dest-dir=./data

OpenShift Virtualization托管集群故障排除

当您对OpenShift Virtualization上的托管集群进行故障排除时,请从顶层的HostedClusterNodePool资源开始,然后沿堆栈向下工作,直到找到根本原因。以下步骤可以帮助您发现常见问题的根本原因。

HostedCluster资源卡在部分状态

如果托管控制平面由于HostedCluster资源挂起而无法完全上线,请通过检查先决条件、资源条件以及节点和Operator状态来识别问题。

步骤
  • 确保您满足OpenShift Virtualization上托管集群的所有先决条件。

  • 查看HostedClusterNodePool资源上的条件,查找阻止进度验证错误。

  • 使用托管集群的kubeconfig文件,检查托管集群的状态

    • 查看oc get clusteroperators命令的输出,查看哪些集群Operator处于挂起状态。

    • 查看oc get nodes命令的输出,以确保工作节点已准备好。

未注册任何工作节点

如果托管控制平面由于没有注册工作节点而无法完全上线,请通过检查托管控制平面的各个部分的状态来识别问题。

步骤
  • 查看HostedClusterNodePool条件,查找指示问题的故障。

  • 输入以下命令以查看NodePool资源的KubeVirt工作节点虚拟机 (VM) 状态

    $ oc get vm -n <namespace>
  • 如果虚拟机卡在配置状态,请输入以下命令以查看虚拟机命名空间内的CDI导入Pod,以了解导入Pod为何未完成的原因

    $ oc get pods -n <namespace> | grep "import"
  • 如果虚拟机卡在启动状态,请输入以下命令以查看virt-launcher Pod的状态

    $ oc get pods -n <namespace> -l kubevirt.io=virt-launcher

    如果virt-launcher Pod处于挂起状态,请调查为何未调度Pod。例如,可能没有足够的资源来运行virt-launcher Pod。

  • 如果虚拟机正在运行,但未注册为工作节点,请使用Web控制台访问受影响虚拟机之一的VNC。VNC输出指示是否应用了启动配置。如果虚拟机在启动时无法访问托管控制平面启动服务器,则无法正确配置虚拟机。

  • 如果应用了启动配置,但虚拟机仍未注册为节点,请参见识别问题:访问虚拟机控制台日志,了解如何在启动期间访问虚拟机控制台日志。

工作节点卡在NotReady状态

在集群创建期间,节点在网络堆栈推出时会暂时进入NotReady状态。此过程的一部分是正常的。但是,如果此过程花费的时间超过15分钟,则可能发生问题。

步骤

通过调查节点对象和Pod来识别问题

  • 输入以下命令以查看节点对象上的条件,并确定节点未准备就绪的原因

    $ oc get nodes -o yaml
  • 输入以下命令查找集群中失败的Pod

    $ oc get pods -A --field-selector=status.phase!=Running,status,phase!=Succeeded

Ingress和控制台集群Operator未上线

如果托管控制平面由于Ingress和控制台集群Operator未上线而无法完全上线,请检查通配符DNS路由和负载均衡器。

步骤
  • 如果集群使用默认Ingress行为,请输入以下命令以确保在托管虚拟机 (VM) 的OpenShift Container Platform集群上启用了通配符DNS路由

    $ oc patch ingresscontroller -n openshift-ingress-operator \
      default --type=json -p \
      '[{ "op": "add", "path": "/spec/routeAdmission", "value": {wildcardPolicy: "WildcardsAllowed"}}]'
  • 如果您为托管控制平面使用自定义基础域,请完成以下步骤

    • 确保负载均衡器正确地将目标指向VM Pod。

    • 确保通配符DNS条目将目标指向负载均衡器IP地址。

托管集群的负载均衡器服务不可用

如果托管控制平面由于负载均衡器服务不可用而无法完全上线,请检查事件、详细信息和Kubernetes集群配置管理器 (KCCM) Pod。

步骤
  • 查找与托管集群中的负载均衡器服务相关的事件和详细信息。

  • 默认情况下,托管集群的负载均衡器由托管控制平面命名空间中的kubevirt-cloud-controller-manager处理。确保KCCM Pod在线,并查看其日志中的错误或警告。要识别托管控制平面命名空间中的KCCM Pod,请输入以下命令

    $ oc get pods -n <hosted_control_plane_namespace> -l app=cloud-controller-manager

托管集群PVC不可用

如果托管控制平面由于托管集群的持久卷声明 (PVC) 不可用而无法完全上线,请检查PVC事件和详细信息以及组件日志。

步骤
  • 查找与PVC相关的事件和详细信息,以了解正在发生的错误。

  • 如果PVC无法附加到Pod,请查看托管集群中kubevirt-csi-node daemonset组件的日志,以进一步调查问题。要识别每个节点的kubevirt-csi-node Pod,请输入以下命令

    $ oc get pods -n openshift-cluster-csi-drivers -o wide -l app=kubevirt-csi-driver
  • 如果PVC无法绑定到持久卷 (PV),请查看托管控制平面命名空间中kubevirt-csi-controller组件的日志。要识别托管控制平面命名空间中的kubevirt-csi-controller Pod,请输入以下命令

    $ oc get pods -n <hcp namespace> -l app=kubevirt-csi-driver

VM节点未正确加入集群

如果托管控制平面由于VM节点未正确加入集群而无法完全上线,请访问VM控制台日志。

步骤

RHCOS镜像镜像失败

对于断开连接环境中的OpenShift Virtualization上的托管控制平面,oc-mirror无法自动将Red Hat Enterprise Linux CoreOS (RHCOS)镜像镜像到内部注册表。创建第一个托管集群时,Kubevirt虚拟机无法启动,因为内部注册表中没有启动镜像。

要解决此问题,请手动将RHCOS镜像镜像到内部注册表。

步骤
  1. 运行以下命令获取内部注册表名称

    $ oc get imagecontentsourcepolicy -o json | jq -r '.items[].spec.repositoryDigestMirrors[0].mirrors[0]'
  2. 运行以下命令获取有效负载镜像

    $ oc get clusterversion version -ojsonpath='{.status.desired.image}'
  3. 从托管集群上的有效负载镜像中提取包含启动镜像的0000_50_installer_coreos-bootimages.yaml文件。将<payload_image>替换为有效负载镜像的名称。运行以下命令

    $ oc image extract --file /release-manifests/0000_50_installer_coreos-bootimages.yaml <payload_image> --confirm
  4. 运行以下命令获取RHCOS镜像

    $ cat 0000_50_installer_coreos-bootimages.yaml | yq -r .data.stream | jq -r '.architectures.x86_64.images.kubevirt."digest-ref"'
  5. 将 RHCOS 镜像复制到您的内部注册表。将<rhcos_image>替换为您的 RHCOS 镜像;例如,quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:d9643ead36b1c026be664c9c65c11433c6cdf71bfd93ba229141d134a4a6dd94。将<internal_registry>替换为您的内部注册表名称;例如,virthost.ostest.test.metalkube.org:5000/localimages/ocp-v4.0-art-dev。运行以下命令

    $ oc image mirror <rhcos_image> <internal_registry>
  6. 创建一个名为rhcos-boot-kubevirt.yaml的 YAML 文件,该文件定义ImageDigestMirrorSet对象。请参阅以下示例配置

    apiVersion: config.openshift.io/v1
    kind: ImageDigestMirrorSet
    metadata:
      name: rhcos-boot-kubevirt
    spec:
      repositoryDigestMirrors:
        - mirrors:
            - <rhcos_image_no_digest> (1)
          source: virthost.ostest.test.metalkube.org:5000/localimages/ocp-v4.0-art-dev (2)
    1 指定您的 RHCOS 镜像,不包含其摘要,例如,quay.io/openshift-release-dev/ocp-v4.0-art-dev
    2 指定您的内部注册表名称,例如,virthost.ostest.test.metalkube.org:5000/localimages/ocp-v4.0-art-dev
  7. 应用rhcos-boot-kubevirt.yaml文件以创建ImageDigestMirrorSet对象,运行以下命令

    $ oc apply -f rhcos-boot-kubevirt.yaml

将非裸机集群返回到延迟绑定池

如果您使用的是没有BareMetalHosts的延迟绑定托管集群,则必须完成其他手动步骤才能删除延迟绑定集群并将节点返回到 Discovery ISO。

对于没有BareMetalHosts的延迟绑定托管集群,删除集群信息不会自动将所有节点返回到 Discovery ISO。

步骤

要解除绑定具有延迟绑定的非裸机节点,请完成以下步骤

  1. 删除集群信息。有关更多信息,请参阅从管理中删除集群

  2. 清理根磁盘。

  3. 使用 Discovery ISO 手动重新引导。

重启托管控制平面组件

如果您是托管控制平面的管理员,您可以使用hypershift.openshift.io/restart-date注释来重启特定HostedCluster资源的所有控制平面组件。例如,您可能需要重启控制平面组件以进行证书轮换。

步骤
  • 要重启控制平面,请通过输入以下命令来注释HostedCluster资源

    $ oc annotate hostedcluster \
      -n <hosted_cluster_namespace> \
      <hosted_cluster_name> \
      hypershift.openshift.io/restart-date=$(date --iso-8601=seconds) (1)
    1 只要注释的值发生更改,控制平面就会重新启动。date命令用作唯一字符串的来源。注释被视为字符串,而不是时间戳。
验证

重新启动控制平面后,通常会重新启动以下托管控制平面组件

您可能会看到一些其他组件作为其他组件实施的更改的副作用而重新启动。

  • catalog-operator

  • certified-operators-catalog

  • cluster-api

  • cluster-autoscaler

  • cluster-policy-controller

  • cluster-version-operator

  • community-operators-catalog

  • control-plane-operator

  • hosted-cluster-config-operator

  • ignition-server

  • ingress-operator

  • konnectivity-agent

  • konnectivity-server

  • kube-apiserver

  • kube-controller-manager

  • kube-scheduler

  • machine-approver

  • oauth-openshift

  • olm-operator

  • openshift-apiserver

  • openshift-controller-manager

  • openshift-oauth-apiserver

  • packageserver

  • redhat-marketplace-catalog

  • redhat-operators-catalog

暂停托管集群和托管控制平面的协调

如果您是集群实例管理员,您可以暂停托管集群和托管控制平面的协调。当您备份和还原 etcd 数据库或需要调试托管集群或托管控制平面的问题时,您可能需要暂停协调。

步骤
  1. 要暂停托管集群和托管控制平面的协调,请填充HostedCluster资源的pausedUntil字段。

    • 要暂停协调直到特定时间,请输入以下命令

      $ oc patch -n <hosted_cluster_namespace> \
        hostedclusters/<hosted_cluster_name> \
        -p '{"spec":{"pausedUntil":"<timestamp>"}}' \
        --type=merge (1)
      1 以 RFC339 格式指定时间戳,例如,2024-03-03T03:28:48Z。协调将暂停,直到指定时间过去。
    • 要无限期暂停协调,请输入以下命令

      $ oc patch -n <hosted_cluster_namespace> \
        hostedclusters/<hosted_cluster_name> \
        -p '{"spec":{"pausedUntil":"true"}}' \
        --type=merge

      协调将暂停,直到您从HostedCluster资源中删除该字段。

      当为HostedCluster资源填充暂停协调字段时,该字段会自动添加到关联的HostedControlPlane资源中。

  2. 要删除pausedUntil字段,请输入以下补丁命令

    $ oc patch -n <hosted_cluster_namespace> \
      hostedclusters/<hosted_cluster_name> \
      -p '{"spec":{"pausedUntil":null}}' \
      --type=merge

将数据平面缩减到零

如果您未使用托管控制平面,为了节省资源和成本,您可以将数据平面缩减到零。

确保您已准备好将数据平面缩减到零。因为缩减后工作节点的工作负载会消失。

步骤
  1. 设置kubeconfig文件以访问托管集群,运行以下命令

    $ export KUBECONFIG=<install_directory>/auth/kubeconfig
  2. 获取与您的托管集群关联的NodePool资源的名称,运行以下命令

    $ oc get nodepool --namespace <hosted_cluster_namespace>
  3. 可选:为防止 pod 耗尽,请在NodePool资源中添加nodeDrainTimeout字段,运行以下命令

    $ oc edit nodepool <nodepool_name>  --namespace <hosted_cluster_namespace>
    示例输出
    apiVersion: hypershift.openshift.io/v1alpha1
    kind: NodePool
    metadata:
    # ...
      name: nodepool-1
      namespace: clusters
    # ...
    spec:
      arch: amd64
      clusterName: clustername (1)
      management:
        autoRepair: false
        replace:
          rollingUpdate:
            maxSurge: 1
            maxUnavailable: 0
          strategy: RollingUpdate
        upgradeType: Replace
      nodeDrainTimeout: 0s (2)
    # ...
    1 定义托管集群的名称。
    2 指定控制器用于耗尽节点的总时间。默认情况下,nodeDrainTimeout: 0s设置会阻止节点耗尽进程。

    要允许节点耗尽进程持续一段时间,您可以相应地设置nodeDrainTimeout字段的值,例如,nodeDrainTimeout: 1m

  4. 通过运行以下命令,缩减与您的托管集群关联的NodePool资源

    $ oc scale nodepool/<nodepool_name> --namespace <hosted_cluster_namespace> --replicas=0

    将数据平面缩减到零后,控制平面中的一些 pod 会保持Pending状态,而托管控制平面会保持运行状态。如有必要,您可以扩展NodePool资源。

  5. 可选:通过运行以下命令,扩展与您的托管集群关联的NodePool资源

    $ oc scale nodepool/<nodepool_name> --namespace <hosted_cluster_namespace> --replicas=1

    重新调整NodePool资源的大小后,请等待几分钟,直到NodePool资源变为Ready状态。

验证
  • 通过运行以下命令,验证nodeDrainTimeout字段的值是否大于0s

    $ oc get nodepool -n <hosted_cluster_namespace> <nodepool_name> -ojsonpath='{.spec.nodeDrainTimeout}'