4. Helm Chart中声明资源配额:在templates/中编写ResourceQuota与LimitRange YAML、通过Values动态控制配额
在生产级 Kubernetes 集群中,资源配额(ResourceQuota)与限制范围(LimitRange)是保障多租户隔离与 Pod 稳定性最核心的准入控制机制。本章将演示如何在 Helm Chart 的 templates/ 目录中声明这两类资源,并通过 values.yaml 实现动态参数化,使同一套 Chart 能适配开发、测试、生产等不同环境的资源管控策略。
4.1 资源配额与限制范围的核心差异
| 维度 | ResourceQuota | LimitRange |
|---|---|---|
| 作用范围 | 命名空间级别,聚合所有 Pod 的资源总和 | Pod / 容器级别,约束单个 Pod 的资源上下限 |
| 主要功能 | 限制 CPU/内存/存储/对象数量的总量上限 | 设置默认 request/limit、最小/最大值 |
| 触发时机 | 创建/更新 Pod 时检查命名空间累计用量 | 创建/更新 Pod 时校验单个容器声明值 |
| 典型场景 | 防止单个 Namespace 耗尽集群资源 | 防止容器未声明资源导致调度异常 |
| Helm 模板化 | 通过 .Values.quota 控制总量阈值 |
通过 .Values.limits 控制默认值与边界 |
最佳实践:ResourceQuota 与 LimitRange 必须成对部署。仅设置 Quota 而不设 LimitRange,会导致未声明资源的 Pod 被拒绝;仅设 LimitRange 而不设 Quota,则无法防止命名空间整体资源超卖。
4.2 在 templates/ 中编写 ResourceQuota YAML
以下是一个标准的 ResourceQuota 模板文件 templates/resourcequota.yaml,通过 .Values.quota 动态注入所有阈值:
apiVersion: v1
kind: ResourceQuota
metadata:
name: {{ include "myapp.fullname" . }}-quota
namespace: {{ .Release.Namespace }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
hard:
requests.cpu: {{ .Values.quota.requestsCpu | default "4" | quote }}
requests.memory: {{ .Values.quota.requestsMemory | default "8Gi" | quote }}
limits.cpu: {{ .Values.quota.limitsCpu | default "8" | quote }}
limits.memory: {{ .Values.quota.limitsMemory | default "16Gi" | quote }}
persistentvolumeclaims: {{ .Values.quota.pvcCount | default "10" }}
pods: {{ .Values.quota.podCount | default "50" }}
count/deployments.apps: {{ .Values.quota.deploymentCount | default "10" }}
count/services: {{ .Values.quota.serviceCount | default "10" }}
关键设计点:
- 使用
include "myapp.fullname" .保证资源名称唯一,避免多 Release 冲突。 - 所有数值型字段通过
default函数提供安全默认值,防止 values.yaml 未定义时模板渲染失败。 requests.cpu等字段使用quote转换为字符串,符合 Kubernetes API 规范。- 对象计数(pods、deployments、services)使用整数类型,无需
quote。
4.3 在 templates/ 中编写 LimitRange YAML
LimitRange 模板 templates/limitrange.yaml 用于约束单个容器的资源声明范围:
apiVersion: v1
kind: LimitRange
metadata:
name: {{ include "myapp.fullname" . }}-limits
namespace: {{ .Release.Namespace }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
limits:
- type: Container
default:
cpu: {{ .Values.limits.defaultCpu | default "500m" | quote }}
memory: {{ .Values.limits.defaultMemory | default "512Mi" | quote }}
defaultRequest:
cpu: {{ .Values.limits.defaultRequestCpu | default "100m" | quote }}
memory: {{ .Values.limits.defaultRequestMemory | default "128Mi" | quote }}
max:
cpu: {{ .Values.limits.maxCpu | default "2" | quote }}
memory: {{ .Values.limits.maxMemory | default "2Gi" | quote }}
min:
cpu: {{ .Values.limits.minCpu | default "50m" | quote }}
memory: {{ .Values.limits.minMemory | default "64Mi" | quote }}
注意:LimitRange 的
default 与 defaultRequest 必须同时设置。如果只设 default 而不设 defaultRequest,Kubernetes 会将 default 的值同时作为 request 使用,可能导致资源预留过高。建议始终显式声明两者。
4.4 通过 Values 动态控制配额
在 values.yaml 中定义完整的配额与限制结构,支持多环境覆盖:
# values.yaml — 默认开发环境配置
quota:
requestsCpu: "4"
requestsMemory: "8Gi"
limitsCpu: "8"
limitsMemory: "16Gi"
pvcCount: 10
podCount: 50
deploymentCount: 10
serviceCount: 10
limits:
defaultCpu: "500m"
defaultMemory: "512Mi"
defaultRequestCpu: "100m"
defaultRequestMemory: "128Mi"
maxCpu: "2"
maxMemory: "2Gi"
minCpu: "50m"
minMemory: "64Mi"
生产环境覆盖文件 values-production.yaml:
# values-production.yaml
quota:
requestsCpu: "16"
requestsMemory: "64Gi"
limitsCpu: "32"
limitsMemory: "128Gi"
podCount: 200
deploymentCount: 50
limits:
maxCpu: "8"
maxMemory: "8Gi"
minCpu: "100m"
minMemory: "128Mi"
部署时通过 -f 参数加载环境特定配置:
helm install myapp ./myapp-chart -f values-production.yaml --namespace production
4.5 资源配额与网络拓扑的协同关系
在 Cilium 网络拓扑中,ResourceQuota 与 LimitRange 直接影响 Pod 的 QoS 等级与网络带宽分配。下图展示了配额、限制与 Cilium 网络策略的协同工作流:
4.6 多环境配额策略对比
| 环境 | CPU 请求总量 | 内存请求总量 | Pod 上限 | 单容器最大 CPU | QoS 策略 |
|---|---|---|---|---|---|
| 开发 (dev) | 4 核 | 8 Gi | 50 | 2 核 | Burstable(默认) |
| 测试 (test) | 8 核 | 16 Gi | 100 | 4 核 | Burstable + 部分 Guaranteed |
| 预发 (staging) | 16 核 | 32 Gi | 150 | 4 核 | Guaranteed(核心服务) |
| 生产 (prod) | 32 核 | 128 Gi | 200 | 8 核 | Guaranteed(全部服务) |
性能调优提示:当 LimitRange 设置
request.cpu == limit.cpu 且 request.memory == limit.memory 时,Pod 的 QoS 等级为 Guaranteed。Cilium 的 eBPF 带宽管理器会为 Guaranteed Pod 分配独立的带宽预算,避免 Burstable/BestEffort Pod 的流量争抢。在生产环境中,建议将核心业务 Pod 的 request 与 limit 设置为相等值。
4.7 验证配额生效的 Helm 测试钩子
在 Chart 的 templates/tests/ 目录下添加测试 Pod,验证 ResourceQuota 与 LimitRange 是否正确加载:
# templates/tests/test-quota.yaml
apiVersion: v1
kind: Pod
metadata:
name: {{ include "myapp.fullname" . }}-quota-test
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": hook-succeeded
spec:
containers:
- name: quota-check
image: bitnami/kubectl:latest
command:
- sh
- -c
- |
echo "=== ResourceQuota ==="
kubectl get resourcequota -n {{ .Release.Namespace }}
echo "=== LimitRange ==="
kubectl get limitrange -n {{ .Release.Namespace }}
echo "=== Pod QoS Check ==="
kubectl get pod -n {{ .Release.Namespace }} -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.qosClass}{"\n"}{end}'
restartPolicy: Never
执行 helm test myapp -n production 即可自动运行上述验证,输出配额与 QoS 状态。
4.8 常见错误与排障
- 错误:
failed to create resource quota: the server could not find the requested resource— 检查 Kubernetes 版本是否支持 ResourceQuota(v1.0+ 均支持)。 - 错误:
exceeded quota: myapp-quota, requested: pods=1, used: pods=50, limited: pods=50— 命名空间 Pod 数量已达上限,需调整.Values.quota.podCount。 - 错误:
container has resource requests but no limit set, and no limit range exists— 未部署 LimitRange 或 LimitRange 未设置default字段。 - 错误:
LimitRange min memory > request memory— 容器声明的 request 小于 LimitRange 的min值,需调整 values 或容器声明。
生产环境警告:ResourceQuota 的
limits.cpu 与 limits.memory 必须大于或等于所有 Pod 的 limit 总和。如果设置过小,会导致部分 Pod 无法调度。建议在生产环境中预留 20% 的缓冲余量。