3. CPU资源管理:CPU时间片、CFS调度器、CPU Manager策略与NUMA亲和性
CPU是容器最核心的竞争资源之一。Kubernetes通过Linux内核的CFS(Completely Fair Scheduler)为容器分配CPU时间片,并通过kubelet的CPU Manager策略控制物理核心的绑定行为。本章深入剖析CPU时间片分配机制、CFS调度器工作原理、CPU Manager的none与static策略差异、CPU Pin技术以及NUMA亲和性优化方法。
3.1 CPU时间片与CFS调度器
Linux CFS调度器为每个进程(或cgroup)分配一个权重(weight),权重越高,获得的CPU时间片比例越大。Kubernetes将requests.cpu和limits.cpu映射为CFS的cpu.shares和cpu.cfs_quota_us参数。
| K8s资源字段 | CFS对应参数 | 作用 |
|---|---|---|
requests.cpu |
cpu.shares |
设置容器权重,决定CPU时间片分配比例(非硬限制) |
limits.cpu |
cpu.cfs_quota_us + cpu.cfs_period_us |
设置CPU使用上限(硬限制),超过则限流 |
container_cpu_cfs_throttled_seconds_total指标可判断是否发生限流。
CFS调度周期默认100ms(cpu.cfs_period_us = 100000)。若容器limits=2核,则cpu.cfs_quota_us = 200000,表示每100ms周期内最多获得200ms的CPU时间。若容器实际需要300ms,则100ms被限流,实际只能使用200ms。
limits.cpu设置为略高于实际峰值使用量,避免频繁throttle导致响应抖动。同时可考虑调整cpu.cfs_period_us为更小值(如50000)以降低调度延迟。
3.2 CPU Manager策略:none vs static
kubelet的CPU Manager负责管理容器CPU亲和性绑定策略。通过--cpu-manager-policy参数设置,支持none和static两种策略。
| 策略 | 行为 | 适用场景 | 优缺点 |
|---|---|---|---|
| none | 默认策略,不进行CPU Pin,容器可在所有CPU上自由调度 | 通用负载、批处理、非延迟敏感型应用 | 优点:CPU利用率高,调度灵活;缺点:缓存亲和性差,延迟抖动大 |
| static | 为Guaranteed QoS(requests=limits)的容器分配独占CPU核心 | 延迟敏感型、高频交易、实时处理、DPDK/SPDK应用 | 优点:CPU Pin固定,缓存亲和性好,延迟稳定;缺点:CPU利用率可能降低,资源碎片化 |
启用static策略后,kubelet将CPU分为共享池和独占池。独占池中的CPU核心被分配给Guaranteed Pod后,其他Pod(包括Burstable、BestEffort)无法使用这些核心,只能使用共享池中的CPU。
3.3 CPU Pin与NUMA亲和性
CPU Pin(CPU固定)是指将容器进程绑定到特定物理CPU核心上运行。在NUMA(Non-Uniform Memory Access)架构下,CPU访问本地内存的速度远快于远程内存。若容器跨NUMA节点访问内存,延迟显著增加。
Kubernetes通过Topology Manager(拓扑管理器)协调CPU Manager和Device Manager,实现NUMA亲和性。启用--topology-manager-policy=single-numa-node可强制容器所有资源(CPU、内存、设备)来自同一个NUMA节点。
3.4 CPU Manager static策略配置与验证
启用static策略需要修改kubelet配置,并重启kubelet服务。以下为典型配置步骤:
- 修改kubelet配置:在
/var/lib/kubelet/config.yaml中添加:
cpuManagerPolicy: static
topologyManagerPolicy: single-numa-node
cpuManagerReconcilePeriod: 10s
kubeReserved:
cpu: "1"
memory: 2Gi
systemReserved:
cpu: "500m"
memory: 1Gi
- 重启kubelet:
systemctl restart kubelet
- 验证CPU Pin状态:查看Pod的cgroup CPU亲和性:
# 查看Pod所在节点
kubectl get pod my-pod -o wide
# 进入Pod所在节点,查看cgroup
cat /sys/fs/cgroup/cpuset/kubepods/besteffort/pod<pod-uid>/cpuset.cpus
cpuset.cpus中显示独占的CPU核心编号(如0,2)。若为Burstable或BestEffort,则显示共享池中的CPU核心。
3.5 性能优化实践:CPU Pin + NUMA亲和性
对于高性能计算、实时数据处理、数据库等场景,推荐以下优化组合:
| 优化项 | 配置 | 效果 |
|---|---|---|
| CPU Manager | static |
独占CPU核心,消除上下文切换抖动 |
| Topology Manager | single-numa-node |
保证CPU和内存来自同一NUMA节点 |
| QoS等级 | Guaranteed(requests=limits) | 避免CPU时间片被抢占 |
| CPU requests/limits | 整数值(如2、4、8) | 确保static策略生效 |
| 预留资源 | kubeReserved + systemReserved |
为系统组件保留CPU,避免资源争抢 |
- static策略可能导致CPU利用率下降,因为独占核心在Pod空闲时无法被其他Pod使用。建议结合HPA(水平自动扩缩)和节点自动伸缩来平衡资源利用率。
- 跨NUMA节点部署Pod时,即使使用static策略,若Topology Manager未启用,仍可能发生跨NUMA内存访问,导致性能下降。
- 对于非延迟敏感型应用,建议使用none策略,以获得更高的CPU利用率和调度灵活性。
3.6 监控与调优指标
以下指标可用于评估CPU资源管理效果:
- CFS限流率:
container_cpu_cfs_throttled_seconds_total / container_cpu_cfs_periods_total,反映CPU限流严重程度。 - CPU上下文切换:
container_cpu_cfs_throttled_seconds_total和node_cpu_context_switches_total,高上下文切换表示CPU Pin不足。 - NUMA内存访问延迟:通过
perf stat -e mem_load_retired.local_dram,mem_load_retired.remote_dram测量本地/远程内存访问比例。 - CPU利用率:
container_cpu_usage_seconds_total,结合requests/limits评估资源浪费或不足。