kubelet CPU 使用率过高问题排查
问题背景
客户的k8s集群环境,发现所有的worker节点的kubelet进程的CPU使用率长时间占用过高,通过pidstat可以看到CPU使用率高达100%。针对此问题对kubelet进程的异常进行问题排查。
集群环境
软件 | 版本 |
---|---|
kubernetes | v1.18.8 |
docker | 18.09.9 |
rancher | v2.4.8-ent |
CentOS | 7.6 |
kernel | 4.4.227-1.el7.elrepo.x86_64 |
排查过程
使用strace工具对kubelet进程进行跟踪
- 由于kubelet进程CPU使用率异常,可以使用strace工具对kubelet进程动态跟踪进程的调用情况,首先使用
strace -cp <PID>
命令统计kubelet进程在某段时间内的每个系统调用的时间、调用和错误情况.
从上图可以看到,执行系统调用过程中,futex抛出了五千多个errors,这肯定是不正常的,而且这个函数占用的时间也达到了99%,所以需要更深层次的查看kubelet进程相关的调用。
- 由于
strace -cp
命令只能查看进程的整体调用情况,所以我们可以通过strace -tt -p <PID>
命令打印每个系统调用的时间戳,如下:
从strace输出的结果来看,在执行futex相关的系统调用时,有大量的Connect timed out,并返回了-1
和ETIMEDOUT
的error,所以才会在strace -cp
中看到了那么多的error。
futex是一种用户态和内核态混合的同步机制,当futex变量告诉进程有竞争发生时,会执行系统调用去完成相应的处理,例如wait或者wake up,从官方的文档了解到,futex有这么几个参数:
futex(uint32_t *uaddr, int futex_op, uint32_t val,
const struct timespec *timeout, /* or: uint32_t val2 */
uint32_t *uaddr2, uint32_t val3);
官方文档给出ETIMEDOUT
的解释:
ETIMEDOUT
The operation in futex_op employed the timeout specified in
timeout, and the timeout expired before the operation
completed.
意思就是在指定的timeout时间中,未能完成相应的操作,其中futex_op
对应上述输出结果的FUTEX_WAIT_PRIVATE
和FUTEX_WAIT_PRIVATE
,可以看到基本都是发生在FUTEX_WAIT_PRIVATE
时发生的超时。
从目前的系统调用层面可以判断,futex无法顺利进入睡眠状态,但是futex做了哪些操作还是不清楚,还无法判断kubeletCPU飙高的原因,所以我们需要进一步从kubelet的函数调用中去看到底是执行了卡在了哪个地方。
FUTEX_PRIVATE_FLAG:这个参数告诉内核futex是进程专用的,不与其他进程共享,这里的FUTEX_WAIT_PRIVATE和FUTEX_WAKE_PRIVATE就是其中的两种FLAG;
futex相关说明1:https://man7.org/linux/man-pages/man7/futex.7.html
fuex相关说明2: https://man7.org/linux/man-pages/man2/futex.2.html
使用go pprof工具对kubelet函数调用进行分析
早期的k8s版本,可以直接通过debug/pprof
接口获取debug数据,后面考虑到相关安全性的问题,取消了这个接口,参考