2. Kubernetes资源模型与容量抽象:Pod、Node、ResourceQuota、LimitRange的容量语义
在容量规划中,Kubernetes 的资源模型是理解集群“能装多少、还剩多少”的基础。Pod、Node、ResourceQuota、LimitRange 这四个对象分别从微观请求、宏观容量、配额边界和默认约束四个维度定义了容量语义。只有准确理解这些原语的数学关系,才能设计出合理的 Kyverno/OPA 策略。
2.1 核心容量原语:Pod 与 Node
Pod 是 Kubernetes 中最小的调度单元,其资源声明直接决定了 Node 的容量消耗。Node 则是集群的物理/虚拟计算节点,其可分配容量是调度决策的硬边界。
| 原语 | 容量语义 | 关键字段 | 规划影响 |
|---|---|---|---|
| Pod | 资源请求(requests)与限制(limits) | spec.containers[].resources.requests.cpu/memoryspec.containers[].resources.limits.cpu/memory |
决定调度时的“承诺容量”与运行时的“突发上限” |
| Node | 总容量减去系统预留后的可分配容量 | status.allocatable.cpu/memory |
决定集群实际可调度 Pod 的总和上限 |
| Node | 节点压力驱逐阈值 | --eviction-hard / --eviction-soft |
触发 Pod 驱逐的剩余容量警戒线 |
容量规划要点: 调度器只检查 Pod 的
requests 总和是否超过 Node 的 allocatable;limits 仅用于运行时 CPU 限流和 OOM 判定。因此,requests 是容量规划的第一性原理。
2.2 容量抽象层:ResourceQuota 与 LimitRange
ResourceQuota 为命名空间级别的容量上限提供硬约束,LimitRange 则为单个 Pod/Container 设置默认值和范围。两者共同构成了多租户环境下的容量治理骨架。
2.2.1 ResourceQuota:命名空间容量天花板
ResourceQuota 定义了命名空间内所有 Pod 的资源请求总和上限。当配额耗尽时,后续 Pod 创建将被 API Server 拒绝。
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
persistentvolumeclaims: "5"
pods: "50"
容量语义: ResourceQuota 的
hard 字段是上限,而非预留。即使命名空间内实际使用量远低于配额,其他命名空间也无法借用。这要求容量规划时必须为每个命名空间预留足够的“安全余量”。
2.2.2 LimitRange:默认值与边界约束
LimitRange 为未显式声明资源请求/限制的 Pod 注入默认值,并强制约束单个容器的资源范围。它防止了“无限制”容器意外耗尽节点容量。
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: team-a
spec:
limits:
- default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "200m"
memory: "256Mi"
max:
cpu: "2"
memory: "4Gi"
min:
cpu: "50m"
memory: "64Mi"
type: Container
| LimitRange 字段 | 容量语义 | 违反后果 |
|---|---|---|
default |
未设置 limits 时的默认上限 | 自动注入,不拒绝 |
defaultRequest |
未设置 requests 时的默认请求值 | 自动注入,不拒绝 |
max |
单个容器的资源上限 | 超出则拒绝创建 |
min |
单个容器的资源下限 | 低于则拒绝创建 |
2.3 容量语义关系图
下图展示了从 Node 物理容量到 Pod 资源声明的完整抽象链路,以及 ResourceQuota 和 LimitRange 在其中的拦截位置。
2.4 容量语义在策略中的映射
Kyverno 和 OPA 在编写资源校验规则时,必须准确理解上述原语的容量语义。以下表格总结了常见策略场景与对应的容量抽象关系:
| 策略场景 | 涉及原语 | 容量语义校验逻辑 | 典型规则示例 |
|---|---|---|---|
| 禁止 requests 为 0 | Pod | requests 是调度承诺,为 0 会导致节点过载 | requests.cpu > 0 |
| 限制 limits/requests 比例 | Pod | 防止 limits 远大于 requests 造成突发超卖 | limits.cpu / requests.cpu ≤ 3 |
| 命名空间总配额校验 | ResourceQuota | 确保命名空间 requests 总和不超过 Quota | sum(requests) ≤ quota.hard |
| 强制设置默认 limits | LimitRange | 未设置 limits 的 Pod 使用默认值 | default.limits.cpu = "500m" |
| 节点可分配容量预警 | Node | 监控 allocatable 余量,低于阈值时告警 | allocatable - sum(requests) < 10% |
常见误区: 很多策略只校验
limits 而忽略 requests。实际上,requests 决定了调度可行性,而 limits 只影响运行时行为。容量规划策略应优先关注 requests 的合理性与配额匹配度。
2.5 容量抽象与策略协同总结
从容量规划视角看,Kubernetes 的资源模型形成了一个清晰的抽象栈:
- 物理层: Node 的 capacity 和 allocatable 定义了集群的容量天花板。
- 配额层: ResourceQuota 在命名空间级别划分容量池,防止单个团队耗尽集群。
- 约束层: LimitRange 为单个容器设置默认值和边界,避免“无限制”容器破坏容量规划。
- 声明层: Pod 的 requests/limits 是容量消耗的最小单元,也是策略校验的核心对象。