Kubernetes 资源监控

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、前言

常见的一些问题

  • kubectl top 为什么会报错
  • kubectl top node 怎么计算和节点上直接 top 有什么区别
  • kubectl top pod 怎么计算包含 pause 吗
  • kubectl top pod 和exec 进入 pod 后看到的 top 不一样
  • kubectl top pod 和 docker stats得到的值为什么不同

二、使用

kubectl top 是基础命令但是需要部署配套的组件才能获取到监控值

  • 1.8以下部署 heapter
  • 1.8以上部署 metric-server

kubectl top node查看node的使用情况
在这里插入图片描述
kubectl top pod: 查看 pod 的使用情况
在这里插入图片描述
不指定pod 名称则显示命名空间下所有 pod–containers可以显示 pod 内所有的container
在这里插入图片描述
指标含义

  • 和 k8s中 的 request、limit 一致CPU单位100m=0.1 内存单位1Mi=1024Ki
  • pod 的内存值是其实际使用量也是做 limit 限制时判断 oom 的依据。pod的使用量等于其所有业务容器的总和不包括 pause 容器值等于 cadvisr中的 container_memory_working_set_bytes 指标
  • node 的值并不等于该 node 上所有 pod 值的总和也不等于直接在机器上运行 top 或 free 看到的值

三、实现原理

3.1 数据链路

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

3.2 kube-aggregator

有了 metrics-server 组件采集到了需要的数据也暴露了接口但走到这一步和 heapster 其实没有区别最关键的一步就是如何将打到 apiserver的 /apis/metrics.k8s.io 请求转发给 metrics-server 组件

解决方案就是kube-aggregator。kube-aggregator 是对 apiserver 的有力扩展它允许 k8s 的开发人员编写一个自己的服务并把这个服务注册到 k8s 的 api 里面即扩展 APImetric-server 其实在 1.7版本就已经完成了只是在等 kube-aggregator 的出现。kube-aggregator 是 apiserver 中的实现有些 k8s 版本默认没开启你可以加上这些配置来开启他的核心功能是动态注册、发现汇总、安全代理。
在这里插入图片描述

3.3 监控体系 ❤️

在提出 metric api 的概念时官方也提出了新的监控体系监控资源被分为了2种

  • Core metrics(核心指标)从 Kubelet、cAdvisor 等获取度量数据再由metrics-server 提供给 Dashboard、HPA 控制器等使用。
  • Custom Metrics(自定义指标)由 Prometheus Adapter 提供 API custom.metrics.k8s.io由此可支持任意Prometheus采集到的指标。

在这里插入图片描述
核心指标只包含 node 和 pod 的 cpu、内存等一般来说核心指标作 HPA 已经足够但如果想根据自定义指标如请求 qps/5xx 错误数来实现 HPA就需要使用自定义指标了。目前 Kubernetes 中自定义指标一般由 Prometheus 来提供再利用 k8s-prometheus-adpater 聚合到 apiserver实现和核心指标同样的效果。

3.4 kubelet

前面提到无论是 heapster 还是 metric-server都只是数据的中转和聚合两者都是调用的 kubelet 的 api 接口获取的数据而 kubelet 代码中实际采集指标的是 cadvisor 模块你可以在 node 节点访问 10255 端口1.11版本过后是10250端口获取监控数据

  • Kubelet Summary metrics: 127.0.0.1:10255/metrics暴露 node、pod 汇总数据
  • Cadvisor metrics: 127.0.0.1:10255/metrics/cadvisor暴露 container 维度数据

Kubelet 虽然提供了 metric 接口但实际监控逻辑由内置的 cAdvisor 模块负责演变过程如下

  • 从k8s 1.6 开始kubernetes 将 cAdvisor 开始集成在kubelet中不需要单独配置
  • 从k8s 1.7 开始Kubelet metrics API 不再包含 cadvisor metrics而是提供了一个独立的 API 接口来做汇总
  • 从 k8s 1.12 开始cadvisor 监听的端口在k8s中被删除所有监控数据统一由 Kubelet 的 API 提供

3.5 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 文件。

3.6 cgroup

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

  • mem usage 的值来自于
    /sys/fs/cgroup/memory/docker/[containerId]/memory.usage_in_bytes
  • 如果没限制内存Limit=machine_mem否则来自于
    /sys/fs/cgroup/memory/docker/[id]/memory.limit_in_bytes
  • 内存使用率=memory.usage_in_bytes/memory.limit_in_bytes

一般情况下cgroup文件夹下的内容包括CPU、内存、磁盘、网络等信息
在这里插入图片描述
如 memory 下的几个常用的指标含义
在这里插入图片描述
memory.stat 中的信息是最全的
在这里插入图片描述

四、问题

一般情况下 top 报错有以下几种可以 kubectl top pod -v=10看到具体的调用日志

  • 没有部署 heapster 或者 metric-server或者 pod 运行异常可以排查对应 pod 日志
  • 要看的 pod 刚刚建出来还没来得及采集指标报 not found 错误默认 1 分钟
  • 以上两种都不是可以检查下 kubelet 的 10255 端口是否开放默认情况下会使用这个只读端口获取指标也可以在 heapster 或 metric-server 的配置中增加证书换成 10250 认证端口

4.2 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 并没有具体的文件。

同理node 的内存使用量也是 container_memory_working_set_bytes。

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

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 可分配量

4.4 kubectl top pod 和 docker stats得到的值为什么不同

如果你的 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 的数据用于回溯历史或者发送报警。

  • 虽然 kubectl top help 中显示支持 Storage但直到 1.16 版本仍然不支持
  • 1.13 之前需要 heapster1.13 以后需要 metric-server这部分 kubectl top help 的输出 有误里面只提到了heapster
  • k8s dashboard 中的监控图默认使用的是 heapster切换为 metric-server后数据会异常需要多部署一个metric-server-scraper 的 pod 来做接口转换具体参考 prhttps://github.com/kubernetes/dashboard/pull/3504
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: k8s