当我们在 Kubernetes 集群中排查问题或监控资源使用情况时,kubectl top
命令是一个非常常用的工具。它能快速地展示 Node 或 Pod 的当前 CPU 和内存使用情况。例如,运行的命令:
kubectl top po
输出类似这样:
app-api-686799f58d-bgfrl 52m 1991Mi
app-api-686799f58d-hcqzc 52m 2015Mi
app-api-686799f58d-p2xbc 49m 1986Mi
这里的 52m
和 49m
代表的就是 Pod 的 CPU 使用量。那么,这些数字具体代表什么?它们和我们日常理解的 CPU 时钟频率(GHz)、双核、四核等概念有什么关系呢?
1. kubectl top
显示了什么?
kubectl top
显示的是 Kubernetes 资源(Node 或 Pod)在过去一个短暂周期内的平均资源使用量。这里的资源主要指 CPU 和 内存。
对于 CPU,它显示的是 Pod 或 Node 消耗的计算时间。
2. 揭秘 ‘m’ 单位:毫核 (Millicores)
kubectl top
显示的 CPU 使用量使用的单位是 m
,它代表 毫核 (millicores)。
在 Kubernetes 中,1 个完整的 CPU 核心 被定义为 1000m。
所以:
1000m
= 1 个完整的 CPU 核心500m
= 0.5 个 CPU 核心(即半个核心)52m
= 0.052 个 CPU 核心5m
= 0.005 个 CPU 核心
Kubernetes 之所以引入毫核这个单位,是为了允许对 CPU 资源进行更细粒度的分配和度量。应用程序很少需要独占一个完整的核心,使用毫核可以更有效地利用硬件资源。
3. CPU 指标是如何测量的?(幕后原理)
kubectl top
显示的数据并不是凭空出现的,它背后有一套数据采集和汇聚的机制:
- 底层 (cgroups): 在每个 Linux 节点上,容器运行时(如 Containerd, CRI-O 等)利用操作系统的 Control Groups (cgroups) 功能来隔离和监控每个容器的资源使用。Cgroups 会跟踪每个进程使用了多少总的 CPU 时间(例如,CPU 时钟周期数或纳秒)。这是一个不断累积的计数器。
- Kubelet 采集: 运行在每个节点上的 Kubelet 组件会定期(比如每隔几秒钟)从 cgroups 读取每个容器当前的累积 CPU 使用时间。
- 计算速率: Kubelet 拿到当前的累积时间后,会与上一次采集时记录的累积时间进行比较。通过计算两次采集之间的 CPU 时间差 除以 时间间隔,就可以得出这段时间内的平均 CPU 使用速率(例如,每秒消耗多少 CPU 时间)。
- 标准化与转换为毫核: Kubelet 将这个速率标准化为相对于一个完整 CPU 核心的使用比例,并乘以 1000 转换为毫核单位。例如,如果在一个 10 秒的间隔内,容器使用了相当于 0.5 秒的 CPU 时间,那么速率就是 0.5秒 / 10秒 = 0.05 (即 5% 的核心使用率),转换为毫核就是 0.05 * 1000 = 50m。
- Metrics Server 汇聚: Kubernetes 集群通常会部署一个 Metrics Server 组件。Metrics Server 会定期(通常每 10-30 秒)从集群中所有节点的 Kubelet 拉取这些计算好的平均 CPU 和内存使用数据。
kubectl top
查询: 当我们运行kubectl top
命令时,它实际上是向 Kubernetes API Server 发起请求,API Server 再从 Metrics Server 获取最新的、针对我们查询的 Pod 或 Node 的指标数据并展示出来。
所以,我们在 kubectl top
中看到的 52m
,代表的是在 Metrics Server 最近一次从 Kubelet 拉取数据前的那个采集周期内,该 Pod 平均消耗了 52 毫核的 CPU 计算能力。这是一个平均值,而不是瞬时值。
4. Kubernetes CPU 与传统 CPU 的关联与区别
现在,让我们把 Kubernetes 的毫核概念与传统的 CPU 时钟频率和核心数关联起来。
-
关联:1000m 对应一个核心
- 最直接的关联是数量关系:1000m 在概念上代表了宿主机上的一个物理 CPU 核心或一个虚拟 CPU 核心(取决于我们的宿主机是物理机还是虚拟机)**所能提供的计算能力。
- 如果我们的 Node 上有一个物理 CPU,它是四核的,那么理论上这个 Node 总共可以向 Kubernetes 提供大约 4 * 1000m = 4000m 的 CPU 容量(实际可用容量可能会略低,因为操作系统和 Kubelet 本身也需要消耗少量 CPU)。
- 我们看到的 Pod 使用
52m
,意味着它平均使用了大约是 Node 上单个核心计算能力的 5.2%。
-
区别:Kubernetes 抽象掉了时钟频率 (GHz)
- 这是最关键的区别点。在传统的硬件概念中,CPU 的性能很大程度上取决于其时钟频率 (GHz)。一个 3GHz 的核心通常比一个 2GHz 的核心计算能力更强。
- 但是,在 Kubernetes 中,为了实现统一的资源管理和跨机器的调度,Kubernetes 抽象掉了不同核心之间的性能差异(即时钟频率)。 对 Kubernetes 而言,Node A 上的 1000m 和 Node B 上的 1000m 被视为等量的计算能力,无论 Node A 的核心是 2GHz 还是 Node B 的核心是 3GHz。
- 这意味着
kubectl top
显示的52m
是一个相对值,代表使用了相当于标准化的 0.052 个核心的计算能力。这个值本身不直接告诉我们 Pod 在物理 CPU 上占用了多少 GHz 的处理能力,而是告诉我们它占用了多少核心份额。
为什么要进行这种抽象?
想象一个集群中有不同配置的服务器:有些是老旧的低频 CPU,有些是全新的高频 CPU。如果 Kubernetes 直接按 GHz 或原始 CPU 时间来分配和度量,调度器会非常复杂,也很难保证 Pod 在不同 Node 上获得一致的资源份额。通过将所有 CPU 资源标准化为“核心份额”(以毫核为单位),Kubernetes 提供了一个统一的资源视图,使得调度器可以更公平、更有效地将 Pod 分配到集群中的任何可用 Node 上,而不用关心底层 CPU 的具体型号和频率。
5. 与 CPU Requests 和 Limits 的关系
在 Pod 的配置中,我们可以指定 CPU 的 requests
和 limits
:
requests
: Pod 启动时请求的 CPU 资源量,调度器使用这个值来决定将 Pod 放在哪个 Node 上。limits
: Pod 可以使用的最大 CPU 资源量,用于限制 Pod 不会过度消耗 CPU 导致影响其他 Pod。
kubectl top
显示的 CPU 指标 (52m
等) 是 Pod 的实际使用量。这个使用量:
- 通常会高于或等于其 CPU
requests
(如果 Node 资源充足)。 - 不应超过其 CPU
limits
(如果设置了 limits)。如果一个 Pod 的实际使用量持续接近或超过了其 limits,可能会导致 Pod 被限流 (throttling),从而影响其性能。
结论
kubectl top
命令中的 CPU 指标(如 52m
)是一个基于毫核 (millicores) 的平均使用量。它代表了 Pod 在过去一个短暂周期内平均消耗了多少标准化后的 CPU 核心份额。
它与传统 CPU 概念的关系是:
- 关联: 1000m 概念上等于宿主机上的一个物理或虚拟 CPU 核心的计算能力。我们的 Pod 使用
52m
意味着它使用了相当于该 Node 上单个核心大约 5.2% 的计算能力。 - 区别: Kubernetes 为了实现统一资源管理和调度,抽象掉了底层 CPU 的时钟频率差异。我们看到的
m
值是一个标准化的份额,不直接反映具体的 GHz 数值。
理解这个抽象层对于有效地在 Kubernetes 中进行资源规划、监控和故障排查至关重要。它帮助我们将关注点从具体的硬件型号转移到统一的资源单元上,从而更好地管理分布式应用。