一、K8S中的应用服务质量(QoS)

服务质量(QoS)类是Kubernetes的概念,它确定Pod的调度和驱逐优先级

Kubelet使用它来管理驱逐pod的顺序,以及使用高级CPU管理策略允许更复杂的pod调度决策。

QoS由Kubernetes本身分配给Pod。但是,DevOps可以通过处理Pod内各个容器的资源请求和限制来控制分配给容器的QoS类。

二、QoS级别

  • Guaranteed:POD中所有容器(包含初始化容器)都必须统一设置了limits,并且设置参数都一致;
  • Burstable:POD中有容器设置了内存或CPU的requests;
  • BestEffort:POD中的所有容器都没有指定CPU和内存的requests和limits;

2.1 Guaranteed

对于 QoS 类为 Guaranteed 的 Pod:

  • Pod 中的每个容器,包含初始化容器,必须指定内存请求和内存限制,并且两者要相等。
  • Pod 中的每个容器,包含初始化容器,必须指定CPU请求和CPU限制,并且两者要相等。
# 创建pod模板
[root@master01 1]# k run qos-demo1 --image=registry.cn-hangzhou.aliyuncs.com/abroad_images/nginx:1.21.6  --dry-run=client -oyaml > qos-demo1.yaml

# 定义yaml文件
[root@master01 1]# vim  qos-demo1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo1
  namespace: study
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6
    name: qos-demo1
    resources:
      limits:
        memory: "500Mi"
        cpu: "700m"
      requests:
        memory: "500Mi"
        cpu: "700m"

# 应用
[root@master01 1]# kaf qos-demo1.yaml

# 验证
kubectl describe po qos-demo2 -nstudy | grep "QoS Class:"
QoS Class:                   Guaranteed

# 环境复原
[root@master01 1]# k delete -f qos-demo1.yaml

注意点:

如果容器指定了自己的内存limits,但没有指定内存requestskubernetes会自动为它指定与内存limits匹配的内存requests。同样,如果容器指定了自己的CPU limits,但没有 指定CPU requestsKubernetes 会自动为它指定与CPU limits匹配的 CPU requests

2.2 Burstable

如果满足下面条件,将会指定 Pod 的 QoS 类为 Burstable:

  • Pod 不符合 Guaranteed QoS 类的标准;
  • Pod 中至少一个容器具有内存 CPU requests;
# 创建pod模板
[root@master01 1]# k run qos-demo2 --image=registry.cn-hangzhou.aliyuncs.com/abroad_images/nginx:1.21.6  --dry-run=client -oyaml > qos-demo2.yaml

# 定义yaml文件
[root@master01 1]# vim  qos-demo2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo2
  namespace: study
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6
    name: qos-demo2
    resources:
      limits:
        memory: "500Mi"
      requests:
        memory: "200Mi"

# 应用
[root@master01 1]# kaf qos-demo2.yaml

# 验证
[root@master01 1]# kubectl describe po qos-demo2 -nstudy | grep "QoS Class:"
QoS Class:                   Burstable

# 环境复原
[root@master01 1]# k delete -f qos-demo2.yaml

2.3 BestEffort

对于 QoS 类为 BestEffort 的 Pod,Pod 中的容器必须没有设置内存和 CPU 限制或请 求。

# 创建pod模板
[root@master01 1]# k run qos-demo3 --image=registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6  --dry-run=client -oyaml > qos-demo3.yaml

# 定义yaml文件
[root@master01 1]# vim  qos-demo3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo3
  namespace: study
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6
    name: qos-demo3

# 应用
[root@master01 1]# kaf qos-demo3.yaml

# 验证
[root@master01 1]# kubectl describe po qos-demo3 -nstudy | grep "QoS Class:"
QoS Class:                   BestEffort

# 环境复原
[root@master01 1]# k delete -f qos-demo3.yaml

三、QoS优先级

3种QoS优先级从有低到高(从左向右):

BestEffort pods -> Burstable pods -> Guaranteed pods

四、驱逐原理

可压缩资源:CPU

在压缩资源部分已经提到CPU属于可压缩资源,当pod使用超过设置的limits值,pod中 进程使用cpu会被限制,但不会被kill。

不可压缩资源:内存

4.1 节点OOM时如何处理Guaranteed, Burstable 和 BestEffort Pods?

如果节点在Kubelet可以回收之前耗尽了内存,即节点发生了oom,则oom_killer会根据 其oom_score终止容器。

对于 “Guaranteed” Pod中的容器,oom_score_adj 为 “ -998”;

对于 “BestEffort” Pod中的容器,其为“ 1000”;

Burstable Pod中的容器,值为“ min(max(2,1000-(1000 * memoryRequestBytes)/ machineMemoryCapacityBytes),999” )”。

oom_killer首先终止QoS等级最低,且超过请求资源最多的容器。这意味着会优先从 Burstable中选择占用资源请求过多的容器进行驱逐;

五、最佳实践

  • 1、按照应用类型进行分类:核心应用(core)/ 常规应用(nomarl)/ 附加应用 (extral)

  • 2、核心应用:Guaranteed / 常规应用:Burstable / 附加应用:BestEffort

  • 3、集群节点分为:核心应用节点 / 常规应用节点 / 附加应用节点

  • 4、调度策略:

  • 核心应用:可以采用nodeAffinity的prefer调度策略调度到核心节点;

  • 常规应用:可以采用nodeAffinity的硬亲和调度策略调度到常规节点;

  • 附加应用:可以采用nodeAffinity的硬亲和调度策略调度到附加节点;