资源配额
本教程共 65 篇 · 第 42 篇 · 更新于 2026-08-14 · 约 15 分钟阅读
本节目标:理解 ResourceQuota 和 LimitRange 各自解决什么问题,会用 YAML 给命名空间设总配额和单对象上下限,并知道两者怎么配合,避免一个 Pod 吃光整个团队资源。
前面几章都在讲 Pod 怎么调度、怎么落点。可在真实集群里,还有一关:资源不能让人乱用。一个团队把节点 CPU 全占满,别的团队就没法干活了。这一章的两样东西,专门管”用量上限”。
42-1 为什么需要配额
很多团队共用一套集群。要是没有约束,哪个组手快、敢开大副本,就把资源抢光了。资源配额就是管理员手里的”公平尺”。
它工作在命名空间层面。不同团队待在不同命名空间,每个命名空间各发一份额度。谁超了谁被拦,互不影响。这种隔离可以用 RBAC 等鉴权机制来强制执行。
配额管的是”总量”。比如 A 团队最多用 20 GiB 内存、10 核 CPU,B 团队最多 10 GiB、4 核。剩下的留作预备,谁都不许超。
Note资源配额由 ResourceQuota 对象定义。一个命名空间里至少有一个 ResourceQuota,配额就对这个命名空间生效了。配额机制在多数发行版里默认开启。
42-2 ResourceQuota 怎么工作
ResourceQuota 的工作方式很直接。管理员为每个命名空间建至少一个 ResourceQuota。用户在命名空间里创建 Pod、Service 等资源时,配额系统实时记账,确保总消耗不突破硬性上限。
如果用户创建或更新资源时踩了配额线,控制平面直接拒绝,返回 HTTP 状态码 403 Forbidden,并附上违反的是哪条约束。
这里有个坑:一旦命名空间对 cpu、memory 启用了配额,用户建 Pod 时必须写清 requests 或 limits,否则配额系统可能拒绝接纳。好在可以用 LimitRange 自动补默认值,后文会讲。
Warning你多半不会直接手建 Pod,而是建 Deployment 这类工作负载对象。配额只拦 Pod,不拦 Deployment。所以一个超量的 Deployment 可能”创建成功”,但它管的那堆 Pod 起不来。这时用
kubectl describe看 Deployment 状态,能发现卡在哪。
42-3 计算资源的配额
最常见的配额就是限制 CPU、内存这类计算资源的总量。ResourceQuota 支持这些资源名:
requests.cpu:所有非终止状态 Pod 的 CPU 请求之和上限。requests.memory:所有非终止状态 Pod 的内存请求之和上限。limits.cpu:所有非终止状态 Pod 的 CPU 限制之和上限。limits.memory:所有非终止状态 Pod 的内存限制之和上限。cpu、memory:分别等同于requests.cpu、requests.memory。hugepages-<size>:指定尺寸巨页的请求总数上限。
一个实际例子,给命名空间设计算资源配额:
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
requests.cpu: "1"
requests.memory: "1Gi"
limits.cpu: "2"
limits.memory: "2Gi"
requests.nvidia.com/gpu: 4
这里的 hard 就是硬性上限。最后一行 requests.nvidia.com/gpu: 4 是扩展资源(如 GPU)的配额。扩展资源不允许超卖,所以只配 requests. 前缀即可,没必要同时写 requests 和 limits。
建好后用 kubectl describe quota compute-resources 能看到 Used 和 Hard 两列,实时反映占用情况。
42-4 存储与对象数量的配额
除了算力和内存,配额还能管存储和”能建多少对象”。
存储相关:
requests.storage:所有 PVC 的存储请求之和上限。persistentvolumeclaims:命名空间里 PVC 的总数上限。<storage-class-name>.storageclass.storage.k8s.io/requests.storage:针对某个 StorageClass 的存储请求上限。- 同理还有该 StorageClass 下的 PVC 数量上限。
比如想给 gold 和 bronze 两种 StorageClass 分别限额:
gold.storageclass.storage.k8s.io/requests.storage: 500Gi
bronze.storageclass.storage.k8s.io/requests.storage: 100Gi
对象数量配额,用来防控制平面被海量对象拖垮。语法是 count/<资源>,核心组资源写 count/pods,非核心组写 count/deployments.apps。常见项:count/pods、count/services、count/secrets、count/configmaps、count/deployments.apps。
也可以直接用简写:pods、services、secrets、configmaps、persistentvolumeclaims,以及 services.loadbalancers、services.nodeports。比如给 pods 设上限,能防止有人建一堆小 Pod 把集群的 Pod IP 耗尽。
TipSecret 体积大,一个命名空间塞太多 Secret 可能让 API 服务器和控制器的启动都受影响。给
secrets设数量配额,是性价比很高的保护。
42-5 配额作用域 scope
ResourceQuota 还能加 scope,只统计符合作用域的资源,作用域取交集生效。v1.36.2 支持这些作用域:
BestEffort:只算 QoS 为 BestEffort 的 Pod。NotBestEffort:只算非 BestEffort 的 Pod。Terminating/NotTerminating:按 Pod 是否在终止中区分。PriorityClass:只算引用了特定优先级类的 Pod。CrossNamespacePodAffinity:管”哪些命名空间允许带跨命名空间亲和性条件的 Pod”。VolumeAttributesClass:只算引用特定卷属性类的 PVC。
带作用域的配额还能配 scopeSelector 字段,用 In、NotIn、Exists、DoesNotExist 做更细的匹配。比如想彻底禁止某命名空间里出现跨命名空间亲和,可以建一个 CrossNamespacePodAffinity 作用域、pods: "0" 的配额,等于把这类 Pod 数量锁死为 0。
Note配额和集群容量无关。它是用绝对数值表达的。你给集群加了新节点,命名空间的额度不会自动变大。想要”按比例扩容”,得自己写控制器去动态调每个命名空间的 hard 值。
42-6 LimitRange 是什么
ResourceQuota 管”命名空间总共能用多少”。可它防不住另一个问题:一个 Pod 自己把整块额度吃光。LimitRange 就是来管”单个对象能申请多少”的。
LimitRange 是限制命名空间内,每个适用对象(Pod、容器、PVC)的资源取值区间的策略对象。只要命名空间里至少有一个 LimitRange,Kubernetes 就会对新建的对象做约束。
一个 LimitRange 能做的事:
- 规定 Pod 或容器能用的最小、最大 CPU 和内存。
- 规定 PVC 能申请的最小、最大存储。
- 规定某资源的 request 和 limit 的比值上限。
- 给没写资源需求的容器自动补上默认 request 和 limit。
42-7 LimitRange 的约束与默认值
管理员在命名空间建一个 LimitRange,用户再来建 Pod 或 PVC。流程分两步:第一步,准入控制器给没设资源需求的容器补默认 request/limit;第二步,跟踪用量,确保没突破 LimitRange 定的最小、最大和比值。
如果创建或更新的对象违反了 LimitRange 的约束,API 服务器的请求会失败,返回 403 Forbidden 并说明踩了哪条线。
LimitRange 有几个行为要点:
- 验证只在 Pod 准入阶段做,已经跑着的 Pod 不受影响。你改了 LimitRange,旧 Pod 原样继续。
- 命名空间里若有两个以上 LimitRange,到底用谁的默认值是不确定的,别这么干。
- 加了针对
cpu、memory的 LimitRange 后,建 Pod 就必须写清这些资源的请求或限制,否则会被系统拒绝。
apiVersion: v1
kind: LimitRange
metadata:
name: mem-cpu-limit-range
spec:
limits:
- default:
cpu: 500m
memory: 256Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: "1"
memory: 512Mi
min:
cpu: 50m
memory: 64Mi
type: Container
这段配置给命名空间里的容器设了默认、最小和最大。写 Pod 时忘填资源,准入控制器就按 defaultRequest、default 补上;想填超过 max 的,直接被拒。
WarningLimitRange 不检查它补的默认值是否自洽。如果你把 limit 默认值设得比容器自己写的 request 还小,最终 Pod 会因为”request 大于 limit”而无法调度。配 LimitRange 时留意默认值的合理性。
42-8 两者怎么配合
ResourceQuota 和 LimitRange 是一对搭档,一个管总盘子,一个管单对象,合起来才完整。
典型搭配:命名空间开了 cpu、memory 配额,要求每个 Pod 都写资源需求。可你不能指望每个开发都记得写。于是用 LimitRange 自动补默认值——没写的容器,按 LimitRange 给的默认 request/limit 填上,配额系统就不会因”缺字段”而拒人于千里之外。
另外,配额管的是总量,LimitRange 管的是区间,两者都不影响已存在的资源。已经跑着的 Pod,无论你之后怎么改配额或 LimitRange,都保持原状。这点对线上变更很友好,但也意味着”存量”不会自动收敛,需要你另行处理。
Note本章讲的两样对象都属于集群管理员在命名空间层面做的事。它们和容器自身的 resources 配置、QoS 类密切相关——想深入资源配置,可回看第 15 章的资源限制与 QoS 相关内容。
42-9 一句话回顾
ResourceQuota 回答”这个命名空间总共能用多少”,按总量硬拦;LimitRange 回答”单个 Pod、容器、PVC 能申请多大”,按区间约束并补默认。两者都只在新建对象时生效,都用 403 Forbidden 拒绝越界。把它们配合好,多团队共享集群才既公平又省心。