共享集群混部导致 CPU 抢占 20%,你会如何隔离并量化影响

解读

“共享集群混部”指同一物理机/宿主机上同时部署了多条业务线(如在线、离线、大数据、AI 训练)或不同优先级的容器/虚拟机。CPU 抢占 20% 并不是简单的“整体利用率降 20%”,而是指高优业务被低优邻居挤占,导致关键指标(P99 延迟、吞吐、错误率)劣化。面试官想验证三件事:

  1. 能否用可重复实验把“邻居噪音”隔离出来;
  2. 能否把 20% 抢占翻译成业务可感知的数字(RT 上涨多少、吞吐掉多少、SLA 破多少);
  3. 能否给出工程化方案,让结果可落地到 K8s/YARN/自研调度器。

知识点

  1. CPU 调度类(cgroup v1 cpu.shares/cpu.cfs_quota_us、v2 cpu.weight/cpu.max)与内核调度器原理;
  2. 干扰源分类:时钟抢占、L3 Cache 挤占、内存带宽挤占、上下文切换、超线程逻辑核争抢;
  3. 可观测体系:perf、BPF、schedtrace、sar、mpstat、taskclock、cache-miss、IPC、runqlat、runqocc;
  4. 业务指标到资源指标的映射:Little’s Law、Utilization Law、排队论 M/M/1;
  5. 隔离手段:绑核(taskset、cpuset)、调度类(SCHED_FIFO/RR、DEADLINE)、RDT(CAT/MBA)、超线程关闭、NUMA 亲和、K8s 的 static/numa-aware 策略、YARN 的 Node-label + cgroups;
  6. 量化方法:单变量轮替、A/B 对照、置信区间、双样本 t 检验、效应量 Cohen’s d、线性回归归因;
  7. 生产灰度:调度器影子模式、chaos 注入、金丝雀发布、SLO 熔断。

答案

回答采用“五步法”,每一步都给出可落地的命令或脚本,确保面试官可以“听得懂、抄得走、能复现”。

第一步:建立“安静”基线

  1. 选一台同型号裸金属,关闭超线程、Turbo、节能模式,固定 cpufreq 到基频;
  2. 用 cpuset 把高优业务绑到物理核 0-7,其余核留空;
  3. 跑 10 分钟峰值流量,采集:P99 RT、QPS、CPU 利用率、IPC、cache-miss、runqlat(>10ms 次数);
  4. 重复 3 次,取均值 μ₀ 和标准差 σ₀,作为“无干扰基线”。

第二步:引入“干扰模型”——模拟 20% 抢占

  1. 在剩余核启动 stress-ng:
    stress-ng –cpu 4 –cpu-method matrixprod –cpu-load 20 –timeout 600s
    保证只占 20% 单核时间片,但随机调度到任意核,制造真实抢占;
  2. 同时启动内存带宽干扰:
    mbw 128 –m 2000 –t 600
    控制内存带宽占用在读 5 GB/s 左右,模拟大数据 MapReduce 心跳;
  3. 记录同一高优业务的指标,得到 μ₁。

第三步:隔离变量——定位真凶

  1. 若 μ₁ 与 μ₀ 差异显著(t 检验 p<0.05),则继续;否则提高负载再测;
  2. 用 perf stat -a -e cache-misses,cycles,instructions 观察 IPC 下降比例;
  3. 用 bpftrace 脚本 runqlat.bt 统计高优线程排队延迟,若 95pct 从 2ms 涨到 8ms,说明调度延迟是主因;
  4. 用 pqos(Intel RDT)查看 L3 OCCUPANCY,若高优从 1.2 MB 被挤到 0.3 MB,则 Cache 挤占是次因;
  5. 把干扰源逐项关闭,做“单因子轮替”,用线性回归量化:
    ΔRT = 0.8×runqlat + 0.2×cache_miss,R²=0.93,说明调度延迟贡献 80%。

第四步:量化业务损失

  1. 用 Utilization Law:
    基线 CPU 利用 60%,QPS₀=10000,RT₀=60ms;
    抢占后 CPU 利用仍 60%,但 QPS₁=8500,RT₁=72ms;
    计算“有效容量”损失 = (10000-8500)/10000 = 15%,即 20% CPU 抢占导致 15% 容量蒸发;
  2. 换算到 SLA:若 SLA 为 RT<80ms@P99,基线 P99=68ms,抢占后 P99=84ms,破线 4ms,违约率 0.3%→2.1%,全年违约分钟数 = 525600×(2.1%-0.3%) ≈ 9451 分钟,直接关联到年度可用性 99.9%→99.8%,触及绩效红线。

第五步:工程化隔离与验证

  1. 调度层:K8s 启用 static + cpuset,把高优 Pod 绑到专属物理核,低优 Pod 用 burstable 且 cpu.max=quota/period=20000/100000(20% 上限);
  2. Cache 层:pqos -e "llc:1=0x00f0;" 把高优分配到 COS1,保留 4 路 L3;低优 COS2 仅得 2 路;
  3. 内存带宽:pqos -e "mba:2=30;" 限制低优最大 30% 内存带宽;
  4. 灰度发布:用 Argo Rollout 做 10% 金丝雀,监控 P99 RT 回退到 70ms 以内即全量;
  5. 回归测试:重跑第二步脚本,验证 ΔRT 从 12ms 降到 2ms,容量损失从 15% 降到 3%,达到“可接受噪音窗口”。

拓展思考

  1. 如果抢占发生在云厂商超卖场景,宿主机不可控,如何在不绑核的前提下用“无侵入采样”量化?
    答:利用 eBPF 的 cpu_cycles 事件与业务 trace_id 联动,做“慢请求火焰图”聚类,再用概率图模型(Bayesian Change Point)推断邻居噪音出现时刻,从而把 RT 抖动拆成“自身毛刺”与“邻居抢占”两部分。

  2. 当 20% 抢占不是 CPU 而是内存带宽,且触发 NUMA 跨节点,如何量化?
    答:用 perf c2c 查看远端 NUMA 访问比例,把跨节点延迟换算到指令数,再用 Little’s Law 推导 QPS 损失;隔离手段包括 numactl –membind、K8s TopologyManager 的 single-numa-node 策略。

  3. 长期看,如何把“抢占成本”量化成预算,反向驱动调度器打分?
    答:建立“干扰价格”模型,把每 1% CPU 抢占映射到 X 元运营成本(违约赔偿 + 扩容费用),调度器在打分函数里增加“干扰价格”维度,实现经济视角的最优调度。