资源请求限制与 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 可统一规范命名空间内的资源写法。

笔记加载中…