首页 > 系统相关 >kube-apiserver内存溢出问题调查及go tool pprof工具的使用

kube-apiserver内存溢出问题调查及go tool pprof工具的使用

时间:2023-07-26 16:33:06浏览次数:50  
标签:pprof tool apiserver -- 内存 go kube

问题描述

测试集群三台master,每个master上面的kube-apiserver都频繁的重启。登录其中一台master,发现kube-apiserver的内存占用特别高,每次重启完后内存很快就飙到了20G左右,而且还有继续增长的趋势。因为默认kube-apiserver的静态pod是没有设置memeory limit的,最终api-server会吃光机器的所有内存,导致master机器运行异常。

查看容器内存占用的命令:

docker stats --no-stream |grep kube-apiserver

crio 使用 crictl
container_id=`crictl ps -a | grep etcd`
crictl  stats $container_id

临时方案

出现问题后,没有找到问题根源,所以先修改了kube-apiserver的静态pod yaml文件,位于/etc/kubernetes/manifests/kube-apiserver.yaml,添加resources.limits.memory 为32g(本机内存为64g)。这样现在kube-apiserver的内存,使它消耗内存到32g的时候就oom kill自动重启, 大内存方案可行,如果内存较小,很快就会重启。

问题分析

api-server内存持续升高,肯定是有资源在堆内存里申请了空间但是没有释放。首先考虑是否是因为建立了太多的链接导致的,使用如下指令查询kube-apiserver链接数:

netstat -nat | grep -i "6443" | wc -l

发现链接数在100多并不算多。

继续分析只能考虑导出kube-apiserver的heap文件来查看其详细的内存分布。这种方式需要使用go语言包的pprof工具,下面详细讲解go tool pprof 工具的使用以及kube-apiserver的配置。

 

go tool pprof 工具使用

kube-apiserver集成了pprof工具,可以通过链接/debug/prof/heap的url来获得heap文件。

pprof是什么

pprof 是 go 语言自带的基础库,可以分析程序的运行情况,并且提供可视化的功能。它包含两个相关的库:runtime/pprof 和 net/http/pprof , net/http/pprof 可以提供一个 HTTP 接口,获得性能数据,它的底层使用的 runtime/pprof

pprof如何使用

一般如果我们使用 net/http/pprof 并开启了端口监听,如8001端口,我们就可以通过浏览器访问该服务pprof的页面,例如 http://127.0.0.1:8080/debug/pprof/ 

我们常用的参数为

allocs 所有过去内存分配的采样
goroutine 所有当前goroutine的堆栈跟踪
heap 对活动对象的内存分配进行采样
profile cpu profile采样

刚才分析的是 heap 内存情况,同样可以根据需要分析前面说的所有采样。

#所有过去内存分配的采样
go tool pprof http://127.0.0.1:8001/debug/pprof/allocs
#对活动对象的内存分配进行采样(活动)
go tool pprof http://127.0.0.1:8001/debug/pprof/heap
# 下载 cpu profile,默认从当前开始收集 30s 的 cpu 使用情况,需要等待 30s
go tool pprof http://127.0.0.1:8001/debug/pprof/profile
# wait 120s
go tool pprof http://127.0.0.1:8001/debug/pprof/profile?seconds=120    
#导致同步原语阻塞的堆栈跟踪
go tool pprof http://127.0.0.1:8001/debug/pprof/block
#所有当前goroutine的堆栈跟踪
go tool pprof http://127.0.0.1:8001/debug/pprof/goroutine
#争用互斥锁持有者的堆栈跟踪
go tool pprof http://127.0.0.1:8001/debug/pprof/mutex
#当前程序的执行轨迹。

 

 

使用 pprof 分析 kubelet 性能

想要获取 kubelet 的 pprof 数据,首先需要使用kubectl proxy命令启动API server代理

# kubectl proxy --address='0.0.0.0'  --accept-hosts='^*$'
Starting to serve on [::]:8001

 

#新开一个terminal,执行如下指令,进入交互界面

#输入
./go tool pprof http://127.0.0.1:8001/debug/pprof/heap


# 输入top 20
#进入交互界面后,输入top 20查看内存使用前20的函数调用
Fetching profile over HTTP from http://127.0.0.1:8001/debug/pprof/heap
Saved profile in /root/pprof/pprof.kube-apiserver.alloc_objects.alloc_space.inuse_objects.inuse_space.004.pb.gz
File: kube-apiserver
Type: inuse_space
Time: Dec 10, 2020 at 2:46pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)top 20


#得到如下输出
Showing nodes accounting for 11123.22MB, 95.76% of 11616.18MB total
Dropped 890 nodes (cum <= 58.08MB)
Showing top 20 nodes out of 113
     flat  flat%   sum%        cum   cum%
9226.15MB 79.43% 79.43%  9226.15MB 79.43%  bytes.makeSlice
1122.61MB  9.66% 89.09%  1243.65MB 10.71%  k8s.io/kubernetes/vendor/k8s.io/api/core/v1.(*ConfigMap).Unmarshal
 139.55MB  1.20% 90.29%   153.05MB  1.32%  k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1.(*ObjectMeta).Unmarshal
 120.53MB  1.04% 91.33%   165.03MB  1.42%  encoding/json.(*decodeState).objectInterface
 117.29MB  1.01% 92.34%   117.29MB  1.01%  reflect.unsafe_NewArray
 108.03MB  0.93% 93.27%   108.03MB  0.93%  reflect.mapassign
  66.51MB  0.57% 93.84%    66.51MB  0.57%  k8s.io/kubernetes/vendor/github.com/json-iterator/go.(*Iterator).ReadString
  62.51MB  0.54% 94.38%    62.51MB  0.54%  k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/registry/generic.ObjectMetaFieldsSet
  61.51MB  0.53% 94.91%    61.51MB  0.53%  k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource.objectMetaFieldsSet
  43.01MB  0.37% 95.28%   137.03MB  1.18%  k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime.structToUnstructured
     18MB  0.15% 95.43%   183.61MB  1.58%  k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/storage/cacher.(*watchCache).Replace
  13.50MB  0.12% 95.55%   137.03MB  1.18%  k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime.toUnstructured
      9MB 0.077% 95.63%   237.54MB  2.04%  k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured.unstructuredJSONScheme.decodeToUnstructured
   7.50MB 0.065% 95.69%   144.53MB  1.24%  k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime.(*unstructuredConverter).ToUnstructured
      6MB 0.052% 95.74%   123.29MB  1.06%  reflect.MakeSlice
   1.50MB 0.013% 95.76%  8944.02MB 77.00%  encoding/json.mapEncoder.encode

 

通过heap文件输出,可以看到占用内存最多的是makeSlice函数占用了9G多的内存。它的调用者是v1.(*ConfigMap).Unmarshal,configmap是kubernetes的一种资源,Unmarshal是json和struct做转换的函数。所以怀疑与configmap资源有关。

在宿主机上使用

kubectl get configmap -A 发现命令卡死没有输出,但是在特定的某一个namespace下进行kubectl get configmap是有返回的。所以怀疑其中的某一个namespace下有大量的configmap,kubectl get configma卡死从而导致kubectl get configmap -A卡死。

下面就尝试在每一个namespace下执行kubectl get configmap。当执行到kubectl get configmap -n kubesphere-controls-system,时发现命令卡住,在等待了3分钟后有数据返回。使用wc统计了数量发现kubesphere-controls-system下有17万多的configmap,大多是kubeconfig-xxxx样子的。后面的xxx是用户名。使用kubectl get user同样发现了有17万多的用户。应该是之前同步的ldap的用户,每创建一个用户,就会在kubesphere-controls-system下新建一个configmaps。查看etcd db文件,发现达到了1.5g左右,其他正常的集群db文件一般在50M甚至更低。

分析到这里,问题基本明朗了。可能是kubesphere 2.x版本时同步了ldap的数据到kubesphere中,kubesphere每创建一个user就会新建个对应的configmap里面存着key和cert。17万configmap,导致api-server去list configmap时无法一次获取到,就会一直创建slice(这里应该是golang语言包里的一个bug https://studygolang.com/artic...,从而使api-server耗尽内存

解决方案

最终的解决方案就是删除这些ldap用户,kubesphere升级到3.0后每一次登录都直接到ldap验证,且是在host集群上执行的。被纳管集群不需要存贮这些数据。在使用kubectl delete user发现用户无法删除,因为etcd数据量太大了,kube-apiserver与etcd之间的调用性能下降很严重。kube-apiserver已经无法正常的提供服务了。所以考虑使用etcdctl直接链接etcd来删除数据

#删除 user
ETCDCTL_API=3 etcdctl --endpoints https://10.250.7.21:2379 --cacert $ETCD_TRUSTED_CA_FILE --cert $ETCD_CERT_FILE --key $ETCD_KEY_FILE del /registry/iam.kubesphere.io/users/ --prefix
#删除对应的 configmap
ETCDCTL_API=3 etcdctl --endpoints https://10.250.7.21:2379 --cacert $ETCD_TRUSTED_CA_FILE --cert $ETCD_CERT_FILE --key $ETCD_KEY_FILE del /registry/configmaps/kubesphere-controls-system/kubeconfig- --prefix

 

删除完数据后,使用docker restart 重启kube-apiserver,观测了一会,发现内存一直保持在1g左右。kubectl操作以及sit集群的web页面响应都比之前快了许多。

 

参考:

https://segmentfault.com/a/1190000039649589
https://blog.csdn.net/buppt/article/details/127505818

 

标签:pprof,tool,apiserver,--,内存,go,kube
From: https://www.cnblogs.com/fengjian2016/p/17582844.html

相关文章

  • k8s使用token访问集群apiserver
    exportTOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6InRjMEs2b2tyVUFjdHZuazNTS1VrM0s3LWFHMlVjek5NTUJnVUVSTTVHQnMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJzaGlvcmlrbyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY29......
  • Tool-Gitlab-备份恢复-迁移
    Tool-Gitlab-备份恢复-迁移备份sudogitlab-rakegitlab:backup:create使用命令会在/var/opt/gitlab/backups目录下创建一个压缩包,这个压缩包就是Gitlab整个的完整部分。需要在gitlab运行时操作。gitlab.rb和gitlab-secrets.json两个文件包含敏感信息。未被备份到备份文......
  • Tool-CMake-添加自定义宏定义
    Tool-CMake-添加自定义宏定义cmake,makefile中定义的宏变量,其实和C/C++中的#define是一致的,可以传入到C/C++中。控制程序的编译比如:cmake中有宏定义:add_definitions(-Dhello="hellocmake")......
  • Tool-Gitlab-502-端口占用
    安装Gitlab后,登陆报错502,端口占用卸载一、卸载GitLab及其依赖1、首先停止GitLab的运行命令:sudogitlab-ctlstop2、卸载GitLab:sudoapt-getremovegitlab-ce3、卸载GitLab依赖:sudoapt-getautoremove-y4、移除GitLab相关的文件:sudorm-rf/opt/gitlabtail日志sud......
  • Tool-Intel VTune Profiler
    Tool-IntelVTuneProfiler转自使用IntelVTuneProfiler进行性能分析及优化初识Intel®VTune™ProfilerIntelVTuneProfiler是一个全平台的性能分析工具,可以帮助你快速发现和分析应用程序及整个系统的性能瓶颈。工具支持分析本地或远程的Windows,Linux及Android应用,这些应......
  • mii-tool
    mii-tool配置网络设备协商方式的工具补充说明mii-tool命令是用于查看、管理介质的网络接口的状态,有时网卡需要配置协商方式,比如10/100/1000M的网卡半双工、全双工、自动协商的配置。但大多数的网络设备是不用我们来修改协商,因为大多数网络设置接入的时候,都采用自动协商来解决......
  • Java生成SSL自签名证书及解析(keytool方式和源码方式)
    一:序当需要在Java应用程序中使用SSL/TLS加密通信或进行身份验证时,证书是必不可少的。证书可以用来验证服务器的身份,并确保通信的安全性。在Java开发中,可以使用JDK自带的keytool工具生成自签名证书。而本文将介绍如何使用JDK的keytool工具生成自签名证书以及相......
  • 晶晨刷机工具usb burning tool刷机卡住
    解决方法使用usb双公头线,不要使用typec线直接连笔记本AMD平台使用usb3.0接口软件一检测到设备就可以断开短接点了,不用一直短接......
  • 在Vue3中,解决 Echart tooltip 不显示的问题
    为什么在Vue中使用ECharts时图表显示异常?Vue3,中使用reactive及ref会导致ECharts的对象实例被代理成为响应式对象,影响ECharts对内部属性的访问,可能会导致图表无法正确显示等一系列意外问题,且会由于深度监听而极大地降低图表展示性能。解决方案为:使用普通变量声明ECh......
  • rrdtool的使用介绍
    rrdtool的使用介绍rrdtool的介绍rrdtool(roundrobindatabase)工具为环状数据库的存储格式。roundrobin是一种处理定量数据以及当前元素指针的技术。rrdtool主要用来跟踪对象的变化情况,生成这些变化的走势图,比如业务的访问流量,系统性能,磁盘利用率等趋势图,很多流行监控平台都使......