Kubernetes 资源配额怎样避免命名空间之间互相争抢
来源:17golang原创
时间:2026-11-14 05:06:31 471浏览 收藏
我在共享 Kubernetes 集群里最容易遇到的争抢,不是某个 Pod 突然变慢,而是一个命名空间不断提高 requests,最后让别的团队的新 Pod 无法进入。ResourceQuota 的正确用法是先按 namespace 划出总量边界,再用 LimitRange 约束单个 Pod 或容器的最小、最大值和默认值;这样“团队总预算”和“单个工作负载上限”才不会混在一起。
给每个业务 namespace 配置独立的 ResourceQuota,并让每个容器明确 requests/limits;如果担心遗漏,再用 LimitRange 注入默认值。需要注意,ResourceQuota 统计的是 namespace 的聚合消耗,不会把 Pod 固定到某些节点,也不会自动把集群新增容量分给某个 namespace。
官方地址:https://kubernetes.io/docs/concepts/policy/resource-quotas/
先把命名空间边界和配额职责分清
ResourceQuota 只在它所在的 namespace 内生效。它可以统计非终止 Pod 的 CPU、内存请求和限制,也可以统计 Pod、PVC、Service、Secret 等对象数量。不同 namespace 可以各自有一套上限,但这些上限是绝对值:把集群扩容,并不会自动提高现有 quota。
| 治理问题 | 主要对象 | 应该由谁负责 |
|---|---|---|
| 一个团队总共能申请多少 CPU、内存 | ResourceQuota | namespace 聚合预算 |
| 一个 Pod 或容器不能超过多少 | LimitRange | 单对象上下限与默认值 |
| Pod 最终落在哪台节点 | 调度器、节点池、亲和性 | 放置和容量规划 |
因此,quota 不是“给 namespace 预留一组节点”。多个 namespace 的 Pod 仍可能落在同一个节点上,最终是否调度成功还取决于节点可用资源、调度约束和 Pod 的 requests。配额要解决的是一个 namespace 能向集群申请多少,以及 API Server 是否应该拒绝继续增加。

初始化 ResourceQuota 的总量边界
我通常先为每个业务 namespace 建立一份小而清楚的 quota,先限制 requests 总量,再限制 limits 总量和 Pod 数。下面的示例把“可调度承诺”“最大限制”和“对象数量”放在同一个 namespace 的治理文件里:
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-budget
namespace: team-a
spec:
hard:
# requests 影响调度承诺,控制团队最多申请的 CPU 和内存
requests.cpu: "8"
requests.memory: 16Gi
# limits 约束运行时上限,避免限制总和无限增大
limits.cpu: "12"
limits.memory: 24Gi
# 限制活跃 Pod 数,防止错误的批量创建拖垮集群对象
pods: "40"
这里的 requests.cpu 与 requests.memory 是 namespace 内所有相关 Pod 的请求总和,limits.* 则是限制总和。只要新的创建或更新会让 used 超过 hard,API 请求就会被拒绝。资源名可以使用简写的 cpu、memory,但团队规范最好统一写出 requests.*,减少读配置时的歧义。
用 requests、limits 和 LimitRange 处理单 Pod
只配总量还不够:如果 namespace 有 16Gi 内存预算,一个 Pod 也可能一次申请接近全部预算。LimitRange 适合给单个容器规定最小、最大和默认的 requests/limits;它和 ResourceQuota 是互补关系,不要拿其中一个替代另一个。
apiVersion: v1
kind: LimitRange
metadata:
name: team-a-defaults
namespace: team-a
spec:
limits:
- type: Container
# 未填写资源字段的容器使用默认值,避免 quota 因缺少字段而拒绝
default:
cpu: "500m"
memory: 512Mi
defaultRequest:
cpu: "100m"
memory: 128Mi
# 单容器不能申请超过这个上限,也不能低于最小请求
max:
cpu: "2"
memory: 4Gi
min:
cpu: "50m"
memory: 64Mi
这个组合有一个常被忽视的顺序:Pod 进入 API Server 时,LimitRange 可以为缺省字段提供默认值,然后 ResourceQuota 再按 namespace 汇总。若在启用 CPU 或内存 quota 的 namespace 中完全不写请求或限制,Pod 可能因为缺少对应资源字段而无法通过准入;所以默认值应和团队的实际工作负载一起评估,不能随便填一个极小数字。

运行检查并观察拒绝原因
配置完后,我会先看 quota 的 hard 和 used,再检查工作负载是否带有预期的资源字段。下面的命令只负责读取状态,不依赖某个发行版的额外插件:
# 查看 team-a 的配额上限与当前消耗 kubectl get resourcequota -n team-a -o yaml # 用表格快速观察 requests、limits 和 Pod 数的剩余空间 kubectl describe resourcequota team-a-budget -n team-a # 查看 Pod 最终得到的 requests/limits,确认默认值是否符合预期 kubectl get pods -n team-a -o custom-columns='NAME:.metadata.name,CPU_REQ:.spec.containers[*].resources.requests.cpu,MEM_REQ:.spec.containers[*].resources.requests.memory,CPU_LIMIT:.spec.containers[*].resources.limits.cpu,MEM_LIMIT:.spec.containers[*].resources.limits.memory'
如果创建失败,重点看返回中的 exceeded quota、requested、used 和 limited。例如当前内存请求是 15Gi,quota 上限是 16Gi,新 Pod 再申请 2Gi 就会被拒绝;这不是“节点刚好没空位”的同一个问题,而是 namespace 的 API 准入预算先被触发。
排查时不要只看 Deployment 副本数。一个 Deployment 可能通过 ReplicaSet 创建多个 Pod,Job 或 CronJob 也可能持续产生对象;应同时观察 quota 的对象数量项和工作负载控制器的副本策略。
扩展到对象数量和分级治理
当团队已经有稳定的 CPU、内存预算后,再补对象数量通常比继续扩大资源配额更有效。例如对 PVC、LoadBalancer Service 或 Secret 设置数量限制,可以防止错误脚本不断创建对象,耗尽控制面存储或云资源配额:
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-object-budget
namespace: team-a
spec:
hard:
# 保护持久化存储申请和高成本的外部负载均衡入口
persistentvolumeclaims: "12"
services.loadbalancers: "2"
# 限制控制面对象数量,降低批量错误的影响面
count/secrets: "80"
count/jobs.batch: "100"
如果集群需要按 PriorityClass 给高、低优先级工作负载分配不同预算,可以使用带 scopeSelector 的 ResourceQuota。它仍然是 namespace 内的聚合统计,不会把低优先级 Pod 自动赶到别的节点,也不会替代节点池或抢占策略的整体设计。
最后要记住一个边界:配额变化不会回溯修改已经创建的资源。扩大 quota 不会自动改变旧 Pod 的 requests,缩小 quota 也不等于立即驱逐已经运行的 Pod;它主要影响后续创建或更新是否能通过检查。
清理与总结
实验 namespace 不再使用时,先确认里面没有要保留的对象,再删除测试资源。生产环境不要直接照抄示例数字,而应从历史用量、峰值副本数、节点容量和故障余量倒推 hard 值。
# 仅删除本教程创建的测试 namespace;生产环境请先确认清理范围 kubectl delete namespace team-a
我的落地顺序是:先用 ResourceQuota 定义 namespace 的总预算,再用 LimitRange 收紧单容器的边界,随后用 hard/used 和 Pod 实际字段做复查。这样即使多个团队共用节点,也能把“谁申请了多少”和“单个 Pod 能申请多少”拆成可解释的两层规则。
常见问题
ResourceQuota 能把团队固定到独立节点吗?
不能。它限制 namespace 的聚合资源和对象数量,不负责节点放置;节点池、污点容忍、亲和性和调度策略才是节点隔离工具。
只配置 requests.cpu,为什么 Pod 仍可能创建失败?
需要结合 namespace 里的 quota 项和 Pod 字段看。如果 quota 同时要求 CPU 或内存的请求/限制,而容器没有对应字段,准入可能拒绝;LimitRange 可以提供默认值,但默认值本身也要满足最小值、最大值和团队预算。
新增节点后要不要自动提高每个 namespace 的 quota?
不应该自动提高。quota 是治理预算而不是节点容量镜像;应根据团队实际需求、共享余量和调度策略重新分配,避免扩容后所有 namespace 同时放大申请。
一句话总结:用 ResourceQuota 限制 namespace 总量,用 LimitRange 限制单对象,用 requests 表达调度承诺,再用 hard/used 观察真实消耗;这比给所有 namespace 一个过大的上限更能减少互相争抢。
-
214 收藏
-
Golang · Go教程 | 5个月前 | 性能优化 · kubernetes · Go教程 · 生产实践 · Go1.25 · golang Go Kubernetes 性能优化 GOMAXPROCS473 收藏
-
Golang · Go教程 | 3个月前 | 容器 · go · 性能 · kubernetes · 运行时 · Kubernetes GOMAXPROCS cgroup Go 1.25 容器 CPU 限额438 收藏
-
318 收藏
-
353 收藏
-
科技周边 · 业界新闻 | 28分钟前 | 云原生 · 可观测性 · 业界新闻 · 云原生 FLUSH OpenTelemetry Collector batch processor observability268 收藏
-
482 收藏
-
302 收藏
-
217 收藏
-
446 收藏
-
401 收藏
-
296 收藏
-
491 收藏
-
295 收藏
-
267 收藏
-
247 收藏
-
352 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习