Kubernetes 调度策略深度拆解:我如何帮团队省下 90% 的资源成本
Kubernetes 调度策略深度拆解:我如何帮团队省下 90% 的资源成本
作者|Echo_Wish(爱算账的 K8s 打工人)
兄弟姐妹们,实话实说:很多公司的 Kubernetes 集群资源使用率真实情况只有 10%~30%。你没看错,就是这点儿。
大家不是技术不行,而是默认调度 + 一堆“看起来合理”的配置把钱烧没了。
我见过太多集群:节点 CPU 一直空着,Pod 却在横着扩;大部分 Deployment 的 request 都是拍脑袋写的;HPA 靠天吃饭;调度策略完全走默认;晚上没人访问服务,集群却和白天一样热火朝天地烧钱。
所以我想写一篇真正落地、接地气、能帮你 省真金白银 的调度策略指南。下面的招数都是我自己在生产环境试过的,省下来不仅是成本,更是 KPI 吧(你懂的)。
一、为什么默认调度会浪费资源?
Kubernetes 默认调度器(kube-scheduler)遵循一种“大家都能跑就行”的哲学,优先保证可靠性,但绝不帮你省钱。
默认的问题:
- Request 填大了 → 导致 资源虚空占用(实际不需要那么多)。
- Pod 分散调度 → 节点之间负载不均,出现大量 碎片化。
- 低峰期没有自动缩容 → 白白浪费节点成本。
- 没用 NodeAffinity / Taints → Pod 跑得乱七八糟 → 影响 bin-packing。
简单说:
默认调度不是为省钱设计的,而是为“不出事”设计的。
二、想省 90% 成本?先搞清楚资源是怎么烧掉的
来看一张典型“企业集群 CPU 使用情况”的 ASCII 图:
节点1: [##########------------------------] 35%
节点2: [######----------------------------] 20%
节点3: [########--------------------------] 25%
节点4: [#---------------------------------] 5%
节点5: [#---------------------------------] 3%
节点6: [#################################] 90%(重点服务)
真实情况:三个节点能干这六个节点的活。
这就是 bin-packing 不好 + pod 分布不均 的结果。
下面我给你一个从“浪费”走向“极致省钱”的完整路径。
三、四大调度策略 + 实战配置(真正能省钱)
策略一:优化 Request / Limit(最有效的降本手段,没有之一)
很多团队 CPU request 全靠猜,写得特别大,比如:
resources:
requests:
cpu: 500m
memory: 1Gi
实际上服务平均 CPU 可能就只有 30m。
Result:节点被虚假占满,真正的资源利用率低得可怜。
怎么解决?
步骤 1:用 metrics-server 或 Prometheus 查看真实资源使用
kubectl top pod
步骤 2:按照平均值 + 波动给 request,而不是盲目加大
例如你的服务平时使用 20–50m CPU,那么 request 给 50–80m 都很安全。
策略二:使用 Pod 优先级(PriorityClass)让重要服务先占坑
遇到资源紧张时,谁先被挤掉?
默认:大家地位一样 → 调度器乱来。
用 PriorityClass 能保证关键服务永远有资源:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: critical-app
value: 1000000
globalDefault: false
description: "关键服务,不可驱逐"
然后在 Pod 里使用:
priorityClassName: critical-app
这样 bin-packing 时关键服务先放,高优先级抢占低优先级 → 节点资源利用更紧凑。
策略三:Pod 亲和性/反亲和性,让调度真正“聪明”起来
让 Pod 尽量挤在一起(bin packing 强化版)
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: myservice
topologyKey: kubernetes.io/hostname
效果:
Pod 越多,就越被安排在同一个节点,空出更多节点可供缩容。
反亲和性:防止相同 Pod 全堆一台(必要时启用)
例如高可用服务:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: gateway
topologyKey: kubernetes.io/hostname
策略四:使用 Descheduler + Cluster Autoscaler(成本杀手锏)
光靠 scheduler 不够,因为 Pod 会随着时间推移变得不均衡,这就需要 Descheduler 来重新平衡。
示意图:
初始:
节点1:80%
节点2:10%
节点3:15%
Descheduler 运行后:
节点1:60%
节点2:60%
节点3:25%
→ Cluster Autoscaler 自动把节点3缩掉 → 节省钱。
Descheduler 配置示例
profiles:
- name: Default
pluginConfig:
- name: "RemoveDuplicates"
- name: "LowNodeUtilization"
args:
thresholds:
cpu: 20
memory: 20
targetThresholds:
cpu: 80
memory: 80
Descheduler 会把“不满载”的节点 Pod 全挪走 → Autoscaler 自动缩容 → 真正省钱。
四、最容易忽视的关键:按时间动态调度(夜间成本减半)
不少服务晚上根本没多少访问量,但 Pod 仍然占着资源不松口。
👇 推荐用 HPA + CronJob 做“时间维度调度”:
例:夜间自动缩容,只保留 1 个 Pod
apiVersion: batch/v1
kind: CronJob
metadata:
name: night-scale
spec:
schedule: "0 1 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: kubectl
image: bitnami/kubectl
command: ["kubectl", "scale", "deploy/myapp", "--replicas=1"]
restartPolicy: OnFailure
白天流量恢复:
schedule: "0 7 * * *"
command: ["kubectl", "scale", "deploy/myapp", "--replicas=10"]
一个简单策略 → 节省 30–40% 的节点成本。
五、我踩过的坑和真实感受
这些年从 50 台节点省到 15 台节点,不夸张说省了好几百万——但这个过程不轻松。
我见过这些坑:
- 开发随便填 request,导致整集群被“虚空占用”
- 调度策略写得很复杂,却没人维护
- Autoscaler 配置错误 → 峰值瞬间崩
- SRE 只看 CPU,不看内存,结果内存 OOM 把 Pod 全踢下线
也见过好的情况:
- 用好 bin-packing → 节点减少 50%
- 夜间缩容策略 → 再省 30%
- 优先级 + 节点池分层 → 再省 10%
真正让我省下 90% 成本的不是某个神技,而是这四件事:
- 请求值填准确
- Pod 调度更聪明
- 持续重平衡
- 自动缩容策略完善
没有玄学,就是扎实的工程方法。
- 点赞
- 收藏
- 关注作者
评论(0)