一、pod的Qos等级
一个不一定能提供所有pod所指定的资源limites之和那么多的资源量,比如两个pod,podA使用了节点内存的90%,podB突然需要更多的内存,这是节点就无法提供足量内存,那个容器将被杀掉呢,kubernetes无法做出正确决策,需要制优先级。
kubernetes将pod划分为3种Qos等级:
BestEffort(优先级最低)
Burstable
Guaranteed(优先级最高)
pod的BestEffort等级
最低优先级的Qos等级是BestEffort
容器没有设置任何requests和limits的pod,这个等级运行的容器没有任何资源保证。在最坏情况下,他们分不到任何cpu时间,同时,在需要为其他pod释放内存时,这些容器第一批被杀死。不过因为BestEffort pod没有陪只内存limits,当有充足的可用内存时,这些容器可以使用任意多的内存。
Guaranteed等级
该等级会分配那些所有资源request和limits相同的pod。对于一个Guaranteed级别的pod,有以下几个条件:
cpu和内存都要设置requests和limits
每个容器都需要设置资源量
他们必须相等(每个容器的每种资源的requests和limits必须相等)
因为如果容器的资源request没有显示设置,默认与limits相同,所以只设置所有资源(pod内每个容器的每种资源)的限制量就可以使pod的Qos等级为Guaranteed。这些pod的容器可以使用它所申请的等额资源,但无法消耗更多资源(因为他们的requests和limits相等)
Burstable等级
介于BestEffort和Guaranteed之间。其他所有的pod都属于这个等级,包括容器的requests和limits不相同的单容器pod,至少有一个容器只定义了requests但没有定义limits的pod,以及一个容器的requests和limits相等,但时另一个容器不指定requests和limits的pod。Burstable pod可以获得他们所申请的等额资源,并可以使用额外的资源(不超过limits)
容器的QOS等级
CPU requests vs limits |
内存requests vs limits |
容器的Qos等级 |
未设置 |
未设置 |
BestEffort |
未设置 |
Requests<limits |
Burstable |
未设置 |
Requests=limits |
Burstable |
Requests<limits |
未设置 |
Burstable |
Requests<limits |
Requests<limits |
Burstable |
Requests<limits |
Requests=limits |
Burstable |
Requests=limits |
Requests=limits |
Guaranteed |
多容器pod的Qos等级
容器1的Qos等级 |
容器1的Qos等级 |
pod的Qos容器 |
BestEffort |
BestEffort |
BestEffort |
BestEffort |
Burstable |
Burstable |
BestEffort |
Guaranteed |
Burstable |
Burstable |
Burstable |
Burstable |
Burstable |
Guaranteed |
Burstable |
Guaranteed |
Guaranteed |
Guaranteed |
内存不足时哪个进程会被杀死
在一个超卖的系统,BestEffort等级的pod首先被杀掉,其次是Burstable pod,最后是Guaranteed pod。Guaranteed pod只有在系统进程需要内存时才会被杀掉。
如何处理相同Qos等级的容器
每个运行中的进程都有一个被称为OutOfMemory(OOM)分数的值。系统通过比较所有运行进程的OOM分数来选择要杀掉的进程。当需要释放内存时,分数最高的进程将被杀掉。
OOM分数由两个参数计算得出:进程已消耗内存占可用内存百分比,与一个基于pod QoS等级和容器内存申请量固定的OOM分数调节因子。对于两个属于Burstable等级的单容器的pod,系统会杀掉内存实际使用量占内存申请量比例更高的pod。
这说明我们不仅要注意requests和limits之间的关系,还要留心requests和预期实际消耗内存之间的关系。
二、为命名空间中的pod设置默认的requests和limits
前面讲了为单个容器设置资源requests和limits。
可以通过创建一个LimitRange资源来避免必须配置每个容器。LimitRange资源不仅允许用户(为每个命名空间)指定能给容器配置的每种资源的最小和最大限额,还支持在没有显式指定资源requests时为容器设置默认值。
LimitRange资源
LimitRange资源被LimitRanger准入控制插件。API服务器接收到带有pod描述信息的POST请求时,LimitRanger插件队pod spec进行校验。如果校验失败,将直接拒绝。因此,LimitRange对象的一个广泛应用场景就是阻止用户创建大于单个节点资源量的pod。如果没有LimitRange,api服务器将欣然接收pod创建请求,但永远无法调度成功。
LimitRange资源中的limits应用于同一命名空间中每个独立的pod、容器,或者其它类型的对象,但他并不会限制这个命名空间中所有pod可用资源的总量,总量时通过ResourceQuota对象指定。
LimitRange对象创建
yaml文件:limits.yaml
apiVersion:v1
kind:LimitRange
metadata:
name:example
spec:
limits:
-type:pd
min:
cpu:50m
memory:5mi
max:
cpu:1
memory:1Gi
-type:Container
defaultRequest:
cpu:100m
memory:10Mi
default:
cpu:200m
memory:100mi
min:
cpu:50m
memroy:5Mi
max:
cpu:1
memroy:1Gi
maxLimitRequestRatio:
cpu:4
memroy:10
-type:PersistentVolumeClaim
min:
storage:1Gi
max:
storage:10Gi
LimitRange对象中配置的校验(和默认值)信息在api服务器接收到新的pod和pvc创建请求时执行,如果之后修改了限制,已经存在的pod和pvc将不会再次进行校验,新的限制只会应用于之后创建的pod和pvc。
强制进行限制
创建一个cpu申请量大于limitRange允许值的pod,会限制创建成功