node-agent 报错 Either cluster is not ready for registering, cluster is currently provisioning, or etcd, controlplane and worker node have to be registered
本文永久链接: https://www.xtplayer.cn/rancher/either-cluster-is-not-ready-for-registering/
问题背景
某天一客户突然反馈 rancher local 集群节点 32G 内存资源耗尽,local 集群中只运行了 rancher 相关业务。
经过一系列排查,发现耗尽内存的是 k8s apiserver 进程。在 apiserver 容器日志中发现了大量以下日志:
{"log":"I0507 08:24:37.492998 1 pathrecorder.go:253] kube-apiserver: \"/apis/management.cattle.io/v3/namespaces/c-dql6k/nodes/machine-h46dc\" satisfied by NotFoundHandler\n","stream":"stderr","time":"2022-05-07T08:24:37.495887119Z"} |
问题排查
rancher 中保存的数据,均是以 CRD(CustomResourceDefinition)(https://kubernetes.io/zh/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/)资源的形式存储在 K8S 中,rancher 会通过 kubernetes svc
调用 local k8s apiserver 来读写 CRD 资源。
management.cattle.io
是 rancher 存储数据的 API Group
,所有与 rancher 相关的 CRD 资源均在这个 API Group
中。
在 rancher 中有一个叫做 nodes.management.cattle.io
的 CRD 资源,这个 CRD 资源用于保存所有集群的 node 配置信息。比如在 local 集群中执行 kubectl get nodes.management.cattle.io -A
可以看到以 CLUSTER-ID 为 NAMESPACE 的 node 列表。
查看 local apiserver 的日志,发现频繁的刷新着 /apis/management.cattle.io/v3/namespaces/c-dql6k/nodes/machine-h46dc
相关字样的日志信息,通过这些信息可以初步判断集群 c-dql6k 的 machine-h46dc 节点可能存在异常。在 rancher 架构中,每个业务集群的节点上均运行着一个 node-agent pod
,这个 pod 主要负责 node 注册以及节点配置更新,如果 rancher 频繁的读写 nodes.management.cattle.io
CRD,那么也说明了对应节点的 node-agent pod
很有可能运行异常。
根据 local apiserver 的日志知道了 cluster-id 和 node-id, 通过在 local 集群中执行以下命令快速定位集群名称以及节点 IP。
kubectl get clusters.management.cattle.io <cluster-id> -ojson|jq .status.appliedSpec.displayName |
kubectl get nodes.management.cattle.io -n <cluster-id> <node-id> -ojson|jq .status.internalNodeStatus.addresses |
通过以上命令快速定位到具体集群和具体的 node 名称,切换到 system 项目下,点击 cattle-system 命名空间下的 cattle-node-agent 服务,根据查询到的 node ip 可以快速的定位到具体的 node-agent pod 名称。
查询 node-agent pod 日志
根据以上操作定位到具体集群以及具体 node agent pod 后,通过 rancher ui 查看 node agent pod 日志。
问题分析
Rancher 中有一个 nodessyncer controller
,它会根据下游集群的 node 情况,把 K8S node 同步到 local 的nodes.management.cattle.io CRD
中。
- 如果是 import 集群,因为 node 已存在,那么在
nodes.management.cattle.io CRD
中将会以machine-
命名方式创建nodes.management.cattle.io
资源。 - 如果自定义集群,正常自定义创建集群时,在 local 集群的 c-xxx ns中创建了 m-xxx node,此时nodessyncer会判断已经存在了这个资源,就不会创建
machine-
node。
基于以上逻辑,出现 node-agent 报以上错误有以下两种可能:
- 在 rancher ui 删除节点时,可能某些原因导致 rancher
nodes.management.cattle.io CRD
中的 node 资源被删除了,但是下游 k8s 集群却未能正常的把节点从 k8s 中剔除。当再次通过 rancher ui 复制添加节点的命令执行后,因为这个时候 node 已经存在 k8s 集群中,因此 node-agent 不会再次注册,所以抛出了错误日志。 - 在清理下游集群节点时,如果先删除的 local m-xxx node,nodessyncer 可能瞬间同步了下游的 native node 并创建machine-xxx node。因为当时下游集群的native node在这个时间窗口,还没有被清理,从程序逻辑执行角度,会出现这种情况。
解决方法
如果集群运行踢出节点,那么最简单的方法就是把异常的节点从集群中中踢出,执行 kubectl get node 命令确认节点已经删除后,再把节点初始化之后重新添加到集群中。
如果节点不能踢出,那么只能通过手动更新配置了。通过执行
kubectl get nodes.management.cattle.io -n <cluster-id> <node-id> -oyaml
导出一个正常节点和异常节点的 YAML ,然后进行对比。
可以发现主要的差异在 status.rkeNode 和 spec.customConfig 。
rkeNode: |
spec.customConfig 配置是做的自定义配置,根据实际清楚修改。
最后执行 kubectl edit nodes.management.cattle.io -n <cluster-id> <node-id> -oyaml
,将以上配置更新即可。