
Kubernetes集群CPU使用率高达100%,详细排查过程!
作者介绍
谢泽钦,Rancher Labs技术支持工程师,负责Rancher中国客户的维护和相关技术支持。4年的云计算领域的经验,经历了OpenStack到Kubernetes的技术变革,对底层操作系统、KVM虚拟化和Docker容器等相关云技术拥有丰富的运维和实践经验。
本文是为Rancher客户进行问题排查的记录。
问题背景
我们发现客户的Kubernetes集群环境中所有的worker节点的Kubelet进程的CPU使用率长时间占用过高,通过pidstat可以看到CPU使用率高达100%。本文记录下了本次问题排查的过程。

集群环境
|
|
|
|
|
|
|
|
|
|
|
|
排查过程
使用strace工具对kubelet进程进行跟踪


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
The operation in futex_op employed the timeout specified in
timeout, and the timeout expired before the operation
completed.
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函数调用进行分析
kubectl proxy --address='0.0.0.0' --accept-hosts='^*$'
docker run -itd --name golang-env --net host golang bash
docker exec -it golang-env bash
go tool pprof -seconds=60 -raw -output=kubelet.pprof http://127.0.0.1:8001/api/v1/nodes/${NODENAME}/proxy/debug/pprof/profile
git clone https://github.com/brendangregg/FlameGraph.git
cd FlameGraph/
./stackcollapse-go.pl kubelet.pprof > kubelet.out
./flamegraph.pl kubelet.out > kubelet.svg

func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
// Set stats from memory.stat.
statsFile, err := os.Open(filepath.Join(path, "memory.stat"))
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
defer statsFile.Close()
sc := bufio.NewScanner(statsFile)
for sc.Scan() {
t, v, err := fscommon.GetCgroupParamKeyValue(sc.Text())
if err != nil {
return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err)
}
stats.MemoryStats.Stats[t] = v
}
stats.MemoryStats.Cache = stats.MemoryStats.Stats["cache"]
memoryUsage, err := getMemoryData(path, "")
if err != nil {
return err
}
stats.MemoryStats.Usage = memoryUsage
swapUsage, err := getMemoryData(path, "memsw")
if err != nil {
return err
}
stats.MemoryStats.SwapUsage = swapUsage
kernelUsage, err := getMemoryData(path, "kmem")
if err != nil {
return err
}
stats.MemoryStats.KernelUsage = kernelUsage
kernelTCPUsage, err := getMemoryData(path, "kmem.tcp")
if err != nil {
return err
}
stats.MemoryStats.KernelTCPUsage = kernelTCPUsage
useHierarchy := strings.Join([]string{"memory", "use_hierarchy"}, ".")
value, err := fscommon.GetCgroupParamUint(path, useHierarchy)
if err != nil {
return err
}
if value == 1 {
stats.MemoryStats.UseHierarchy = true
}
pagesByNUMA, err := getPageUsageByNUMA(path)
if err != nil {
return err
}
stats.MemoryStats.PageUsageByNUMA = pagesByNUMA
return nil
}
# time cat /sys/fs/cgroup/memory/memory.stat >/dev/null
real 0m9.065s
user 0m0.000s
sys 0m9.064s
解决方法
echo 2 > /proc/sys/vm/drop_caches
-
其实这个主要还是内核的问题,在GitHub上这个commit(https://github.com/torvalds/linux/commit/205b20cc5a99cdf197c32f4dbee2b09c699477f0)中有提到,在5.2+以上的内核版本中,优化了CGroup stats相关的查询性能,如果想要更好的解决该问题,建议可以参考自己操作系统和环境,合理的升级内核版本。 -
另外Redhat在kernel-4.18.0-176(https://bugzilla.redhat.com/show_bug.cgi?id=1795049)版本中也优化了相关CGroup的性能问题,而CentOS 8/RHEL 8默认使用的内核版本就是4.18,如果目前您使用的操作系统是RHEL7/CentOS7,则可以尝试逐渐替换新的操作系统,使用这个4.18.0-176版本以上的内核,毕竟新版本内核总归是对容器相关的体验会好很多。
kernel相关commit:
https://github.com/torvalds/linux/commit/205b20cc5a99cdf197c32f4dbee2b09c699477f0
redhat kernel bug fix:
https://bugzilla.redhat.com/show_bug.cgi?id=1795049
文章来源:Rancher Labs / 原文链接

Linux技术高效运维 » Kubernetes集群CPU使用率高达100%,详细排查过程!
常见问题FAQ
- 资源有效期多久?
- 没有下载到资源?
- 在哪里能够获得该资源?