kubernets节点异常问题分析

本文分析了Kubernetes集群中节点异常,尤其是Node处于Ready状态但不可用的问题。通过kubelet的状态上报机制,包括NodeLease和NodeStatus,探讨了为何节点在磁盘故障时仍显示为Ready。同时,解释了os-image显示unknow的原因,并讨论了监控数据获取原理,提出使用node-problem-detector来增强节点状态判断。
摘要由CSDN通过智能技术生成

问题现象

kubernetes集群中,发生部分pod应用不可用的告警

问题排查

基于这种情况,根据经验判断,怀疑是对应的某个节点出现问题。

  1. 找到其中一个pod,kubectl get pod -o wide|grep pod-xxx 查看其在哪个节点上

  2. 通过kubectl describe node xxxx 查看该node上的信息,发现该节点上的pod都出现上在了不可用的应用清单中。另外还观察到了一条warning信息

image-20210730172143273.png

  1. 通过其ip地址,登录服务器,发现已经无法登录了。
  2. 查看node节点监控,看能否发现一些端倪。监控数据却没有异常。初步确认是底层服务器问题,赶紧反馈给云厂商。
  3. 排查影响范围,通过kubectl get node -o wide ,发现一个很奇怪的现象,node节点处于ready状态,但是os-image字段显示unknow状态
  4. 将其unknow状态的节点逐一测试,发现都无法登录。

image-20210730172104898.png

其实问题通过上面一顿操作,可以得到一个基本结论,出现了unknown状态的node存在问题,导致该节点上的pod都不可用。具体原因还要看云厂商给出结论。从目前得到的信息推断应该是物理机磁盘出现问题,导致文件系统io出现错误。所以后面的分析也是基于这个结论去分析的。

事情到这里,我们还是有些问题要去反思的。

  1. 服务器上的pod都不可用了,且服务器也无法登录了,而k8s的出问题的node节点为什么状态还是Ready?
  2. 服务器不可用了,监控为什么还是正常的?
  3. 问题节点的os-image的信息为什么是unknown的状态?

问题解惑

要弄清上面的问题,我们要先看下kubelet的状态上报机制是怎样的。或许能够解答第一个和第三个问题。

kubelet的状态上报机制

在 v1.13 之前的版本中,节点的心跳只有 NodeStatus,从 v1.13 开始,NodeLease feature 作为 alpha 特性引入。当启用 NodeLease feature 时,每个节点在“kube-node-lease”名称空间中都有一个关联的“Lease”对象,该对象由节点定期更新,NodeStatus 和 NodeLease 都被视为来自节点的心跳。NodeLease 会频繁更新,而只有在 NodeStatus 发生改变或者超过了一定时间(默认值为1分钟,node-monitor-grace-period 的默认值为 40s),才会将 NodeStatus 上报给 master。由于 NodeLease 比 NodeStatus 更轻量级,该特性在集群规模扩展性和性能上有明显提升。

1584064568734-eb0c7ce1-a896-4b8b-a1c3-e289e1091aa2-7802610.png

上传信息

状态的信息的心跳我么依靠nodelease来实现,减少apiserver的压力。其上传的信息相对于node的信息少很多,比较轻量级。

// kubernetes/pkg/kubelet/kubelet.go
func (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate) {
    
  ...
  if kl.kubeClient != nil {
   
		// Start syncing node status immediately, this may set up things the runtime needs to run.
    // 通过node的状态信息
		go wait.Until(kl.syncNodeStatus, kl.nodeStatusUpdateFrequency, wait.NeverStop)
		// 更新node的缓存信息
    go kl.fastStatusUpdateOnce()

		// start syncing lease
    // 开启同步lease信息
		go kl.nodeLeaseController.Run(wait.NeverStop)
	}
  ...
}
NodeLease

通过一下代码我们可以看到,只是上传一个很简单数据。

// retryUpdateLease attempts to update the lease for maxUpdateRetries,
// call this once you're sure the lease has been created
func (c *controller) retryUpdateLease(base *coordinationv1.Lease) error {
   
  // 上传重试机制
	for i := 0; i < maxUpdateRetries; i++ {
   
    // 生成新的lease
		leaseToUpdate, _ := c.newLease(base)
    // 更新apiserver的信息
		lease, err := c.leaseClient.Update(context.TODO(), leaseToUpdate, metav1.UpdateOptions{
   <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值