# kubectl top 和 cadvisor metric ，docker state不一致的问题

kubectl top 、 k8s dashboard 以及 HPA 等调度组件使用的数据是一样，数据链路如下：

![](https://upload-images.jianshu.io/upload_images/1889435-eb475a92ab93a9c5?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)

## cgroup

cgroup文件中的值是监控数据的最终来源，如

* mem usage的值，来自于\
  &#x20;`/sys/fs/cgroup/memory/docker/[containerId]/memory.usage_in_bytes`
* 如果没限制内存，Limit = machine\_mem，否则来自于\
  &#x20;`/sys/fs/cgroup/memory/docker/[id]/memory.limit_in_bytes`
* 内存使用率 = memory.usage\_in\_bytes/memory.limit\_in\_bytes

一般情况下，cgroup文件夹下的内容包括CPU、内存、磁盘、网络等信息：

![](https://upload-images.jianshu.io/upload_images/1889435-03c878a978d3fa2f?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)

#### kubectl top pod 内存怎么计算，包含 pause容器 吗

每次启动 pod，都会有一个 pause 容器，既然是容器就一定有资源消耗（一般在 2-3M 的内存），cgroup 文件中，业务容器和 pause 容器都在同一个 pod的文件夹下。

但 cadvisor 在查询 pod 的内存使用量时，是先获取了 pod 下的container列表，再逐个获取container的内存占用，不过这里的 container 列表并没有包含 pause，因此最终 top pod 的结果也不包含 pause 容器

**pod 的内存使用量计算**

kubectl top pod 得到的内存使用量，并不是cadvisor 中的container\_memory\_usage\_bytes，而是container\_memory\_working\_set\_bytes，计算方式为：

* container\_memory\_usage\_bytes == container\_memory\_rss + container\_memory\_cache + kernel memory
* container\_memory\_working\_set\_bytes = container\_memory\_usage\_bytes - total\_inactive\_file（未激活的匿名缓存页）

container\_memory\_working\_set\_bytes是容器真实使用的内存量，也是limit限制时的 oom 判断依据

cadvisor 中的 container\_memory\_usage\_bytes对应 cgroup 中的 memory.usage\_in\_bytes文件，但container\_memory\_working\_set\_bytes并没有具体的文件，他的计算逻辑在 cadvisor 的代码中，如下：[image](https://github.com/kubernetes/kubernetes/blob/596a48dd64bcaa01c1d2515dc79a558a4466d463/pkg/kubelet/server/stats/summary.go)

![](https://upload-images.jianshu.io/upload_images/1889435-e5cf09939d700704?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)

同理，node 的内存使用量也是container\_memory\_working\_set\_bytes

### 4.3 kubectl top node 怎么计算，和节点上直接 top 有什么区别

kubectl top node得到的 cpu 和内存值，并不是节点上所有 pod 的总和，不要直接相加。top node是机器上cgroup根目录下的汇总统计image

![](https://upload-images.jianshu.io/upload_images/1889435-12250b22471254d9?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)

在机器上直接 top命令看到的值和 kubectl top node 不能直接对比，因为计算逻辑不同，如内存，大致的对应关系是(前者是机器上 top，后者是kubectl top):

```
rss + cache = (in)active_anon + (in)active_file
```

image

![](https://upload-images.jianshu.io/upload_images/1889435-9e3dfbb4de2e2b1d?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)

### 4.4 kubectl top pod 和exec 进入 pod 后看到的 top 不一样

top命令的差异和上边 一致，无法直接对比，同时，就算你对 pod 做了limit 限制，pod 内的 top 看到的内存和 cpu总量仍然是机器总量，并不是pod 可分配量

* 进程的RSS为进程使用的所有物理内存（file\_rss＋anon\_rss），即Anonymous pages＋Mapped apges（包含共享内存）
* cgroup RSS为（anonymous and swap cache memory），不包含共享内存。两者都不包含file cache

### 4.5 kubectl top pod 和 docker stats得到的值为什么不同？

docker stats dockerID 可以看到容器当前的使用量：image\


![](https://upload-images.jianshu.io/upload_images/1889435-cdb7681a6e3f8df4?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)

如果你的 pod中只有一个 container，你会发现docker stats 值不等于kubectl top 的值，既不等于 container\_memory\_usage\_bytes，也不等于container\_memory\_working\_set\_bytes。

因为docker stats 和 cadvisor 的计算方式不同，总体值会小于 kubectl top：计算逻辑是：

```
docker stats = container_memory_usage_bytes - container_memory_cache
```

### 五. 后记

一般情况下，我们并不需要时刻关心node 或 pod 的使用量，因为有集群自动扩缩容(cluster-autoscaler)和pod 水平扩缩容（HPA）来应对这两种资源变化，资源指标的意义更适合使用prometheus来持久化 cadvisor 的数据，用于回溯历史或者发送报警。

关于prometheus的内容可以看[容器监控系列](https://links.jianshu.com/go?to=https%3A%2F%2Fyasongxu.gitbook.io%2Fcontainer-monitor%2F)

其他补充：

1. 虽然kubectl top help中显示支持Storage，但直到 1.16 版本仍然不支持
2. 1.13 之前需要 heapster，1.13 以后需要metric-server，这部分kubectl top help的输出 有误，里面只提到了heapster
3. k8s dashboard 中的监控图默认使用的是 heapster，切换为 metric-server后数据会异常，需要多部署一个metric-server-scraper 的 pod 来做接口转换，具体参考 pr：[https://github.com/kubernetes/dashboard/pull/3504](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fkubernetes%2Fdashboard%2Fpull%2F3504)

### 六. 参考资料

* [https://github.com/kubernetes-sigs/metrics-server/issues/193](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fkubernetes-sigs%2Fmetrics-server%2Fissues%2F193)
* [https://github.com/kubernetes/kubernetes/pull/83247](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fkubernetes%2Fkubernetes%2Fpull%2F83247)
* [https://www.cnblogs.com/liuhongru/p/11215447.html](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.cnblogs.com%2Fliuhongru%2Fp%2F11215447.html)
* [https://github.com/DirectXMan12/k8s-prometheus-adapter/blob/master/docs/walkthrough.md#quantity-values](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2FDirectXMan12%2Fk8s-prometheus-adapter%2Fblob%2Fmaster%2Fdocs%2Fwalkthrough.md%23quantity-values)
* [https://github.com/fabric8io/kansible/blob/master/vendor/k8s.io/kubernetes/docs/design/resources.md](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Ffabric8io%2Fkansible%2Fblob%2Fmaster%2Fvendor%2Fk8s.io%2Fkubernetes%2Fdocs%2Fdesign%2Fresources.md)
* [https://erdong.site/linux/system/computer-unit-conversion.html](https://links.jianshu.com/go?to=https%3A%2F%2Ferdong.site%2Flinux%2Fsystem%2Fcomputer-unit-conversion.html)
* [https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu](https://links.jianshu.com/go?to=https%3A%2F%2Fkubernetes.io%2Fdocs%2Fconcepts%2Fconfiguration%2Fmanage-compute-resources-container%2F%23meaning-of-cpu)
* [https://access.redhat.com/documentation/zh-cn/red\_hat\_enterprise\_linux/6/html/resource\_management\_guide/sec-memory](https://links.jianshu.com/go?to=https%3A%2F%2Faccess.redhat.com%2Fdocumentation%2Fzh-cn%2Fred_hat_enterprise_linux%2F6%2Fhtml%2Fresource_management_guide%2Fsec-memory)
* [https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.kernel.org%2Fdoc%2FDocumentation%2Fcgroup-v1%2Fmemory.txt)
* [https://www.cnblogs.com/liuhongru/p/11215447.html](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.cnblogs.com%2Fliuhongru%2Fp%2F11215447.html)
* [https://github.com/moby/moby/issues/10824](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fmoby%2Fmoby%2Fissues%2F10824)
* [https://github.com/docker/cli/pull/80](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fdocker%2Fcli%2Fpull%2F80)

\
\
作者：二二向箔\
链接：https://www.jianshu.com/p/64230e3b6e6c\
来源：简书\
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
