2. Kubernetes 资源模型:Pod 与 Container 的资源请求与限制
在 Kubernetes 集群中,资源管理是性能调优与成本控制的核心。每个 Pod 和 Container 都需要明确声明其所需的计算资源(CPU 和内存),调度器才能做出合理的调度决策,kubelet 才能进行有效的资源回收与压制。本章深入解析资源请求(Requests)与限制(Limits)的语义,以及由此衍生的三种服务质量(QoS)等级。
2.1 资源请求(Requests)与限制(Limits)
Kubernetes 为每个容器定义了两种资源规格:Requests 和 Limits。它们分别代表“最低保障”和“最高上限”。
| 属性 | 语义 | 调度依据 | CPU 特性 | 内存特性 |
|---|---|---|---|---|
| Requests | 容器启动所需的最小资源保证 | 调度器根据 Node 剩余可分配资源进行调度 | 作为 CPU 共享调度权重(CFS quota) | 作为内存预留,不会被回收 |
| Limits | 容器允许使用的资源硬上限 | 不参与调度决策 | 超过时会被限流(throttle) | 超过时容器会被 OOM Kill |
关键区别: CPU 是可压缩资源,超限只会导致性能下降;内存是不可压缩资源,超限直接导致容器重启。生产环境中,务必为内存设置合理的 Limits。
2.2 资源单位与配置示例
CPU 资源以 cores 为单位,支持小数(如 0.5)和整数(如 2)。内存资源以 字节 为单位,常用后缀包括 Mi(Mebibytes)、Gi(Gibibytes)。
apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: app
image: nginx:latest
resources:
requests:
cpu: "500m" # 0.5 核
memory: "256Mi" # 256 Mebibytes
limits:
cpu: "1000m" # 1 核
memory: "512Mi" # 512 Mebibytes
常见陷阱: 如果只设置 Limits 而不设置 Requests,Kubernetes 会自动将 Requests 设置为与 Limits 相同的值。这可能导致资源预留过高,降低集群利用率。
2.3 QoS 等级:Guaranteed、Burstable、BestEffort
Kubernetes 根据 Pod 中所有容器的 Requests 和 Limits 配置,自动将 Pod 划分为三种 QoS 等级。等级决定了在节点资源紧张时,哪些 Pod 优先被驱逐。
| QoS 等级 | 配置条件 | 资源保障 | 驱逐优先级 | 典型场景 |
|---|---|---|---|---|
| Guaranteed | 所有容器:Requests == Limits(CPU 和内存) | 最高 | 最低(最后被驱逐) | 数据库、关键中间件 |
| Burstable | 至少一个容器:Requests < Limits | 中等 | 中等 | Web 服务、批处理任务 |
| BestEffort | 所有容器:未设置 Requests 和 Limits | 最低 | 最高(最先被驱逐) | 非关键测试、临时任务 |
性能调优建议: 对于延迟敏感型应用,应使用 Guaranteed 等级,确保 CPU 和内存不被抢占。对于吞吐型应用,Burstable 等级可以在资源空闲时获得更好的性能,同时允许一定的资源超卖。
2.4 QoS 等级与资源回收机制
当节点内存不足时,kubelet 的 OOM Killer 会根据 QoS 等级和 OOM 分数(oom_score)决定杀死哪些进程。OOM 分数由两部分组成:
- QoS 基础分: BestEffort 最高,Guaranteed 最低。
- 内存使用率: 实际使用内存占 Requests 的比例越高,分数越高。
这意味着:即使两个 Pod 同属 Burstable 等级,内存使用率更高的 Pod 会先被杀死。
# 查看 Pod 的 QoS 等级
kubectl get pod <pod-name> -o jsonpath='{.status.qosClass}'
2.5 资源模型与调度决策
调度器(kube-scheduler)在调度 Pod 时,只检查 Node 的 已分配 Requests 总和 是否超过 Node 的 可分配资源。Limits 不参与调度决策,但会影响节点上的实际资源竞争。
2.6 实战:合理配置资源配额
在命名空间级别,可以通过 ResourceQuota 限制资源总量,防止单个团队或应用过度消耗集群资源。
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"
pods: "50"
最佳实践: 在创建 ResourceQuota 时,建议同时设置 Requests 和 Limits 的配额。如果只设置 Limits 配额,用户可能不设置 Requests,导致调度器无法准确评估资源需求。
2.7 性能调优:Requests 与 Limits 的黄金比例
根据实际生产经验,不同场景下的 Requests/Limits 比例建议如下:
| 应用类型 | CPU Requests/Limits 比例 | 内存 Requests/Limits 比例 | 推荐 QoS | 说明 |
|---|---|---|---|---|
| 延迟敏感型(如 Redis、Kafka) | 1:1 | 1:1 | Guaranteed | 避免 CPU 限流和 OOM |
| 吞吐型(如 Web 服务) | 1:2 ~ 1:4 | 1:1.5 ~ 1:2 | Burstable | 允许突发流量,提高资源利用率 |
| 批处理/离线任务 | 1:1 ~ 1:2 | 1:1 | Burstable | 避免内存超限导致任务失败 |
| 非关键测试 | 不设置 | 不设置 | BestEffort | 利用空闲资源,随时可被驱逐 |
性能优化核心原则: Requests 保证稳定性,Limits 控制爆炸半径。在资源充足时,适当提高 Limits 可以提升性能;在资源紧张时,合理的 Requests 可以保障关键服务的正常运行。