在kubernetes中,每一个POD都有个QoS标记,经过这个Qos标记来对POD进行服务质量管理。QoS的英文全称为"Quality of Service",中文名为"服务质量",它取决于用户对服务质量的预期,也就是指望的服务质量。对于POD来讲,服务质量体如今两个指标上,一个指标是CPU,另外一个指标是内存。在实际运行过程当中,当NODE节点上内存资源紧张的时候,kubernetes根据POD具备的不一样QoS标记,采起不一样的处理策略。线程
在Kubernetes中,POD的QoS服务质量一共有三个级别,以下图所示:继承
这三个QoS级别介绍,能够看下面表格:接口
QoS级别进程 |
QoS介绍内存 |
BestEffort资源 |
POD中的全部容器都没有指定CPU和内存的requests和limits,那么这个POD的QoS就是BestEffort级别kubernetes |
Burstablerequests |
POD中只要有一个容器,这个容器requests和limits的设置同其余容器设置的不一致,那么这个POD的QoS就是Burstable级别it |
Guaranteed |
POD中全部容器都必须统一设置了limits,而且设置参数都一致,若是有一个容器要设置requests,那么全部容器都要设置,并设置参数同limits一致,那么这个POD的QoS就是Guaranteed级别 |
为了更清楚的了解这三个QoS级别,下面咱们举例说明。
QoS级别 |
QoS配置例子 |
BestEffort |
containers: name: foo resources: name: bar resources: |
Burstable |
containers: name: foo resources: limits: cpu: 10m memory: 1Gi requests: cpu: 10m memory: 1Gi
name: bar |
containers: name: foo resources: limits: memory: 1Gi
name: bar resources: limits: cpu: 100m |
|
containers: name: foo resources: requests: cpu: 10m memory: 1Gi
name: bar |
|
Guaranteed |
containers: name: foo resources: limits: cpu: 10m memory: 1Gi name: bar resources: limits: cpu: 100m memory: 100Mi |
containers: name: foo resources: limits: cpu: 10m memory: 1Gi requests: cpu: 10m memory: 1Gi
name: bar resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 1Gi |
QoS级别决定了kubernetes处理这些POD的方式,咱们之内存资源为例:
一、当NODE节点上内存资源不够的时候,QoS级别是BestEffort的POD会最早被kill掉;当NODE节点上内存资源充足的时候,QoS级别是BestEffort的POD可使用NODE节点上剩余的全部内存资源。
二、当NODE节点上内存资源不够的时候,若是QoS级别是BestEffort的POD已经都被kill掉了,那么会查找QoS级别是Burstable的POD,而且这些POD使用的内存已经超出了requests设置的内存值,这些被找到的POD会被kill掉;当NODE节点上内存资源充足的时候,QoS级别是Burstable的POD会按照requests和limits的设置来使用。
三、当NODE节点上内存资源不够的时候,若是QoS级别是BestEffort和Burstable的POD都已经被kill掉了,那么会查找QoS级别是Guaranteed的POD,而且这些POD使用的内存已经超出了limits设置的内存值,这些被找到的POD会被kill掉;当NODE节点上内存资源充足的时候,QoS级别是Burstable的POD会按照requests和limits的设置来使用。
从容器的角度出发,为了限制容器使用的CPU和内存,是经过cgroup来实现的,目前kubernetes的QoS只能管理CPU和内存,因此kubernetes如今也是经过对cgroup的配置来实现QoS管理的。
咱们简单来介绍下cgroup:
一、来源:
cgroups(Control Groups)最初叫ProcessContainer,由Google工程师(Paul Menage和Rohit Seth)于2006年提出,后来由于Container有多重含义容易引发误解,就在2007年改名为Control Groups,并被整合进Linux内核。顾名思义就是把进程放到一个组里面统一加以控制。
二、官方定义:
cgroups是Linux内核提供的一种机制,这种机制能够根据特定的行为,把一系列系统任务及其子任务整合(或分隔)到按资源划分等级的不一样组内,从而为系统资源管理提供一个统一的框架。
三、做用:
资源限制(Resource Limitation):cgroups能够对进程组使用的资源总额进行限制。如设定应用运行时使用内存的上限,一旦超过这个配额就发出OOM(Out of Memory)。
优先级分配(Prioritization):经过分配的CPU时间片数量及硬盘IO带宽大小,实际上就至关于控制了进程运行的优先级。
资源统计(Accounting): cgroups能够统计系统的资源使用量,如CPU使用时长、内存用量等等,这个功能很是适用于计费。
进程控制(Control):cgroups能够对进程组执行挂起、恢复等操做。
四、特色:
cgroups的API以一个伪文件系统的方式实现,即用户能够经过文件操做实现cgroups的组织管理。
cgroups的组织管理操做单元能够细粒度到线程级别,用户态代码也能够针对系统分配的资源建立和销毁cgroups,从而实现资源再分配和管理。
全部资源管理的功能都以“ subsystem(子系统)”的方式实现,接口统一。
子进程建立之初与其父进程处于同一个cgroups的控制组。
五、本质:
本质上来讲,cgroups是内核附加在程序上的一系列钩子(hooks),经过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。
六、cgroups术语
task(任务):cgroups的术语中,task就表示系统的一个进程。
cgroup(控制组):cgroups 中的资源控制都以cgroup为单位实现。cgroup表示按某种资源控制标准划分而成的任务组,包含一个或多个子系统。一个任务能够加入某个cgroup,也能够从某个cgroup迁移到另一个cgroup。
subsystem(子系统):cgroups中的subsystem就是一个资源调度控制器(ResourceController)。好比CPU子系统能够控制CPU时间分配,内存子系统能够限制cgroup内存使用量。
hierarchy(层级树):hierarchy由一系列cgroup以一个树状结构排列而成,每一个hierarchy经过绑定对应的subsystem进行资源调度。hierarchy中的cgroup节点能够包含零或多个子节点,子节点继承父节点的属性。整个系统能够有多个hierarchy。
在kubernetes中,咱们能够看看POD配置中的requests和limits参数是如何同cgroup创建关联关系,进而实现对POD的资源QoS管理的。
QoS级别 |
QoS配置例子 |
cgroup对应 |
Guaranteed |
kind: Pod metadata: name: Pod1 spec: containers: name: foo resources: limits: cpu: 10m memory: 1Gi name: bar resources: limits: cpu: 100m memory: 2Gi |
/Pod1/cpu.quota = 110m /Pod1/cpu.shares = 110m /Pod2/cpu.quota = 20m /Pod2/cpu.shares = 20m /Pod1/memory.limit_in_bytes = 3Gi /Pod2/memory.limit_in_bytes = 2Gi |
kind: Pod metadata: name: Pod2 spec: containers: name: foo resources: limits: cpu: 20m memory: 2Gi |
||
Burstable |
kind: Pod metadata: name: Pod3 spec: containers: name: foo resources: limits: cpu: 50m memory: 2Gi requests: cpu: 20m memory: 1Gi name: bar resources: limits: cpu: 100m memory: 1Gi |
/Bu/cpu.shares = 30m /Bu/Pod3/cpu.quota = 150m /Bu/Pod3/cpu.shares = 20m /Bu/Pod4/cpu.quota = 20m /Bu/Pod4/cpu.shares = 10m /Bu/memory.limit_in_bytes = Allocatable - 5Gi /Bu/Pod3/memory.limit_in_bytes = 3Gi /Bu/Pod4/memory.limit_in_bytes = 2Gi |
|
kind: Pod metadata: name: Pod4 spec: containers: name: foo resources: limits: cpu: 20m memory: 2Gi requests: cpu: 10m memory: 1Gi |
|
BestEffort |
kind: Pod metadata: name: Pod5 spec: containers: name: foo resources: name: bar resources: |
/BE/cpu.shares = 2 /BE/cpu.quota= not set /BE/memory.limit_in_bytes = Allocatable - 7Gi /BE/Pod5/memory.limit_in_bytes = no limit |
咱们知道了cgroups里面有hierarchy(层级树)的概念,那么咱们来看在kubernetes里面是如何把POD放在hierarchy(层级树)上面的:
对于kubernetes来讲,经过cgroup就能够给POD设置QoS级别,当资源不够使用时,先kill优先级低的POD,在实际使用时,是经过OOM(Out of Memory)分数值来实现的,OOM分数值从0到1000。OOM分数值是根据OOM_ADJ参数计算出来的,对于Guaranteed级别的POD,OOM_ADJ参数设置成了-998,对于BestEffort级别的POD,OOM_ADJ参数设置成了1000,对于Burstable级别的POD,OOM_ADJ参数取值从2到999,对于kube保留的资源,好比kubelet,OOM_ADJ参数设置成了-999。OOM_ADJ参数设置的越大,经过OOM_ADJ参数计算出来的OOM分数越高,OOM分数越高,这个POD的优先级就越低,在出现资源竞争的时候,就越早被kill掉,对于OOM_ADJ参数是-999的表明kubernetes永远不会由于OOM而被kill掉。以下图所示: