资源请求限制与 QoS
不写资源约束的容器会挤占整台节点,一个吃内存的应用可能拖垮同节点的其他 Pod。requests 与 limits 让 Kubernetes 知道每个容器「至少要多少、最多能用多少」,据此完成调度与运行期限制,是集群稳定运行的前提。
requests 与 limits 的语义
- requests:调度依据,节点必须能凑够所有 Pod 的 requests 才会被选中。
- limits:运行上限,容器实际使用超过 limits 会被限制或杀掉。
spec:
containers:
- name: app
image: myapp:1.0
resources:
requests:
cpu: 100m # 100 毫核 = 0.1 核
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
单位换算注意:CPU 以核为单位,1000m = 1 核;内存 Mi/Gi 是二进制单位(1Gi = 1024Mi),M/G 是十进制(1G = 1000M),二者不要混用。
超卖与驱逐
调度只看 requests:只要节点上 requests 之和未超,即使实际占用可能超卖也会调度。当节点内存不足时,kubelet 会按优先级驱逐 Pod,保障节点存活。
QoS 三档
requests 与 limits 的写法决定 Pod 的 QoS 等级,等级越低越先被驱逐:
| QoS 等级 | 判定条件 | 说明 |
|---|---|---|
| Guaranteed | 每个容器 requests == limits 且都写了 | 最高保障 |
| Burstable | 写了 requests 但未到 Guaranteed | 常见默认档 |
| BestEffort | 完全没写 requests/limits | 最先被驱逐 |
kubectl get pod xxx -o jsonpath='{.status.qosClass}'
# 输出:Burstable
OOMKilled 现象
容器实际内存超过 limits 时会被内核 OOM 杀掉并重启,典型现象:
kubectl describe pod xxx
# 输出:Last State: Terminated Reason: OOMKilled
kubectl logs xxx --previous # 查看被杀前日志
OOMKilled 通常说明内存 limits 小于真实需求,或应用存在内存泄漏,应先调大 limits(或加内存上限监控),再配合优化应用。
LimitRange 兜底默认值
团队里常有人忘记写资源,LimitRange 可在命名空间层面兜底:给未声明的容器补默认值,也可强制必须声明:
apiVersion: v1
kind: LimitRange
metadata:
name: ns-default
spec:
limits:
- type: Container
default: # 没写 limits 时套用
cpu: 500m
memory: 256Mi
defaultRequest: # 没写 requests 时套用
cpu: 100m
memory: 128Mi
小结:requests 决定调度、limits 决定上限,CPU 用核/毫核、内存用二进制单位;QoS 由 requests/limits 关系决定,BestEffort 最先被驱逐;OOMKilled 多为内存 limits 偏小,LimitRange 可统一规范命名空间内的资源写法。