背景
近期项目引入了 cliet-go watch Pod ,但内存开始非预期地水涨船高。
Watch 的 Pod 数量大概 3.3k 左右,实际内存在 130MB 左右。但是内存涨幅巨大。
| 观察项 | 引入 watch 前 | 引入 watch 后 | 涨幅 |
|---|---|---|---|
| ps | 182MB | 825MB | 643MB |
| heapSys | 367MB | 755MB | 388MB |
| heapInuse | 94MB | 699MB | 605MB |
| pprof | 62MB | 369MB | 307MB |
问题 1:内存指标与分析问题
- heapInuse 和 pprof 中的内存 gap 是啥呢?我理解 pprof 中显示的内存(369MB)不就是堆内存吗,heapInuse(699MB)也是如此?那之间为啥差着 300+MB 呢?
- 大家平时有没有趁手的工具分析内存呢? viewcore 有大佬用吗,官方仓库下没有 quickstart,按照教程直接就是 panic
问题 2:内存为啥涨这么多
这个我找到社区的一个Issue,大概就是 informer 的 relfector 踩了一个 gogc 的坑,将[]pod转成[]*pod时,原来的 slice 无法 gc ,最终导致双倍的 Pod 内存压力。
但是当前现状是,整体 Pod 实际 size 只有 130MB ,双倍也就是 260MB ,加上 Slice 的 buffer 算 300MB ,和 pprof 的涨幅比较吻合(即涨幅 300MB ),但是和 HeapInuse 的涨幅就差太多了,但是从监控上看 RSS 涨幅又与 HeapInuse 的涨幅一致(即涨幅 600MB)。所以又回到了第一个问题。
问题 3:k8s 这个坑怎么解
另外,关于 client-go 这个双倍内存的问题,之前提到的 Issue 里,有个大佬开源了一个工具说解决了这个问题,但我用下来,实际没解决。。。,所以大家是怎么解决的呢?由于 Kubernetes 并不是我在维护,所以升级版本之类的就不可行了。