2. 资源模型与度量体系
做资源利用率优化,第一步不是调参,而是把“资源”这件事在 Kubernetes 里说清楚。Kubernetes 并不直接管理物理 CPU 核或内存条,它管理的是一套抽象后的可声明、可调度、可计量的资源模型。只有先理解这套模型,才能理解为什么“节点 CPU 使用率 30%”和“Pod 的 CPU 利用率 30%”可能指向完全不同的结论。
一、Kubernetes 的资源抽象层次
Kubernetes 把资源分成三个层次来理解:节点可分配资源(Allocatable)、容器声明资源(Requests/Limits)、实际使用资源(Usage)。调度器只看 Requests,kubelet 的驱逐逻辑看 Limits 与节点压力,而监控系统看的是 Usage。三者不一致,正是利用率指标容易误读的根源。
节点侧,一个 Node 的容量(Capacity)会被系统组件、kubelet 预留、驱逐阈值逐步扣减,最终得到可分配给 Pod 的 Allocatable。例如一个 8 核 32GiB 的节点,扣除 kube-reserved、system-reserved 和 eviction 阈值后,Allocatable 可能只有 7.6 核 29GiB。因此节点利用率的分母应当是 Allocatable,而不是 Capacity。
二、CPU 的计量单位与语义
CPU 在 Kubernetes 中是可压缩资源,计量单位是“核”,写法上 1 等于 1000m(毫核)。500m 表示 0.5 核。CPU 的 Requests 决定调度权重和 cgroup 的 cpu.shares,Limits 决定 cgroup 的 cpu.cfs_quota_us,也就是 CPU 上限。超过 Limits 时 CPU 会被节流(throttling),而不是被杀掉。
这里有一个关键点:CPU 利用率的分母选择会显著改变结论。若用 Requests 作分母,得到的是“配额使用率”,反映申请是否虚高;若用节点 Allocatable 作分母,得到的是“节点真实占用率”,反映整体水位。工程上通常两个都要看。
三、内存的计量单位与语义
内存是不可压缩资源,单位是字节,常用 Mi、Gi 表示。256Mi 即 256×1024×1024 字节。内存超过 Limits 会触发 OOMKill,容器被强制终止;节点内存紧张时,kubelet 会按 QoS 等级驱逐 Pod。QoS 由 Requests 与 Limits 的关系决定:两者相等且都设置的是 Guaranteed,只设 Requests 的是 Burstable,都不设的是 BestEffort。
内存利用率同样要区分口径:容器工作集(working set)与 RSS 不同,缓存(page cache)是否计入也会影响结果。通常用 container_memory_working_set_bytes 作为内存使用量,它更接近“真实占用”。
四、存储、网络与 GPU 的抽象
存储分为临时存储(ephemeral-storage)和持久卷(PV)。临时存储以字节计量,用于限制容器可写的本地磁盘量,超限会被驱逐。PV 通过 PVC 声明容量,单位同样是字节,但它是“容量配额”而非“实时用量”,利用率需要结合文件系统实际使用量计算。
网络在 Kubernetes 中没有 Requests/Limits 形式的资源声明,它通过 CNI 插件、带宽插件或 eBPF 观测来度量。常用指标是带宽(bps)、包速率(pps)和连接数。网络利用率通常以网卡线速或节点带宽上限为分母。
GPU 是扩展资源,以整数计量,nvidia.com/gpu: 1 表示申请一张 GPU。GPU 不可超卖,Requests 必须等于 Limits。GPU 利用率不能只看“是否被占用”,而要看 SM 利用率、显存占用、显存带宽等维度,通常由 DCGM 等工具采集。
五、利用率指标的定义与陷阱
利用率本质是一个比值:利用率 = 实际使用量 ÷ 可用总量。难点在于分子和分母都可能有多种口径。以 CPU 为例,分子可以是容器 CPU 使用秒数速率,分母可以是 Requests、Limits 或 Allocatable;以内存为例,分子可以是 working set、RSS 或含缓存的总量。指标定义不统一,优化就会失去基准。
实践中建议固定一套口径并写入监控规范。例如:CPU 配额使用率 = rate(container_cpu_usage_seconds_total[5m]) ÷ kube_pod_container_resource_requests{resource="cpu"};内存工作集使用率 = container_memory_working_set_bytes ÷ kube_pod_container_resource_limits{resource="memory"}。分母为 0 或缺失时要显式排除,避免出现无穷大或误导性尖峰。
六、可参考的度量字段清单
| 资源 | 计量单位 | 关键指标 | 超限行为 |
|---|---|---|---|
| CPU | 核 / 毫核(m) | usage_seconds_total、throttled_periods | 节流,不终止 |
| 内存 | 字节(Mi/Gi) | working_set_bytes、rss | OOMKill / 驱逐 |
| 临时存储 | 字节 | ephemeral_storage_used | 驱逐 Pod |
| 持久卷 | 字节 | kubelet_volume_stats_used_bytes | 写入失败 |
| 网络 | bps / pps | container_network_receive_bytes | 无硬限制,拥塞 |
| GPU | 整数(张) | DCGM_FI_DEV_GPU_UTIL、显存占用 | 调度失败 |
把这张表当作度量体系的“字典”:任何一次利用率分析,先确认用的是哪一行、哪个分母、哪个采集源。资源模型清晰之后,后续的 Requests/Limits 调优、HPA 阈值设定、节点扩容判断才有共同语言。