1 事件背景
大家都知道 k8s 容量不够的时候,都是添加节点(横向扩展)来解决问题。这几天有小伙伴在升级 k8s 容量的时候碰到一个问题,他将集群中某一个 node节点的 CPU 做了升级(纵向扩展),然后重启了这个 node 节点导致 kubelet 无法启动,然后大量 pod 被驱逐,报警电话响个不停。为了紧急恢复业务,果断参加故障恢复。
2 现象获取
在知道事件背景后,我登上了那个已经重启完毕的 node 节点,开始了一系列的网络测试,确认 node 这个宿主机到 Apiserver 和 Loadbalancer 的 ip 和 port 都是通的。随后赶紧看了下 kubelet 的日志,果不其然,一行日志让我看到问题点:
E1121 23:43:52.644552 23453 policy_static.go:158] "Static policy invalid state, please drain node and remove policy state file" err="current set of available CPUs \"0-7\" doesn't match with CPUs in state \"0-3\""
E1121 23:43:52.644569 23453 cpu_manager.go:230] "Policy start error" err="current set of available CPUs \"0-7\" doesn't match with CPUs in state \"0-3\""
E1121 23:43:52.644587 23453 kubelet.go:1431] "Failed to start ContainerManager" err="start cpu manager error: current set of available CPUs \"0-7\" doesn't match with CPUs in state \"0-3\""
说到这里,很多小伙伴会说:“就这??”。 真的就这。是因为啥呢? 是因为 kubelet 启动参数里面有一个参数很重要:–cpu-manager-policy 。表示 kubelet 在使用宿主机的 cpu 是什么逻辑策略。如果你设定为 static ,那么就会在参数 –root-dir 指定的目录下生成一个 cpu_manager_state 这样一个绑定文件。
cpu_manager_state 内容大致长得如下:
[root@master-01 system]# cat /var/lib/kubelet/cpu_manager_state
{ "policyName": "static", "defaultCpuSet": "0-7", "checksum": 14413152 }
当你升级这个 k8s node 节点的 CPU 配置,并且使用了 static cpu 管理模式,那么 kubelet 会读取 cpu_manager_state 文件,然后跟现有的宿主运行的资源做对比,如果不一致,kubelet 就不会启动了。
3 原理分析
参考官网。
4 解决方案
因此,当我们发现“start cpu manager error”之类的错误时,就可以按照下面的步骤进行尝试解决:
第一步:首先要删除系统的/var/lib/kubelet/cpu_manager_state或者/var/lib/kubelet/memory_manager_state(扩容内存的话,也有可能会出现这个问题),避免与旧的策略产生冲突
# rm /var/lib/kubelet/cpu_manager_state
第二步:加载服务
# systemctl daemon-reload
第三步:重启kubelet服务
# systemctl restart kubelet
这样的话,新的CPU管理策略文件就会重新生成,然后观察服务否恢复正常。