QoS 类别
学习目标
- 理解 Kubernetes 的三种 QoS 类别
- 掌握 QoS 类别的分配规则
- 了解 QoS 类别对 Pod 驱逐的影响
核心概念
一句话解释
QoS(Quality of Service)类别决定 Pod 在资源不足时的优先级,Guaranteed 最高,BestEffort 最低。
三种 QoS 类别
┌─────────────────────────────────────────────────────────┐
│ QoS 类别 │
├─────────────────────────────────────────────────────────┤
│ │
│ Guaranteed(保证) │
│ ┌─────────────────────────────────────────┐ │
│ │ 所有容器的 requests == limits │ │
│ │ 优先级:最高(最后被杀掉) │ │
│ │ 适用:关键业务、数据库 │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Burstable(可突发) │
│ ┌─────────────────────────────────────────┐ │
│ │ 至少一个容器 requests != limits │ │
│ │ 优先级:中等 │ │
│ │ 适用:大多数应用 │ │
│ └─────────────────────────────────────────┘ │
│ │
│ BestEffort(尽力而为) │
│ ┌─────────────────────────────────────────┐ │
│ │ 没有设置 requests 和 limits │ │
│ │ 优先级:最低(最先被杀掉) │ │
│ │ 适用:非关键、可中断任务 │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
分配规则
# Guaranteed: requests == limits
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "256Mi"
# Burstable: requests < limits(至少一个容器)
resources:
requests:
cpu: "250m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
# BestEffort: 不设置 requests 和 limits
resources: {}
# 或者不写 resources 字段
QoS 分配流程
┌─────────────────────────────────────────────────────────┐
│ QoS 分配逻辑 │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. 检查所有容器 │
│ │ │
│ v │
│ 2. 是否所有容器都设置了 requests == limits? │
│ ├─ Yes → Guaranteed │
│ └─ No │
│ │ │
│ v │
│ 3. 是否有容器设置了 requests 或 limits? │
│ ├─ Yes → Burstable │
│ └─ No │
│ │ │
│ v │
│ 4. BestEffort │
│ │
└─────────────────────────────────────────────────────────┘
多容器 Pod 示例
# 示例 1: Guaranteed
apiVersion: v1
kind: Pod
metadata:
name: guaranteed-pod
spec:
containers:
- name: app
image: nginx
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "256Mi"
- name: sidecar
image: busybox
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "100m"
memory: "64Mi"
# 所有容器 requests == limits → Guaranteed
# 示例 2: Burstable
apiVersion: v1
kind: Pod
metadata:
name: burstable-pod
spec:
containers:
- name: app
image: nginx
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "512Mi"
- name: sidecar
image: busybox
# 没有设置 resources
# 至少一个容器 requests != limits → Burstable
驱逐优先级
┌─────────────────────────────────────────────────────────┐
│ 驱逐优先级 │
├─────────────────────────────────────────────────────────┤
│ │
│ 资源不足时(OOM 或 Node Pressure): │
│ │
│ 1. BestEffort Pod 最先被驱逐 │
│ └─ 没有资源保证,随时可以杀掉 │
│ │
│ 2. Burstable Pod 次之 │
│ └─ 超出 requests 的部分可以被回收 │
│ │
│ 3. Guaranteed Pod 最后被驱逐 │
│ └─ 有严格的资源保证 │
│ │
│ 同一 QoS 类别内,按 requests 比例驱逐 │
│ │
└─────────────────────────────────────────────────────────┘
OOM 评分
# Linux OOM Killer 评分
# 分数越高,越容易被杀掉
# Guaranteed Pod
# OOM 调整分数:-998(几乎不会被杀)
# Burstable Pod
# OOM 调整分数:根据 requests 计算
# requests 越小,分数越高,越容易被杀
# BestEffort Pod
# OOM 调整分数:1000(最容易被杀)
资源回收
┌─────────────────────────────────────────────────────────┐
│ 资源回收 │
├─────────────────────────────────────────────────────────┤
│ │
│ 场景:节点内存不足 │
│ │
│ 节点状态: │
│ - 总内存:8Gi │
│ - 已分配:7.5Gi │
│ - 可用:500Mi │
│ - 需要回收:1Gi │
│ │
│ Pod 列表: │
│ ┌─────────────┬──────────┬──────────┬─────────┐ │
│ │ Pod │ QoS │ requests │ limits │ │
│ ├─────────────┼──────────┼──────────┼─────────┤ │
│ │ besteffort │ BestEff. │ 0 │ 0 │ │
│ │ burstable-1 │ Burstable│ 256Mi │ 512Mi │ │
│ │ burstable-2 │ Burstable│ 512Mi │ 1Gi │ │
│ │ guaranteed │ Guarant. │ 512Mi │ 512Mi │ │
│ └─────────────┴──────────┴──────────┴─────────┘ │
│ │
│ 驱逐顺序: │
│ 1. besteffort(BestEffort) │
│ 2. burstable-1(Burstable,requests 较小) │
│ 3. burstable-2(Burstable,requests 较大) │
│ 4. guaranteed(Guaranteed,最后被驱逐) │
│ │
└─────────────────────────────────────────────────────────┘
实践练习
练习 1:创建不同 QoS 类别的 Pod
# qos-pods.yaml
apiVersion: v1
kind: Pod
metadata:
name: guaranteed-pod
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "256Mi"
---
apiVersion: v1
kind: Pod
metadata:
name: burstable-pod
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "250m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
---
apiVersion: v1
kind: Pod
metadata:
name: besteffort-pod
spec:
containers:
- name: nginx
image: nginx
kubectl apply -f qos-pods.yaml
# 查看 QoS 类别
kubectl get pods -o custom-columns=NAME:.metadata.name,QOS:.status.qosClass
练习 2:验证 QoS 分配
# 查看 Pod 详细信息
kubectl describe pod guaranteed-pod | grep -A 5 "QoS Class"
kubectl describe pod burstable-pod | grep -A 5 "QoS Class"
kubectl describe pod besteffort-pod | grep -A 5 "QoS Class"
练习 3:观察资源压力下的驱逐
# 创建多个 Pod 模拟资源压力
apiVersion: v1
kind: Pod
metadata:
name: besteffort-1
spec:
containers:
- name: stress
image: polinux/stress
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "256M"]
---
apiVersion: v1
kind: Pod
metadata:
name: burstable-1
spec:
containers:
- name: stress
image: polinux/stress
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "256M"]
resources:
requests:
memory: "128Mi"
limits:
memory: "256Mi"
kubectl apply -f eviction-test.yaml
# 观察 Pod 状态变化
kubectl get pods -w
# 在资源压力下,besteffort-1 会先被驱逐
练习 4:查看 OOM 评分
# 查看 Pod 的 OOM 评分
kubectl exec <pod-name> -- cat /proc/self/oom_score
# 查看所有进程的 OOM 评分
kubectl exec <pod-name> -- ps -eo pid,oom_score,comm
练习 5:使用 PriorityClass 影响驱逐
# 高优先级 Pod
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "High priority class"
---
apiVersion: v1
kind: Pod
metadata:
name: high-priority-pod
spec:
priorityClassName: high-priority
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "256Mi"
最佳实践
1. 关键业务使用 Guaranteed
- 数据库、核心服务
- 确保资源不被回收
2. 大多数应用使用 Burstable
- 允许突发使用资源
- 但有基本保证
3. 非关键任务使用 BestEffort
- 批处理任务
- 可以随时中断
4. 避免资源浪费
- 合理设置 requests
- 不要过度分配
5. 监控和调整
- 观察实际资源使用
- 根据需要调整 QoS 类别
常见问题
1. Pod 被意外驱逐
# 检查 Pod QoS 类别
kubectl get pod <pod-name> -o yaml | grep -A 5 qosClass
# 检查节点资源压力
kubectl describe node <node-name> | grep -A 10 "Conditions"
# 原因:可能是 BestEffort 或 Burstable Pod 在资源压力下被驱逐
2. 如何保证 Pod 不被驱逐
# 使用 Guaranteed QoS
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "256Mi"
# 使用高优先级 PriorityClass
priorityClassName: high-priority
3. QoS 类别可以手动设置吗?
# 不能手动设置
# QoS 类别由 requests 和 limits 自动决定
# 查看实际 QoS 类别
kubectl get pod <pod-name> -o jsonpath='{.status.qosClass}'
小结
| 要点 | 说明 |
|---|---|
| Guaranteed | requests == limits,最高优先级 |
| Burstable | requests < limits,中等优先级 |
| BestEffort | 无 requests/limits,最低优先级 |
| 驱逐顺序 | BestEffort → Burstable → Guaranteed |
| OOM 评分 | Guaranteed 最低,BestEffort 最高 |
| 使用场景 | 根据业务重要性选择 QoS 类别 |
练习编辑器
bash
Loading...