k8s node 热扩容内存导致的一次业务故障
由来
2024/04 月底发生的,k8s node 热扩容内存导致的一次业务故障,此次不是排查,而是过程梳理。k8s 版本是 1.27.4。
过程
我们有些业务的 cpu 和内存是根据使用人数上涨的,多副本资源占用 > 单个高配副本,例如 1000 个人使用某个功能,多副本可能需要 6个 4c4G,但是单个副本 18c16G 就可以。所以我们的核心业务服务都是不加 limit 的。该服务也有自我限制,例如它最多使用机器的 85% 内存后,后续请求就不处理。
客户使用人数上升,告警后现场人员让客户给机器加了内存(hotplug) 由 64g -> 128g ,然后过了一天后机器频繁驱逐导致 cpu 高。看 kubelet 日志报错内存压力触发驱逐,但是看监控使用还好(node_exporter获取是实时的)内存没到 75% 以上才 65%,核心服务日志里也没到百分比上线内存,后面发现是 kubelet 的内存信息还是老的:
1 | Capacity: |
重启 kubelet 后,内存信息就正常了:
1 | Capacity: |
代码分析
在 func NewMainKubelet(
里,只获取一次
1 | // https://github.com/kubernetes/kubernetes/blob/7b359a2f9e1ff5cdc49cfcc4e350e9d796f502c0/pkg/kubelet/kubelet.go#L607-L614 |
全局搜 setCachedMachineInfo(
找到了 kubernetes/pkg/kubelet/kubelet_getters.go
下的:
1 | // GetCachedMachineInfo assumes that the machine info can't change without a reboot |
搜 GetCachedMachineInfo
找到 kubernetes/pkg/kubelet/kubelet_node_status.go
下:
1 | // https://github.com/kubernetes/kubernetes/blob/d1c7f7a0e9d59aa88aa5b4d07db7e14772b3e386/pkg/kubelet/kubelet_node_status.go#L733 |
然后 kubernetes/pkg/kubelet/nodestatus/setters.go
里的 func MachineInfo(
1 | // https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/nodestatus/setters.go#L283 |
defaultNodeStatusFuncs
是 node kubelet 每 nodeStatusUpdateFrequency
时候查看一些信息变化否,变了后面会上报更新,从上面整个代码流程看是只获取了一次,开了个虚拟机搭建修改代码 GetCachedMachineInfo()
内尾部追加,编译替换后运行,扩容测试了下可以不重启动态更新:
1 | // Avoid collector collects it as a timestamped metric |
后面去提了 kep Hot increase cpu/memory/storage without restarting kubelet 但是发现之前就有了,只不过依旧没符合要求和合入。