kubectl top 能够很方便地查看node、pod的实时资源使用状况:如CPU、内存。这篇文章会介绍其数据链路和实现原理,同时借kubectl top 阐述 k8s 中的监控体系,窥一斑而知全豹。最后会解释常见的一些问题:html
如下命令的运行环境为:node
kubectl top 是基础命令,可是须要部署配套的组件才能获取到监控值linux
kubectl top node: 查看node的使用状况git
kubectl top pod: 查看 pod 的使用状况github
不指定pod 名称,则显示命名空间下全部 pod,--containers能够显示 pod 内全部的containerdocker
指标含义:api
kubectl top 、 k8s dashboard 以及 HPA 等调度组件使用的数据是同样,数据链路以下:缓存
使用 heapster 时:apiserver 会直接将metric请求经过 proxy 的方式转发给集群内的 hepaster 服务。安全
而使用 metrics-server 时:apiserver是经过/apis/metrics.k8s.io/的地址访问metric网络
这里能够对比下kubect get pod时的日志:
能够发现,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-server注册 pod 和 node 时:
在提出 metric api 的概念时,官方页提出了新的监控体系,监控资源被分为了2种:
核心指标只包含node和pod的cpu、内存等,通常来讲,核心指标做HPA已经足够,但若是想根据自定义指标:如请求qps/5xx错误数来实现HPA,就须要使用自定义指标了。
目前Kubernetes中自定义指标通常由Prometheus来提供,再利用k8s-prometheus-adpater聚合到apiserver,实现和核心指标(metric-server)一样的效果。
前面提到,不管是 heapster仍是 metric-server,都只是数据的中转和聚合,二者都是调用的 kubelet 的 api 接口获取的数据,而 kubelet 代码中实际采集指标的是 cadvisor 模块,你能够在 node 节点访问 10255 端口 (read-only-port)获取监控数据:
示例,容器的内存使用量:
kubelet虽然提供了 metric 接口,但实际监控逻辑由内置的cAdvisor模块负责,演变过程以下:
到这里为止,k8s范围内的监控体系就结束了,若是你想继续了解cadvisor和 cgroup 的内容,能够向下阅读
cadvisor由谷歌开源,使用Go开发,项目地址也是google/cadvisor,cadvisor不只能够搜集一台机器上全部运行的容器信息,包括CPU使用状况、内存使用状况、网络吞吐量及文件系统使用状况,还提供基础查询界面和http接口,方便其余组件进行数据抓取。在K8S中集成在Kubelet里做为默认启动项,k8s官方标配。
cadvisor 拿到的数据结构示例:
核心逻辑:
经过new出来的memoryStorage以及sysfs实例,建立一个manager实例,manager的interface中定义了许多用于获取容器和machine信息的函数
cadvisor的指标解读:cgroup-v1
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中的信息是最全的:
原理到这里结束,这里解释下最开始的kubectl top 的几个问题:
通常状况下 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并无具体的文件,他的计算逻辑在 cadvisor 的代码中,以下:
同理,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
top命令的差别和上边 一致,没法直接对比,同时,就算你对 pod 作了limit 限制,pod 内的 top 看到的内存和 cpu总量仍然是机器总量,并非pod 可分配量
docker stats dockerID 能够看到容器当前的使用量:
若是你的 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的内容能够看容器监控系列
其余补充: