常见的一些问题:
kubectl top 是基础命令,但是需要部署配套的组件才能获取到监控值
kubectl top node:查看node的使用情况
kubectl top pod: 查看 pod 的使用情况
不指定pod 名称,则显示命名空间下所有 pod,–containers可以显示 pod 内所有的container
指标含义:
kubectl top、 k8s dashboard 以及 HPA 等调度组件使用的数据是一样,数据链路如下:
使用 heapster 时:apiserver 会直接将 metric 请求通过 proxy 的方式转发给集群内的 hepaster 服务。
而使用 metrics-server 时:apiserver 是通过 /apis/metrics.k8s.io/ 的地址访问 metric。
heapster 使用的是 proxy 转发,而 metric-server 和普通 pod都是使用 api/xx 的资源接口,heapster采用的这种 proxy 方式是有问题的
于是官方从 1.8 版本开始逐步废弃 heapster,并提出了上边 Metric api 的概念,而 metrics-server 就是这种概念下官方的一种实现,用于从 kubelet获取指标,替换掉之前的 heapster
有了 metrics-server 组件,采集到了需要的数据,也暴露了接口,但走到这一步和 heapster 其实没有区别,最关键的一步就是如何将打到 apiserver的 /apis/metrics.k8s.io 请求转发给 metrics-server 组件?
解决方案就是:kube-aggregator。kube-aggregator 是对 apiserver 的有力扩展,它允许 k8s 的开发人员编写一个自己的服务,并把这个服务注册到 k8s 的 api 里面,即扩展 API,metric-server 其实在 1.7版本就已经完成了,只是在等 kube-aggregator 的出现。kube-aggregator 是 apiserver 中的实现,有些 k8s 版本默认没开启,你可以加上这些配置来开启,他的核心功能是动态注册、发现汇总、安全代理。
在提出 metric api 的概念时,官方也提出了新的监控体系,监控资源被分为了2种:
核心指标只包含 node 和 pod 的 cpu、内存等,一般来说,核心指标作 HPA 已经足够,但如果想根据自定义指标:如请求 qps/5xx 错误数来实现 HPA,就需要使用自定义指标了。目前 Kubernetes 中自定义指标一般由 Prometheus 来提供,再利用 k8s-prometheus-adpater 聚合到 apiserver,实现和核心指标同样的效果。
前面提到,无论是 heapster 还是 metric-server,都只是数据的中转和聚合,两者都是调用的 kubelet 的 api 接口获取的数据,而 kubelet 代码中实际采集指标的是 cadvisor 模块,你可以在 node 节点访问 10255 端口(1.11版本过后是10250端口)获取监控数据:
Kubelet 虽然提供了 metric 接口,但实际监控逻辑由内置的 cAdvisor 模块负责,演变过程如下:
cadvisor 由谷歌开源,使用 Go 开发,cadvisor 不仅可以搜集一台机器上所有运行的容器信息,包括 CPU 使用情况、内存使用情况、网络吞吐量及文件系统使用情况,还提供基础查询界面和 http 接口,方便其他组件进行数据抓取。在K8S 中集成在 Kubelet 里作为默认启动项,k8s 官方标配。
cadvisor的指标解读:cgroup-v1(https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt)
cadvisor 获取指标时实际调用的是 runc/libcontainer 库,而 libcontainer 是对 cgroup 文件 的封装,即 cadvsior 也只是个转发者,它的数据来自于cgroup 文件。
cgroup 文件中的值是监控数据的最终来源,如
/sys/fs/cgroup/memory/docker/[containerId]/memory.usage_in_bytes
/sys/fs/cgroup/memory/docker/[id]/memory.limit_in_bytes
一般情况下,cgroup文件夹下的内容包括CPU、内存、磁盘、网络等信息:
如 memory 下的几个常用的指标含义:
memory.stat 中的信息是最全的:
一般情况下 top 报错有以下几种,可以 kubectl top pod -v=10看到具体的调用日志:
每次启动 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_working_set_bytes 是容器真实使用的内存量,也是 limit限制时的 oom 判断依据。cadvisor 中的 container_memory_usage_bytes 对应 cgroup 中的 memory.usage_in_bytes 文件,但 container_memory_working_set_bytes 并没有具体的文件。
同理,node 的内存使用量也是 container_memory_working_set_bytes。
kubectl top node 得到的cpu和内存值,并不是节点上所有 pod 的总和,不要直接相加。top node 是机器上 cgroup 根目录下的汇总统计。
在机器上直接 top 命令看到的值和 kubectl top node 不能直接对比,因为计算逻辑不同,如内存,大致的对应关系是(前者是机器上 top,后者是 kubectl top):
rss + cache = (in)active_anon + (in)active_file
因此kubectl top pod 和 exec 进入 pod 后看到的 top 不一样
top 命令的差异和上边一致,无法直接对比,同时,就算你对 pod 做了 limit 限制,pod 内的 top 看到的内存和 cpu 总量仍然是机器总量,并不是pod 可分配量
如果你的 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 的数据,用于回溯历史或者发送报警。