Kubernetes 配置Pod的服务质量(Qos)以及生产环境资源池规划;

文章目录

  • 一、Pod Qos类
  • 二、Qos可选类
    • 1.Guaranteed
    • 2.Burstable
    • 3.BestEffort
  • 三、节点压力时驱逐Pod Qos的顺序
  • `总结`


一、Pod Qos类

官方文档在此

服务质量(Quality of Service,Qos)类,kubernetes会基于每个Pod中容器的资源请求资源限制为Pod设置Qos类,然后kubernetes会根据Qos类来决定在遇到节点压力(没有足够可用资源)的时候从Node中驱逐哪些Pod;



二、Qos可选类

Qos可选类有Guaranteed、Burstable和BestEffort,当一个Node资源耗尽时,Kubernetes将首先驱逐在该Node上运行的BestEffort Pod,然后是Burstable Pod,最后是Guaranteed Pod;当这种驱逐是由资源压力引起时,只有超出资源请求的Pod才是被驱逐的候选对象;

  • Guaranteed:Guaranteed Pod具有最严格资源限制,并且最不可能面临驱逐。也就是 只有在这些Pod超过其自身的限制或者在Node抢占时优先级比别的Pod低,才会被杀死;这些Pod不可以获得超出指定limit的资源,这些Pod也可以使用static CPU管理策略来独占CPU;
  • Burstable:Burstable Pod有一些基于request的资源下限保证,但不需要特定的limit;如果未指定limit,则默认limit等于Node的容量,这允许Pod在资源可用时灵活地增加其资源。在Node资源压力导致Pod被驱逐时,只有在所有的BestEffort Pod被驱逐后这些Pod才会被驱逐。因为Burstable Pod可以包括没有资源limit或资源rquest的容器,所以Burstable Pod可以尝试使用任意数量的节点资源;
  • BestEffort :Qos类中的Pod可以使用未专门分配给其他Qos类中的Pod的节点资源。例如一个节点是16核CPU,并且已经将4核分配给了一个Guaranteed Pod,那么BestEffort Qos类中的Pod可以尝试任意使用剩下的12核CPU(如果节点遇到资源压力,kubelet会将BestEffort Pod优先驱逐);

1.Guaranteed

硬性要求:

  • Pod中的所有容器必须要有CPU和内存limit和request
  • Pod中每个容器的CPU和内存的limit值和request值要相等

例如:
下面这个Pod的容器设置了内存请求和内存限制,值都是2Gi,同时也设置了CPU请求和CPU限制,值都是1核(也可以是1000m)

apiVersion: v1
kind: Pod
metadata:
  name: "pod-guaranteed"
  namespace: default
  labels:
    app: "pod-guaranteed"
spec:
  containers:
  - name: pod-guaranteed
    image: "nginx:latest"
    resources:
      limits:
        cpu: 1
        memory: 2Gi
      requests:
        cpu: 1
        memory: 2Gi

验证:

[root@k8s-master ~# kubectl describe pod/pod-guaranteed
Containers:
  pod-guaranteed:
    ...
    Limits:
      cpu:     1
      memory:  2Gi
    Requests:
      cpu:        1
      memory:     2Gi
    ...
QoS Class:       Guaranteed

说明:
如果某 Container 指定了自己的内存限制,但没有指定内存请求,Kubernetes 会自动为它指定与内存限制相等的内存请求。同样,如果容器指定了自己的 CPU 限制, 但没有指定 CPU 请求,Kubernetes 会自动为它指定与 CPU 限制相等的 CPU 请求。
也就是说,如果创建Pod时只指定了CPU和内存的limit,而不指定request,那么默认情况下request是和limit相等的,所以创建出来的Pod也是属于Guaranteed Pod类;


2.Burstable

硬性要求:

  • Pod不符合QoS 类 Guaranteed的要求
  • Pod中至少一个容器有内存或CPU的request或limit

例如(1):
下面这个Pod的容器设置了内存限制为最多使用500Mi,内存请求为200Mi

apiVersion: v1
kind: Pod
metadata:
  name: "pod-burstable"
  namespace: default
  labels:
    app: "pod-burstable"
spec:
  containers:
  - name: pod-burstable
    image: "nginx:latest"
    resources:
      limits:
        memory: 500Mi
      requests:
        memory: 200Mi
      #或如下配置都是属于Burstable Pod类
      #limits:
      #  cpu: 2
      #  memory: 2Gi
      #requests:
      #  cpu: 1
      #  memory: 1Gi

验证:

[root@k8s-master ~]# kubectl describe pod/pod-burstable
Containers:
  pod-burstable:
    ...
    Limits:
      memory:  500Mi
    Requests:
      memory:     200Mi
    ...
QoS Class:       Burstable

例如(2):
下面这个Pod的里包含两个容器,一个容器指定内存请求为200MiB,另一个容器没有任何请求或限制

apiVersion: v1
kind: Pod
metadata:
  name: "pod-burstable2"
  namespace: default
  labels:
    app: "pod-burstable2"
spec:
  containers:
  - name: pod-burstable2
    image: "nginx:latest"
    resources:
      requests:
        memory: 200Mi

  - name: pod-burstable-assist
    image: "redis"

验证:

[root@k8s-master ~]# kubectl describe pod/pod-burstable2
Containers:
  pod-burstable2:
    ...
    Requests:
      memory:     200Mi
    ...
QoS Class:       Burstable

3.BestEffort

硬性要求:

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

例如:
下面这个Pod的容器没有设置内存和CPU限制或请求

apiVersion: v1
kind: Pod
metadata:
  name: "pod-besteffort"
  namespace: default
  labels:
    app: "pod-besteffort"
spec:
  containers:
 1. name: pod-besteffort
    image: "nginx:latest"

验证:

[root@k8s-master ~]# kubectl get pod/pod-besteffort -o yaml
spec:
  containers:
  ...
    resources: {}
  ...
status:
  qosClass: BestEffort  


三、节点压力时驱逐Pod Qos的顺序

官方文档在此

综上所述,Qos类的优先级由低到高为:
BestEffort < Burstable < Guaranteed

  1. BestEffort 类型的Pods:当节点有压力时/系统用完了全部内存时,首先考虑的就是资源使用量超过其请求的BestEffort Pods,也就是该类型的Pods会最先被kill掉;
  2. Burstable类型的Pods:当节点有压力时/系统用完了全部内存,且 没有BestEffort Pods可以被kill时,该类Pods会被kill掉;
  3. Guaranteed类型的Pods:当节点有压力时/系统用完了全部内存,且 没有BestEffort Pods和BestEffort Pods 可以被kill时,该类型的Pods才会根据资源使用量以及优先级被kill掉;

下面再来解释下为什么Guaranteed类型的Pods是最后才被kill掉的:

Kubernetes通过cgroup给pod设置QoS级别,当资源不足时先kill优先级低的pod,在实际使用过程中,通过OOM分数值来实现,OOM分数值从0-1000(OOM分数值根据OOM_ADJ参数计算得出)。

kubelet 会根据 Pod 的服务质量(QoS)为每个容器设置一个 oom_score_adj 值。

服务质量 oom_score_adj
Guaranteed -997
BestEffort 1000
Burstable 2到999

简单理解为:oom_score_adj的值越大越容易被kill;

对于kubernetes保留资源,比如kubelet,docker,OOM_ADJ参数设置成了-999,表示不会被OOM kill掉。OOM_ADJ参数设置的越大,通过OOM_ADJ参数计算出来OOM分数越高,表明该pod优先级就越低,当出现资源竞争时会越早被kill掉,对于OOM_ADJ参数是-999的表示kubernetes永远不会因为OOM而被kill掉。



总结

在生产环境中,强烈建议划分业务资源池:

  1. 需按照应用的类型/业务进行分类,核心应用/一级应用/二级应用;
  2. 核心应用:Guaranteed / 一级应用:Burstable / 二级应用:BestEffort;
  3. 集群节点需按应用组成资源池:核心业务资源池/一级业务资源池/二级业务资源池
  4. 核心应用需要在核心业务资源池中独占资源(例如CPU = 1或者2 整数则为独占资源,若CPU=1.5 则属于共享资源);
  5. 调度策略:
    核心应用:可以采用nodeAffinity的prefer调度策略调度到核心业务资源池,且核心应用的复副本数应为多个,并且应使用pod的反亲和性podAntiAffinity将其多个副本调度到核心业务资源池的不同节点上(究极高可用);
    一级应用:可以采用nodeAffinity的硬亲和调度策略调度到一级业务资源池;
    二级应用:可以采用nodeAffinity的硬亲和调度策略调度到二级业务资源池;

如果公司有钱,资源充足的话,可将QoS pods类型均设置为Guaranteed。用计算资源换业务性能和稳定性,减少排查问题时间和成本。

你可能感兴趣的:(Kubernetes学习分享;,kubernetes,docker,容器)