排查卡在 Provisioned 状态的业务集群

当 Alauda OS 上的业务集群已达到 Cluster.status.phase = Provisioned,且 Kubernetes 控制平面报告就绪,但集群始终无法完全投入使用时,请使用本指南。

本诊断流程假设业务集群是通过将 provider Cluster API 清单应用到 global 集群创建的。

范围

本指南中的诊断流程针对 global 集群的导入控制器,该控制器由所有基础设施提供商共享。健康的已导入集群的不变量 中的四项不变量——clusters.platform.tkestack.io 是否存在、capi.cpaas.io/imported 标签、ClusterCredential 数量,以及业务集群的 sentry ServiceAccount——适用于所有提供商。

本指南中的日志字符串使用占位符表示协调器对象名称,因为每个基础设施提供商都使用自己的对象类型(例如,提供商自有的 Cluster 和 Machine 基础设施 CRD)。查看提供商的日志时,请将占位符替换为提供商协调器输出中显示的实际对象名称。诊断模式本身不依赖于提供商,只有日志字符串中的对象名称会有所不同。

如果您的环境是 Huawei Cloud Stack,且下述症状还包括某个节点上的 kubeadm init 停滞,而该节点的池配置中带有带点号的主机名,请在完成本页的通用诊断流程后,参阅排查 HCS 业务集群,了解提供商特有的模式。

症状

集群达到部分成功状态后便停滞不前。以下指标会同时出现:

查看位置观察结果
Cluster.status.phase(位于 global 集群上)Provisioned
KubeadmControlPlane.status.readytrue
Machine.status.phaseRunning
Machine.status.conditions[?(@.type=="NodeHealthy")]status: False、reason: NodeConditionsFailed、message: Node condition Ready is False
MachineDeployment.status.conditions[?(@.type=="Available")]status: False、reason: NotAvailable、message: WorkersAvailable: 0 available replicas
业务集群内部:kubectl get nodes一个或多个节点报告 STATUS=NotReady,因为 CNI 未运行

基础设施提供商协调器日志中通常会在 global 集群上出现以下次要特征:

ERROR  failed to reconcile <CNI-AppRelease-object>: ServiceAccount "sentry" not found
ERROR  failed to reconcile <Infra-Cluster-object>: ServiceAccount "sentry" not found

<CNI-AppRelease-object> 和 <Infra-Cluster-object> 是占位符,代表提供商使用的实际对象类型。例如,CNI AppRelease 对象通常以正在部署的 CNI 命名;基础设施集群对象名称则与提供商的 CRD 相匹配(即提供商自有的 *Cluster CRD)。

协调器会尝试通过 AppRelease 资源应用 CNI,该资源由业务集群自己的 sentry ServiceAccount 执行。如果该 ServiceAccount 不存在,CNI 将无法部署,业务节点会一直处于 NotReady 状态。

健康的已导入集群的不变量

业务集群达到健康的稳定状态后,必须满足以下所有条件。除非另有说明,请从 global 集群上下文中验证每项不变量。

  1. 存在一个 clusters.platform.tkestack.io/<cluster-name> 对象。

    kubectl get clusters.platform.tkestack.io <cluster-name>
  2. Cluster API Cluster 资源带有标签 capi.cpaas.io/imported: ""。

    健康导入时,标签值为空字符串 "",因此仅使用 jsonpath 查询无法区分“缺少标签”和“标签值为空”。请使用 jq 显式检查标签是否存在:

    kubectl get cluster <cluster-name> -n <namespace> -o json | \
      jq -r 'if (.metadata.labels | has("capi.cpaas.io/imported"))
             then "present (value=\"\(.metadata.labels["capi.cpaas.io/imported"])\")"
             else "missing"
             end'

    预期输出:present (value="")。missing 表示导入尚未完成。

  3. 恰好有一个 clustercredentials.platform.tkestack.io 对象带有该集群的标签。

    kubectl get clustercredentials.platform.tkestack.io -o json | \
      jq -r --arg c <cluster-name> \
        '.items[] | select(.metadata.labels["cluster.x-k8s.io/cluster-name"]==$c) | .metadata.name'

    应只打印一个名称。

  4. 在业务集群内部,sentry ServiceAccount 存在于 cpaas-system 中。

    kubectl --kubeconfig <workload-kubeconfig> -n cpaas-system get serviceaccount sentry

如果任何不变量不成立,则该业务集群尚未被 global 集群的导入控制器导入,因此预期会出现上述症状模式。

诊断步骤

步骤 1 — 确认 Cluster API 接口正常

kubectl get cluster <cluster-name> -n <namespace> -o wide
kubectl get kubeadmcontrolplane -n <namespace>
kubectl get machinedeployment -n <namespace>

如果此处失败,则与导入模式无关;请直接调查基础设施提供商。

步骤 2 — 检查 Machine 和 Node 状况

kubectl get machine -n <namespace> \
  -l cluster.x-k8s.io/cluster-name=<cluster-name> \
  -o jsonpath='{range .items[*]}{.metadata.name}{" phase="}{.status.phase}{" "}{range .status.conditions[*]}{.type}={.status} {end}{"\n"}{end}'

如果 phase=Running,但 NodeHealthy 状况为 False,则底层业务节点处于 NotReady 状态。继续执行步骤 3。

步骤 3 — 检查基础设施提供商协调器日志

kubectl logs -n cpaas-system <infra-provider-manager-pod> --tail=200 | \
  grep -E 'ServiceAccount|sentry|<cluster-name>'

如果看到重复的 ServiceAccount "sentry" not found 错误,同时 CNI AppRelease 对象协调失败,则说明由于导入流程尚未完成,业务集群的 CNI 未能部署。继续执行步骤 4。

步骤 4 — 验证 global 集群已导入业务集群

运行上一节中的不变量检查。导入失败的综合诊断特征如下:

  • clusters.platform.tkestack.io/<cluster-name> 返回 NotFound。
  • Cluster.metadata.labels 不包含 capi.cpaas.io/imported。

步骤 5 — 验证 ClusterCredential 数量不变量

kubectl get clustercredentials.platform.tkestack.io -o json | \
  jq -r --arg c <cluster-name> \
    '[.items[] | select(.metadata.labels["cluster.x-k8s.io/cluster-name"]==$c)] | length'

健康的集群会打印 1。大于 1 的值(例如 8)表示导入流程反复尝试但均失败,留下了孤立的凭据。

表示导入失败的模式

当以下所有条件同时满足时,诊断结果表明导入失败:

  • Cluster API 表面正常(Cluster.status.phase=Provisioned、KubeadmControlPlane.status.ready=true)。
  • Machine.condition.NodeHealthy=False 以及至少一个业务节点处于 NotReady 状态。
  • 基础设施 provider 日志反复报告 ServiceAccount "sentry" not found。
  • clusters.platform.tkestack.io/<cluster-name> 不存在。
  • Cluster 资源不包含 capi.cpaas.io/imported 标签。
  • 多个 clustercredentials.platform.tkestack.io 对象带有该集群的标签。

当出现此模式时,业务集群在 global 集群上的初始导入失败,导入控制器当前不会从头开始重试。

此模式无法通过以下方式解决

WARNING

在 global 集群上重启 cluster-transformer pod,不会重新导入其初始导入已按此模式失败的业务集群。手动重启 pod 后,日志中不会再出现受影响集群的条目,并且不会创建缺失的 clusters.platform.tkestack.io 条目。

当同一个集群存在多个孤立的 ClusterCredential 时,不要假定控制器最终会自行恢复。

后续步骤

请向平台支持团队提供以下信息:

  • 集群名称和命名空间。
  • 步骤 1 至 5 中诊断命令的输出。
  • 与受影响集群共享同一 cluster.x-k8s.io/cluster-name 标签的每个 clustercredentials.platform.tkestack.io 对象的名称和创建时间戳。

当前的恢复方式要求先清理孤立的 ClusterCredential 条目,然后删除并重新创建业务集群。未经平台支持团队指导,请勿在生产集群上执行此操作:重新创建流程会触发 IaaS 平台上底层虚拟机的删除,并且在执行重新创建前,必须审查特定于 provider 的详细信息(例如 DCS IP 池和主机名规划,或 HCS HCSMachineConfigPool 重新分配)。

另请参阅