用实测数据读 cAdvisor 与 node exporter
目标
用从运行本站的 7 节点集群中采集的实测指标来解读 cAdvisor 和 node exporter 的数字。学完之后,你看到容器的 CPU、内存和 throttle 指标时,就能有依据地回答“这算多吗”。
为什么重要
即使完全掌握了 PromQL 语法,不知道指标数的是什么,也无法解读数字。累积计数器的大小总是活得越久的容器越大,working set 与 usage 数的是不同的东西,CPU 限制不是由 cAdvisor 而是由 kube-state-metrics 告诉你的。不懂这三点,仪表板虽然漂亮,判断却每次都会出错。这里使用的数据来自真实集群,所以值并不整齐——throttle 是 0.19%,没有设置限制的容器则根本没有指标。现场就是这样。
关于数据
- 时间窗口是固定的 3 小时。用
lab-realdata确认。 - 用
promq-at "<PromQL>"提交查询。这个辅助程序会以窗口内的一个固定时刻发起查询。如果直接使用promq,查询的是当前时刻,结果会为空。 - exporter 暴露格式的原始内容在
/opt/lab/realdata/expo/中。 - 来源、采集时间和处理过的内容写在
/opt/lab/realdata/README.md中。内部 IP 和主机名没有抹去——这是本站的真实集群。
步骤
- 用
lab-realdata确认时间窗口,并在/root/pca-exporters/01-count.promql中写出一个查询,统计monitoring命名空间中输出container_cpu_usage_seconds_total的 Pod 有多少个(要数的是 Pod 数,而不是序列数)。 - 在
/root/pca-exporters/02-cpu-rate.promql中写出一个查询,求出monitoring中的prometheus容器现在用了几个核。 - 在
/root/pca-exporters/03-throttle.promql中写出一个查询,求 CFS throttle 比例(throttled_periods / periods,窗口[1h])的最大值,并在/root/pca-exporters/03-throttle.txt中用一行写下该比例最高的容器名称。 - 在
/root/pca-exporters/04-inactive.promql中写出一个查询,求monitoring的grafana容器上container_memory_usage_bytes与container_memory_working_set_bytes的差值,并在/root/pca-exporters/04-inactive.txt中写下给出与该差值相同的值的指标名称。 - 从
id标签中读出ai命名空间tts容器的 QoS 类别,并在/root/pca-exporters/05-qos.txt中用一行写下。 - 找出
/opt/lab/realdata/expo/cadvisor-nuc1.txt中有、但 Prometheus 中没有的指标名称,至少三个,在/root/pca-exporters/06-dropped.txt中每行写一个。 - 在
/root/pca-exporters/07-limit-join.promql中写出一个查询,求ai命名空间中相对于 CPU 限制的使用率的最高值。 - 在
/root/pca-exporters/08-node-cpu.promql中写出一个查询,求192.168.219.120:9100节点的 CPU 使用率(0–1)。 - 在
/root/pca-exporters/09-mem-available.promql中写出一个查询,求同一节点的MemAvailable与MemFree的差值。
参考
- 像
promq-at "count(up)"这样,把查询放在引号里。写在文件里的查询,可以用promq-at "$(cat <파일>)"(占位符为文件名)提交。 - 常见错误 1:结果为空时,应怀疑的不是查询而是时刻。
promq按当前时刻查询,而实测数据只存在于过去的固定窗口中。 - 常见错误 2:直接对标签集合不同的两个指标做除法或减法,结果会为空。用
on(...)对齐,或者用相同的标签缩小范围。
确认已载入的实测数据并统计 Pod 数量
lab-realdata 会告诉你可以查询的时间窗口。请用 promq-at 提交查询——用当前时刻提交会落在窗口之外,得到空结果。直接使用 count() 得到的是序列数,也就是容器数。一个 Pod 里可能有多个容器,所以要先按 pod 分组再计数,才是 Pod 数。
测量累积计数器的斜率
container_cpu_usage_seconds_total 是容器诞生以来用掉的 CPU 秒数的累加值。现在用了几个核,要用 rate 测量斜率才能得出。只要在数据窗口内,范围窗口从 [5m] 到 [30m] 任选都可以。不要看整个命名空间,而是收窄到 prometheus 容器这一个。
用 throttle 比例判断是否超出限制
throttled_periods 是个数,光看这个值无法判断严重与否。请除以同一窗口的 periods 得出比例。最高的容器用 topk(1, ...) 找出,再读取结果中的 container 标签。没有设置限制的容器根本没有这个指标。
确认 usage 与 working set 的差值是什么
把两个指标用相同的标签收窄后相减即可。标签集合不同,相减的结果就会为空。另有一个指标给出的值与这个差值完全相同——请用 promq-at 浏览 grafana 容器中以 container_memory_ 开头的指标。
从 cgroup 路径读出 QoS 类别
container_cpu_usage_seconds_total 的 id 标签就是原样的 cgroup 路径。请找出 kubepods-besteffort、kubepods-burstable 这些路径段。Guaranteed Pod 则完全没有这一段。看 ai 命名空间的 tts 容器即可。
找出原始输出中有、Prometheus 中没有的指标
/opt/lab/realdata/expo/cadvisor-nuc1.txt 是 kubelet 实际输出的原始内容。请把其中的指标名称用 promq-at 逐个查询。结果为空的,就是被技术栈的 metric_relabel 丢弃的指标。找出至少三个并写下来。
与 kube-state-metrics 拼接,求出相对于限制的使用率
限制不在 cAdvisor 一侧,要从 kube_pod_container_resource_limits 获取。两个指标的标签集合不同,直接相除结果会为空。请把两边都用 sum by (pod,container) 缩减到相同的标签,或者用 on(pod,container) 对齐。别忘了用 resource="cpu" 缩小范围——混入内存限制,值就没有意义了。
从按模式分类的累积时间求出节点 CPU 使用率
node_cpu_seconds_total 是每个核心 × 每个模式一条序列。把 idle 模式的 rate 按核心数取平均,再用 1 去减,就是 0–1 之间的使用率。用 sum 的话,结果会按核心数放大。节点是 192.168.219.120:9100。
测量 MemFree 与 MemAvailable 的差值
把两个指标用相同的 instance 收窄后相减即可。这个差值就是“现在被缓存占用、但需要时可以让出来的内存”。节点与上一步相同,是 192.168.219.120:9100。