在Kubernetes集群中,命名空间级配额通过ResourceQuota对象硬性限制资源总量,对突发流量说“不”的核心机制是调度拦截当Namespaces内已用资源加上新Pod请求超过预设阈值时,API服务器直接拒绝创建,而不是等资源耗尽后驱逐。
命名空间配额为什么能拦住资源突发
资源突发最怕的是无预兆的Pod暴增,一个取值异常的控制器副本数、一次错误配置的HPA扩容策略,都可能把几小时的资源余量在一分钟内打满,命名空间配额的作用就是在源头设一道闸。
ResourceQuota的定义维度
配额不是一个模糊的总量,而是按照Kubernetes资源模型精确计量,常用维度包括:
- CPU和内存:requests、limits两个维度单独计数,比如限制所有Pod的requests.cpu总和不超过4核,limits.memory不超过8G。
- 存储资源:requests.storage限制PVC总容量,同时可限制PersistentVolumeClaims的数量和单个PVC大小。
- 对象数量:pods、deployments、services等对象个数,防止资源密集型的对象无限增长。
这种多维拦截至关重要,只限CPU和内存,没有限Pod数量,集群可能被海量小Pod打爆API Server,实战中建议同时配置资源类配额和对象类配额。
调度器如何执行配额拦截
当一个新的Pod提交到Namespace时,API Server的准入控制器会先做统计:把当前命名空间内所有Pod的requests和limits与配额上限做差,再验证新Pod提交的数值是否超出剩余量。只要任意一项超出,整个创建动作被拒绝,返回一个形如exceeded quota的错误信息,这个动作发生在调度器介入之前,因此资源突发在源头就被拦下,不会占用集群的实际节点容量。
这种机制的优势在于它是一个确定性的硬约束,不受节点压力、调度算法的影响,突发流量再大,配额说拒就拒。
命名空间配额怎么设置:菜鸟也能上手的三种路径
用一条命令创建简单配额
开发环境快速试验时,直接使用kubectl命令:
kubectl create namespace meeting
kubectl create quota meeting-quota -n meeting --hard=cpu=4,memory=8Gi,pods=10
这条命令在meeting这个命名空间内设置三项配额:所有Pod的request CPU总量不超过4核,request内存总量不超过8GiB,同时最多只能存在10个Pod,命令执行后,配额立即生效。
验证是否生效:
kubectl describe resourcequota meeting-quota -n meeting
输出中会展示当前使用量和配额上限,尝试在meeting命名空间创建第11个Pod时,API服务器会拒绝,并提示exceeded quota: meeting-quota。
用YAML方式分布式管理配额
在多环境、多租户场景下,命令方式难以追溯,推荐把配额作为代码管理,写入部署仓库:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
requests.cpu: "8"
requests.memory: 16Gi
limits.cpu: "16"
limits.memory: 32Gi
pods: "50"
services: "20"
应用配置:
kubectl apply -f resourcequota.yaml
之后再执行kubectl get resourcequota -n dev可以看到当前配额状态。
配额设好后的监控和调优
配额不是设完就不管的,延续用kubectl describe resourcequota查看所有指标的使用比例,当某个值的Usage/Hard接近阈值,就该调研发突发流量是正常扩展还是异常攻击了。
容器云资源配额配置的实践中,笔者推荐定期执行配额使用率报告,用kubectl get quota --all-namespaces导出所有Namespace的配额快照,方便团队Review。
命名空间资源限额和LimitRange的对比:只限总量远远不够
很多人以为配好ResourceQuota就万事大吉,实际生产环境中还必须搭配LimitRange,两者各司其职。
ResourceQuota只管总量,管不了单个Pod
ResourceQuota限制的是命名空间内所有Pod的加总,它不会检查一个单独的Pod内存请求是否合理,举例说明:一个Pod申请requests.memory=4Gi在配额额度72Gi的Namespace中是可以被接受的,但这个Pod可能为一个并不需要的缓存组件申请了4GB,造成单点资源浪费,大量这样的Pod堆积起来,总配额很快就会耗尽,但真正关心的业务Pod反而调度不进去。
LimitRange给单个Pod定上限
LimitRange是另一个维度,它在Namespace维度下发准入策略,约束单个Pod、Container的requests和limits最小值/最大值,例如限制单个Pod的CPU申请不超过2核,内存申请不超过8GiB。
| 维度 | ResourceQuota | LimitRange |
|---|---|---|
| 作用范围 | 整个Namespace的资源总量 | 单个Pod或Container |
| 拦截时机 | 统计请求时跨Pod汇总 | 验证单Pod声明值 |
| 典型场景 | 多团队共享集群时划分蛋糕 | 防止单个容器申请过大资源 |
| 失败表现 | 整个Pod会被拒绝 | Pod会被拒绝或字段被强制修正 |
生产环境推荐的组合方案
行业共识认为,同时配FlatRange和ResourceQuota是标准做法,配额上限要覆盖Normal业务预留量和30%-50%的突发余量,LimitRange的单Pod上限按Pod实际用量最高值的1.2倍设置,比如业务Pod内存峰值普遍是1.5GB,可以把LimitRange的max设为2GB。
apiVersion: v1
print:
value:s
列举一组常用配置:
- Pod的requests.cpu必须在100m到2之间
- 单个Container的limit必须在1Gi到4Gi之间
- 默认request为100m CPU和128Mi内存
当ResourceQuota和LimitRange同时存在时,Kubernetes先检查LimitRange,如果Pod声明值超出单Pod的max,则直接被拒;通过后再检查ResourceQuota总量。
k8s限额资源突发的几种常见坑
只限制limits不限制requests,突发照样失控
有人只设limits.cpu=16,limits.memory=32Gi,忽略了requests字段的配额,这会造成什么呢?Kubernetes调度时参考的是requests值,而非limits值,如果Pod不声明requests,那么服务端的默认值会处理,但它究竟是0还是等于limits取决于集群的默认设置,假设requests被当作1或与limits等同,而配额只限制limits时,实际上在CPU资源上并未起到控制突发效果,因为limits不能反映调度时的真实请求量。
必须在配额里同时定义requests和limits。如果只设limits不设requests,那requests总量根本不受限,Pod仍然可以按照满requests量进行调度放置,而调度器没有检测上限,积压的burst资源会持续上涨。
配额设得太紧,导致业务无法扩容
突发场景下,业务扩容被拒,原因是配额余量不足,这种情况比资源耗尽更让人窝火,调优时优先查看kubectl describe中的Used与Hard,比较各项资源的占比,如果内存已经快到上限,扩容时直接报
exceeded quota,此时处理顺序:
- 清理长期废弃PVC,释放requests.storage和PersistentVolumeClaims配额
- 检查是否有异常Pod持续占着resources
- 业务突增确实合理,就临时调高配额,并同步做成本核算
计量维度忽略扩展资源
GPU、FPGA等扩展资源同样可以放入配额,配置方式为:
spec:
hard:
requests.nvidia.com/gpu: "4"
这个限制确保一个Namespace最多申请四张GPU卡,如果只配CPU和内存配额,GPU请求将不受 любой限制。
删除Namespace导致配额和RC一起被带走
资源配额定义在指定命名空间内,删除Namespace时ResourceQuota和LimitRange会全部消失,很多团队在测试环境重建Namespace后直接部署应用,忘了重新应用配额YAML,结果释放了限制,引发资源使用失控,规范做法是需要将配额YAML放在Git仓库的配置目录中,与Namespace的生成流程关联,这样创建即生效。
命名空间级配额常见问题答疑
配额满了之后,已经运行的Pod会被驱逐吗
不会,ResourceQuota只在创建新对象时生效,如果已经运行的Pod集群或某个Pod内部持续提交资源,配额不会惊动现有运行中的进程,若要主动清理,需要人工删除Pod或调低副本数量,同时也需要检查其他Namespace是否也存在资源占用,因为节点级别的物理资源是共享的。
报错exceeded quota时,怎么排查哪个资源超了
错误信息会列出超限的具体资源项,以kubectl apply输出为例,它显示exceeded quota: dev-quota, requested:pods=11, used:10, limited:10,这说明Pod数量超出限制,如果是cpu或memory超限,则会展示当前Used值和Hard值,同时用kubectl get resourcequota dev-quota -n dev -o yaml查看status段中每个资源的Used状态数值。
不同的ResourceQuota可以叠加生效吗
可以,同一命名空间可以创建多个ResourceQuota,Kubernetes的在配额机制中对多个配额对象采用选择器叠加统计的模式,一旦多个都定义相同的资源项,最终取最严格的交集限制,注意在这里区分集合逻辑:一个Pod的所有配置必须同时满足全部配额对象,才会被准入通过。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/642101.html





