在 Kubernetes 集群中,如果没有资源限制,一个恶意的或出现异常的容器可能会耗尽节点上的所有 CPU 和内存,导致其他 Pod 甚至节点本身不稳定。Kubernetes 提供了多层次的资源管理机制:容器级别的 requests 和 limits、命名空间级别的 ResourceQuota 以及 LimitRange。本文详细讲解这些概念,帮助你在保障应用性能的同时,维护集群的整体健康。
一、Requests 与 Limits:容器资源的"申请"与"上限"
每个容器可以指定 resources.requests 和 resources.limits。
requests:调度器基于此值决定将 Pod 放在哪个节点。它表示容器"保证"能获得的最小资源量。
limits:容器允许使用的最大资源量。超过 CPU 限制会限流(throttle),超过内存限制会触发 OOM Kill。
1.1 在 Pod 中配置
yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: app
image: nginx
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
CPU 单位:1 = 1 个 CPU 核心,500m = 0.5 个核心。
内存单位:Ki、Mi、Gi(2 的幂次),也可用 M、G(十进制,但推荐使用 Mi 等)。
1.2 为什么不设置 limits 有害?
如果只设置 requests 不设 limits,容器可以使用节点上所有可用资源,可能导致其他容器饥饿。
如果都不设置,容器可以无限使用资源,是典型的"吵闹邻居"问题。
最佳实践:总是设置 requests 和 limits,且 limits >= requests。
1.3 QoS(服务质量)类别
Kubernetes 根据 requests 和 limits 的组合将 Pod 分为三类,决定了资源紧张时驱逐的顺序:
QoS 类别 条件 驱逐优先级(最低→高)
Guaranteed 每个容器同时设置了 CPU 和内存的 requests 和 limits,且两者相等 最后驱逐
Burstable 至少一个容器设置了 requests,但并非 Guaranteed 中间
BestEffort 没有设置任何 requests 和 limits 最先驱逐
示例:
Guaranteed:requests.memory=256Mi, limits.memory=256Mi(CPU 同理)
Burstable:requests.cpu=250m 但无 limits,或 requests 与 limits 不等
BestEffort:完全不写 resources 字段
生产环境关键服务应使用 Guaranteed,以确保稳定性。
二、ResourceQuota:命名空间级别的资源总量限制
ResourceQuota 用来限制一个命名空间内所有 Pod 的累计资源使用量,防止某个命名空间耗尽集群资源。
2.1 创建 ResourceQuota
yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
persistentvolumeclaims: "10"
pods: "20"
除了 CPU/内存,还可以限制 PVC 数量、Service 数量、ConfigMap 数量等。
当命名空间内资源请求总和超过配额时,新的 Pod 创建会失败(提示 exceeded quota)。
2.2 查看 ResourceQuota 使用情况
bash
kubectl describe resourcequota -n dev
输出会显示当前使用量 / 总配额。
2.3 与 LimitRange 配合
如果命名空间设置了 ResourceQuota,通常要求每个 Pod 必须指定 requests/limits,否则无法创建。可以通过 LimitRange 自动设置默认值。
三、LimitRange:为 Pod 设置默认资源和范围约束
LimitRange 用于在命名空间级别为 Pod 或容器提供默认的 requests/limits,或者约束其取值范围。
3.1 创建 LimitRange
yaml
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limits
namespace: dev
spec:
limits:
- default: # 如果 Pod 未指定 limits,使用此默认值
cpu: "500m"
memory: "512Mi"
defaultRequest: # 如果 Pod 未指定 requests,使用此默认值
cpu: "250m"
memory: "256Mi"
max: # 允许的最大值
cpu: "2"
memory: "4Gi"
min: # 允许的最小值
cpu: "100m"
memory: "128Mi"
type: Container
type 可以是 Container 或 Pod(Pod 级别限制不常用)。
创建 LimitRange 后,后续创建的 Pod 如果未指定资源,会自动注入默认值;如果指定了超出 max/min 范围的值,API Server 会拒绝创建。
3.2 查看 LimitRange
bash
kubectl describe limitrange -n dev
四、实战:配置一个带资源约束的命名空间
假设我们为开发团队创建一个 dev 命名空间,限制总资源不超过 4 核 CPU、8G 内存,同时要求每个容器至少 128Mi 内存,最多 1G 内存,未指定则使用默认值。
步骤:
bash
kubectl create namespace dev
创建 limit-range.yaml:
yaml
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limits
namespace: dev
spec:
limits:
- default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "250m"
memory: "256Mi"
max:
cpu: "1"
memory: "1Gi"
min:
cpu: "100m"
memory: "128Mi"
type: Container
创建 resource-quota.yaml:
yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
pods: "10"
应用配置:
bash
kubectl apply -f limit-range.yaml -f resource-quota.yaml
测试 Pod:
yaml
apiVersion: v1
kind: Pod
metadata:
name: test
namespace: dev
spec:
containers:
- name: app
image: nginx
# 未指定 resources,会使用 LimitRange 默认值
创建后查看配额:
bash
kubectl get resourcequota -n dev
五、最佳实践总结
每个容器都要设置 requests 和 limits,至少设置 memory limits(防止内存泄漏拖垮节点)。
为命名空间配置 ResourceQuota,在多租户环境下尤为重要。
为命名空间配置 LimitRange,强制用户提交的资源在合理范围内,并提供默认值。
关键服务使用 Guaranteed QoS(requests = limits)。
定期监控资源使用:kubectl top nodes、kubectl top pods。
避免在同一个命名空间混用 Guaranteed 和 BestEffort,可能导致资源挤占。
六、常见问题

七、小结
资源管理是 Kubernetes 生产化的重要一环。通过 requests / limits 控制单容器资源,ResourceQuota 限制命名空间总量,LimitRange 提供默认值和范围约束,你可以构建一个稳定、公平的多租户集群。