Request和Limit配置为什么总出问题?
管理过Kubernetes集群的人大概率遇到过这两类报警:Pod被OOMKill,或者明明CPU使用率只有30%却严重Throttling。根因往往指向同一个地方——Request/Limit配置不合理。
Kubernetes的资源模型设计初衷是好的:Request保证最低分配,Limit防止资源超用。但在实际业务场景中,这两组值的设定经常拍脑袋决定,要么”所有Pod统一1C2G”,要么直接照搬JVM堆大小设置,结果就是集群一边资源碎片化严重,一边Pod频繁被驱逐。
CPU Throttling的隐蔽陷阱
Linux CFS调度器对CPU Limit的实现方式是:以100ms为周期,按Limit值计算允许运行的时间片。比如Limit=1的Pod在8核节点上,每个100ms周期只能运行12.5ms。如果Pod在12.5ms内突发用完了时间片,剩余87.5ms都会被Throttle,即使此时节点CPU完全空闲。
这个问题在Java应用上尤为严重。JVM的GC是突发性CPU消费者——一次Young GC可能只持续几毫秒,但需要的CPU峰值远超平均值。如果CPU Limit设得太低,GC被Throttle后STW时间暴增,应用RT飙高。
处理建议:
– CPU Limit和Request保持一致,或者干脆不设Limit(通过LimitRange做集群级兜底)
– 延长CFS配额周期:修改kubelet参数 --cpu-cfs-quota-period 从100ms到500ms,减少短时突发被Throttle的概率
– 对延迟敏感型工作负载(API服务),用 cpu.cfs_quota_us=-1 关闭CFS限速,靠Request做隔离
# 推荐的Pod资源配额模板
apiVersion: v1
kind: Pod
metadata:
name: api-server
spec:
containers:
- name: app
image: api-server:latest
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
memory: "4Gi"
# CPU不设limit,避免Throttling
env:
- name: JAVA_OPTS
value: "-Xmx3g -Xms3g -XX:+UseG1GC"
资源碎片化诊断:集群明明有资源却调度不上去
集群Total CPU 256核,Allocated 180核,还剩76核,但申请新的8C Pod却一直Pending。这类问题在节点规模50+的集群中几乎每周都会碰到。
碎片化的典型成因:
– 节点CPU和内存比例不均衡(某些节点CPU满了但内存大量空闲)
– 大小Pod混合调度,小Pod占了大节点的碎片
– StatefulSet/DaemonSet的固定调度导致节点预留空间无法被复用
下面这个Python脚本用来诊断集群碎片化程度,找出最值得重调度的热点节点:
#!/usr/bin/env python3
"""K8s集群资源碎片化分析脚本
识别CPU/内存分配不均的节点,量化碎片化损失。
"""
import subprocess
import json
def get_node_resources():
"""采集节点资源数据"""
result = subprocess.run(
["kubectl", "top", "nodes", "--no-headers"],
capture_output=True, text=True, timeout=30
)
nodes = []
for line in result.stdout.strip().split("\n"):
parts = line.split()
if len(parts) >= 5:
nodes.append({
"name": parts[0],
"cpu_alloc": int(parts[1].rstrip("%")),
"mem_alloc": int(parts[3].rstrip("%")),
"cpu_cap": parts[2],
"mem_cap": parts[4]
})
return nodes
def calc_fragmentation(nodes, threshold=70):
"""计算碎片化损失的可调度Pod数"""
# 假设标准Pod: 4C8G
pod_cpu, pod_mem = 4, 8 # 占总资源的近似百分比
total_lost = 0
hotspots = []
for n in nodes:
# CPU和内存分配差距过大 = 碎片化
gap = abs(n["cpu_alloc"] - n["mem_alloc"])
if gap > 20: # 差距超20%视为碎片化
# 估算该节点因碎片化浪费的Pod槽位
min_free = min(100 - n["cpu_alloc"], 100 - n["mem_alloc"])
lost_pods = int(min_free / max(pod_cpu, pod_mem))
total_lost += lost_pods
hotspots.append({
"node": n["name"],
"cpu_alloc": n["cpu_alloc"],
"mem_alloc": n["mem_alloc"],
"gap": gap,
"lost_pods": lost_pods
})
hotspots.sort(key=lambda x: x["lost_pods"], reverse=True)
return total_lost, hotspots
def main():
nodes = get_node_resources()
total_lost, hotspots = calc_fragmentation(nodes)
print(f"集群节点数: {len(nodes)}")
print(f"碎片化损失Pod槽位: {total_lost}")
print(f"\n碎片化TOP5热点节点:")
for h in hotspots[:5]:
print(f" {h['node']}: CPU {h['cpu_alloc']}% / MEM {h['mem_alloc']}% "
f"(差{h['gap']}%, 损失{h['lost_pods']}个Pod槽位)")
if total_lost > len(nodes) * 2:
print("\n[WARN] 碎片化严重,建议执行descheduler重平衡")
if __name__ == "__main__":
main()
自定义业务感知调度器:让调度理解你的业务
默认的kube-scheduler基于通用打分策略(Balance、NodeAffinity等),不感知业务语义。比如你希望同一组微服务的Pod分散在不同可用区,同时同一可用区内优先聚合以减少跨区延迟——这种需求默认调度器很难兼顾。
用Scheduler Framework的Plugin机制可以扩展调度逻辑。核心思路是在Score阶段注入业务自定义打分:
– 同业务组Pod跨AZ分散:当前AZ已有同组Pod则降分
– 低延迟需求Pod优先调度到网络延迟低的节点(可通过探针数据打分)
– GPU Pod优先调度到GPU利用率低的节点
实现上,写一个实现了 Score 和 ScoreExtensions 接口的Go Plugin,编译为.so文件挂载到kube-scheduler即可。社区已有现成项目如 scheduler-plugins 可以直接复用CoScheduling等能力。
调度性能调优:大规模集群的瓶颈突破
集群节点超过1000时,调度延迟会明显上升。kube-scheduler默认配置下,一个Pod的调度周期包含Filter和Score两个阶段,每个阶段都遍历所有节点。
几个关键调优参数:
– --max-open-files:提高到50000,避免高并发调度时文件描述符耗尽
– --percentage-of-nodes-to-score:设为50,Score阶段只评估一半节点(大集群下精度损失可忽略)
– 开启 Score 阶段的缓存:避免每个Pod都重复计算节点得分
调度队列也值得关注。默认队列是无优先级的FIFO,如果低优先级批处理任务占满了队列,高优先级在线服务就要排队。启用PodPriority和Preemption可以让调度器抢占低优先级Pod来保障在线服务。
监控告警:用Prometheus捕获资源调度异常
调度相关告警规则需要覆盖三个层面:Pod级别(OOM/Throttling)、节点级别(资源耗尽)、集群级别(调度失败率)。
以下是关键告警规则:
# Pod被OOMKill告警
- alert: PodOOMKilled
expr: kube_pod_container_status_oom_killed == 1
for: 0m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.pod }} 被OOMKill"
description: "命名空间 {{ $labels.namespace }} 的 Pod {{ $labels.pod }} 容器内存超限被杀"
# CPU Throttling告警(Throttling时间占比超50%)
- alert: HighCPUThrottling
expr: |
rate(container_cpu_cfs_throttled_periods_total{container!=""}[5m])
/ rate(container_cpu_cfs_periods_total{container!=""}[5m]) > 0.5
for: 10m
labels:
severity: warning
annotations:
summary: "容器 {{ $labels.container }} CPU被严重Throttling"
description: "Throttling比例超过50%,建议调高CPU Limit或移除Limit"
# 调度失败告警
- alert: PodSchedulingFailed
expr: kube_pod_scheduler_unschedulable > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.pod }} 无法调度"
description: "命名空间 {{ $labels.namespace }} 的 Pod {{ $labels.pod }} 已Pending超5分钟"
资源调度优化没有银弹,核心是让Request/Limit贴近真实用量、持续监控碎片化和Throttling、根据业务需求扩展调度策略。把这套体系搭好,集群的资源利用率和稳定性都能上一个台阶。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-rong-qi-bian-pai-zi-yuan-diao-du-you-hua-shi/