Kubernetes QoS服务质量与资源配额管理

Kubernetes QoS服务质量与资源配额管理

_

一、Kubernetes资源分类

1. 资源类型

Kubernetes默认存在两类基本资源:CPU和Memory。

1.1 CPU

在Kubernetes中,CPU资源拥有统一标准计量单位,称为Kubernetes计算单元,大致等同于x86处理器的单个超线程核心。CPU本质分配的CPU运行时间,因此使用毫核(millicores)作为基础单元,1个CPU核心=1000毫核。

1.2 Memory

内存的请求与限制以字节作为基础单位,支持两种格式标识:一种是十进制单位T、G、M、K;一种是二进制单位Ti、Gi、Mi、Ki。

100M:100x1000x1000字节
100Mi:100x1024x1024字节

2. 可压缩与不可压缩资源

Kubernetes中资源可以分为两类:可压缩与不可压缩资源。

2.1 CPU属于可压缩资源

CPU资源不足时,系统可以减少分配给各个业务进程的CPU时间片,以此腾出算力。业务运行速度会降低、响应延迟变大,但进程不会直接终止,仍然能够持续运行。该特性得益于CPU属于时间分片类的无状态资源。

2.2 内存与本地存储属于不可压缩资源

内存、磁盘存储空间一旦分配给Pod使用,在Pod退出销毁前,无法自动回收分配出去的资源。这类资源没有办法通过“降速”实现资源腾挪。一旦资源使用超出限额,会触发OOM机制或节点资源压力驱逐,相关Pod进程会被终止。

3. 节点资源

执行“kubectl describe node”命令可以查看节点详细信息,其中两个关键资源字段含义如下所示:

  • Capacity(资源总容量):代表节点硬件具备的物理资源总量,是服务器原生拥有的CPU、内存等资源上限。

  • Allocatable(可分配资源):代表节点能够提供给Pod使用的可用资源,系统会预留一部分资源供节点组件(kubelet、容器运行时、操作系统等)使用,因此Allocatable数值通常小于Capacity。

日常分析重点关注CPU与内存两项资源,节点信息显示拥有2个CPU,这里的CPU数量实际对应处理器超线程。内存显示约4GB,代表节点可供给容器调度使用的内存规模。调度器判断节点资源是否充足时,依据Allocatable的值来进行计算,而非Capacity。

root@k8s-master:~# kubectl describe node k8s-worker2

4. 定义资源的使用

在Kubernetes中,Pod的资源配置以容器为最小单位。可以为Pod内每一个容器单独配置requests与limits,定义容器期望占用的资源规格。

4.1 request(资源请求)

request代表容器运行时希望保障获得的最小资源数量。调度器在预选阶段进行校验,只有节点剩余可分配资源大于容器的request,Pod才允许被调度到该节点。

4.2 limit(资源上限)

limit用来设定容器能够使用CPU、内存资源的最大值:

  • CPU:一旦容器占用超出limit,操作系统内核会对容器进行限流,容器运行速度变慢,但不会被终止;

  • 内存:一旦容器内存占用超过limit,容器进程会触发OOMKill,容器被杀死,控制器通常会重启容器。

二、QoS原理与使用

1. QoS概述

Kubernetes集群中会运行大量容器,当容器规模持续增长、节点负载不断升高时,极易出现资源耗尽的局面。因此集群需要一套管控机制,保障核心容器能够获取充足资源,必要时可以终止部分优先级较低的容器释放资源。

QoS(Quality of Service,服务质量)是Kubernetes用来区分Pod资源优先级的机制。当节点资源紧张时(CPU、内存不足),kubelet依据QoS类别决定Pod的调度顺序、OOM驱逐先后顺序,保障重要业务优先获取资源。

2. Pod QoS分类

Kubernetes允许用户通过“requests”和“limits”字段为容器配置资源申请信息。系统会依据Pod内部所有容器的资源配置情况,自动将Pod划分为三种QoS服务质量等级,优先级从高到低依次为:Guaranteed>Burstable>BestEffort。

  • Guaranteed:保障型

  • Burstable:弹性/爆发型

  • BestEffort:尽力服务型

3. Guaranteed(保障型)

Guaranteed是Kubernetes QoS等级中优先级最高的类别,如果要让Pod的QoS等级为Guaranteed,需要同时满足以下全部条件。部署这类Pod时,管理员能够精准预估业务所需资源上限,方便开展集群资源规划。当节点内存资源紧张触发驱逐策略时,该类Pod会最后才被终止,最大程度保障核心业务稳定运行。

  • Pod内每一个容器都需要配置内存“requests”和“limits”,并且内存“requests”和“limits”的值相等。

  • Pod内每一个容器都需要配置CPU“requests”和“limits”,并且CPU“requests”和“limits”的值相等。

  • 要求Pod内部所有容器都满足上述规则,只要有任意一个容器不满足条件,整个Pod都无法判定为Guaranteed类型。

4. Burstable(弹性/爆发型)

Burstable优先级仅次于Guaranteed,高于BestEffort,属于中间等级。管理员能够明确知道该Pod运行时所需的最低资源规格(requests),同时在节点充裕时,允许业务占用更多空闲资源,因此通常配置limits>requests,支撑业务应对流量峰值。资源紧张触发驱逐时,集群会优先清理BestEffort类型的Pod,若资源仍然不足,再考虑驱逐Burstable类型的Pod。 满足下列两项条件时,Pod的QoS等级判定为Burstable:

  • 该Pod无法达到Guaranteed的配置标准;

  • Pod内至少存在一个容器配置了CPU或内存的requests资源请求。 通俗一点说,只要Pod内存在至少一个容器设置了CPU和内存的requests,同时达不到Guaranteed标准,Pod即为Burstable。

5. BestEffort(尽力服务型)

当Pod内所有容器均未配置CPU、内存的“requests”资源请求与“limits”资源限制时,该Pod的QoS等级为BestEffort。

BestEffort等级的Pod拥有三类QoS中的最低等级。节点资源充裕时,这类Pod可以充分占用集群空闲资源。当节点资源紧张,Guaranteed和Burstable类型的Pod需要资源时,BestEffort Pod没有资源保护机制,资源会被抢占、持续压缩。一旦内存压力达到阈值,kubelet会首先驱逐BestEffort类型的Pod,优先保障最高优先级业务稳定运行。

三、QoS案例配置

1. 创建Guaranteed类型的Pod

[Step1] 本地新建YAML清单,定义Pod资源描述模板。

root@k8s-master:~# vim guaranteed-pod.yml
​
# 写入下列内容
apiVersion: v1      # 固定配置
kind: Pod           # 资源类型
metadata:
  name: guaranteed-pod
spec:
  containers:
    - name: guaranteed-pod
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["sleep","1000"]
      # 配置容器资源限额,包含requests和limits两类子项
      resources:
        limits:             # 资源使用硬上限,限制容器最大可用硬件资源,防止容器耗尽节点资源
          memory: "200Mi"   # 内存最大使用上限200Mi,容器内存占用超过该值会触发OOM被直接终止
          cpu: "700m"       # CPU最大使用上限700毫核,容器CPU占用超出上限会被系统节流降频,不会杀死容器
        requests:           # 资源申请配额,集群调度器分配节点资源的判断依据
          memory: "200Mi"   # 申请内存200Mi,调度器会预留200Mi内存供容器使用
          cpu: "700m"       # 申请CPU 700毫核(0.7核),调度时预留0.7核CPU资源

[Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f guaranteed-pod.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的详细信息。

root@k8s-master:~# kubectl get -f guaranteed-pod.yml

[Step4] 验证:查看guaranteed-pod的详细信息,过滤“QoS Class”字段,可以看到该Pod对应的QoS等级。

root@k8s-master:~# kubectl describe pod guaranteed-pod | grep "QoS Class"

2. 创建Burstable类型的Pod

[Step1] 本地新建YAML清单,定义Pod资源描述模板。

root@k8s-master:~# vim burstable-pod.yml
​
# 写入下列内容
apiVersion: v1      # 固定配置
kind: Pod           # 资源类型
metadata:
  name: burstable-pod
spec:
  containers:
    - name: burstable-pod
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["sleep","1000"]
      # 配置容器资源限额,包含requests和limits两类子项
      resources:
        limits:             # 资源使用硬上限,限制容器最大可用硬件资源,防止容器耗尽节点资源
          memory: "200Mi"   # 内存最大使用上限200Mi,容器内存占用超过该值会触发OOM被直接终止
        requests:           # 资源申请配额,集群调度器分配节点资源的判断依据
          memory: "100Mi"   # 申请内存100Mi,调度器会预留100Mi内存供容器使用

[Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f burstable-pod.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的详细信息。

root@k8s-master:~# kubectl get -f burstable-pod.yml

[Step4] 验证:查看burstable-pod的详细信息,过滤“QoS Class”字段,可以看到该Pod对应的QoS等级。

root@k8s-master:~# kubectl describe pod burstable-pod | grep "QoS Class"

3. 创建BestEffort类型的Pod

[Step1] 本地新建YAML清单,定义Pod资源描述模板。

root@k8s-master:~# vim besteffort-pod.yml

# 写入下列内容
apiVersion: v1		# 固定配置
kind: Pod			# 资源类型
metadata:
  name: besteffort-pod
spec:
  containers:
    - name: besteffort-pod
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["sleep","1000"]

[Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f besteffort-pod.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的详细信息。

root@k8s-master:~# kubectl get -f besteffort-pod.yml

[Step4] 验证:查看burstable-pod的详细信息,过滤“QoS Class”字段,可以看到该Pod对应的QoS等级。

root@k8s-master:~# kubectl describe pod besteffort-pod | grep "QoS Class"

4. 超出容器的内存限制

[Step1] 本地新建YAML清单,定义Pod资源描述模板。使用stress容器测试Kubernetes在容器时使用超过限制值的表现。设置容器的限额为100Mi,但是实际运行使用150Mi。

root@k8s-master:~# vim rocky-stress-ng.yml

# 写入下列内容
apiVersion: v1		# 固定配置
kind: Pod			# 资源类型
metadata:
  name: rocky-stress-ng
spec:
  containers:
    - name: rocky-stress-ng
      image: rockylinux:8.9
      imagePullPolicy: IfNotPresent
      # 配置容器资源限额,包含requests和limits两类子项
      resources:
        limits:		# 资源使用硬上限,限制容器最大可用硬件资源,防止容器耗尽节点资源
          # 内存需要设置多一点,否则dnf下载会卡住
          memory: "500Mi"	# 内存最大使用上限500Mi,容器内存占用超过该值会触发OOM被直接终止
        requests:	# 资源申请配额,集群调度器分配节点资源的判断依据
          memory: "400Mi"	# 申请内存400Mi,调度器会预留400Mi内存供容器使用
      command: ["/bin/bash","-c"]
      args:
        - "sleep 3600"

[Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f rocky-stress-ng.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的详细信息。

root@k8s-master:~# kubectl get -f rocky-stress-ng.yml

[Step4] 验证:登录容器,进入交互式终端。在线安装stress-ng,随后执行stress-ng命令反复读写内存页面。

root@k8s-master:~# kubectl exec -it rocky-stress-ng -- bash
[root@rocky-stress-ng /]# dnf install -y stress-ng
[root@rocky-stress-ng /]# stress-ng --vm 1 --vm-bytes 550M --vm-hang 3600 --vm-rw 1000
  • --vm 1:启用vm压力工作进程,启动1个虚拟内存压力线程。

  • --vm-bytes 550M:每个vm工作进程分配550MB内存

  • --vm-hang 3600:内存分配完成后,持久内存3600秒不释放,模拟长期内存占用/内存泄漏场景

  • --vm-rw 1000:分配内存后,循环读写内存页面1000次

[Step5] 此时交互式终端回显运行信息后会进入无响应状态,随后连接断开,进程退出代码为137。

[root@rocky-stress-ng /]# stress-ng --vm 1 --vm-bytes 550M --vm-hang 3600 --vm-rw 1000

[Step6] 验证:查看rocky-stress-ng详情并提取“Last State”相关信息,可以看到容器终止原因为“OOMKilled”,退出代码为137。

root@k8s-master:~# kubectl describe pod rocky-stress-ng  | grep -A 2 "Last State"

[Step7] 验证:重新查看Pod状态,容器依旧显示为Running。原因是容器进程终止后Kubernetes自动重启容器,可以看到当前重启次数为1。

root@k8s-master:~# kubectl get -f rocky-stress-ng.yml

5. 超出节点可用资源

[Step1] 本地新建YAML清单,定义Pod资源描述模板。集群中k8s-worker1和k8s-worker2节点的内存为2G,创建Guaranteed类型的Pod,为容器设置内存请求与上限均未10G。

root@k8s-master:~# vim memory-busybox-pod.yml

# 写入下列内容
apiVersion: v1		# 固定配置
kind: Pod			# 资源类型
metadata:
  name: memory-busybox-pod
spec:
  containers:
    - name: memory-busybox-pod
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      # 配置容器资源限额,包含requests和limits两类子项
      resources:
        limits:		# 资源使用硬上限,限制容器最大可用硬件资源,防止容器耗尽节点资源
          memory: "10Gi"	# 内存最大使用上限10Gi,容器内存占用超过该值会触发OOM被直接终止
        requests:	# 资源申请配额,集群调度器分配节点资源的判断依据
          memory: "10Gi"	# 申请内存10Gi,调度器会预留10Gi内存供容器使用
      command: ["sleep","1000"]

[Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f memory-busybox-pod.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的状态信息,可以看到Pod会处于Pending状态。

root@k8s-master:~# kubectl get -f memory-busybox-pod.yml

[Step4] 验证:查看memory-busybox-pod的详细信息,由于节点内存无法满足Pod的内存申请,调度器会提示内存不足。

root@k8s-master:~# kubectl describe pod memory-busybox-pod | grep -A 3 Events

Kubernetes Helm 基础操作 2026-10-29
Kubernetes 监控组件与Metrics Server、HPA配置 2026-10-30

评论区