1. K8S资源配额
在K8S集群环境中,宿主机的计算资源是有限的,当多个用户或者多个团队共同使用该集群环境时,一个重要的事情就是如何公平的分配宿主机计算资源。为了精细控制POD中容器对宿主机计算资源的使用情况,K8S中提供了requests和limits配额设置方案。此外K8s还提供了ResourceQuota对象和LimitRange对象来控制某个命名空间下POD的资源配额,具体作用如下:
1) ResourceQuota可以对某个命名空间下资源总量进行限制
2) LimitRange可以为某个命令空间下POD中容器提供资源配额的默认值,以及指定资源配额的设置范围。
1.1 requests和limits
该资源配额设置方案是在POD的yaml文件中,针对每一个容器显式指定资源配额数值,从而对每个容器的资源进行限制。整体设置如下图所示:
由上图可以看到,requests和limits配额设置是定义在POD内容器层面上的,未定义资源配额的容器默认值为0,POD的资源配额值为POD内所有容器资源配额之和(已验证,包括初始化容器)。
CPU和RAM 换算单位如下:
1) CPU
单位为m时表示毫核(1个逻辑核分1000毫核);单位为空默认单位为(逻辑)核。
2) RAM
K,M,G,T,P,E 通常这些单位是以1000为换算标准的。
Ki, Mi,Gi, Ti,Pi, Ei 这些通常是以1024为换算标准的
1.1.1 requests介绍
requests是POD期望能够得到的资源值,主要作用是K8S调度POD时节点选择的判断依据。只有当节点上未分配的资源量 >= request 时,才允许将POD调度到该节点上。requests不限制POD的最大可使用资源。
如上图所示,节点上有A、B、C三个POD,现在 Pod D在调度的时候,K8s统计节点上未分配的资源量,其中CPU的未分配资源量(Unallocated)小于Pod D的CPU requests值,故Pod D仍然无法调度到该节点上。可见,K8S 调度Pod的时候并不关注在调度时节点的资源实际使用情况,而是根据现存非终止态容器的requests之和情况判断是否进行调度。(已验证,终止态容器包含初始化容器和job的业务容器)
此外, Pod实际使用量可能大于或小于设置的requests资源值。如果Kubernetes找不到满足资源请求的Node,则Pod创建会停留在Pending状态。
针对CPU和RAM,requests的作用总结如下:
- CPU requests的作用
1) 作为k8s调度POD进行节点筛选的判断依据(绝对值)
2) 宿主机CPU资源抢占时,容器按比例分配CPU使用的依据(相对值)
CPU requests,会对应到容器内cgroup下cpu.shares属性上,当宿主机CPU资源发生抢占时,各个容器按照shares份额比例进行宿主机CPU资源的使用。
- RAM requests的作用
1) POD作为k8s调度POD进行节点筛选的依据
1.1.2 limits介绍
Limits表示POD使用资源的最大值,如果不设置limits,则理论上POD可以使用Node的全部资源。如果POD设置limits,则该POD的资源使用的最大值不超过设置的limits值,并且全部POD资源limits总和可以超过Node的容量。
- CPU limits
CPU是一种可以压榨的资源,可以用满并且Pod之间可以共享使用。CPU limits会作用到cgroup下的cpu.cfs_quota_us(CPU切换周期内的最大使用时间,单位us)属性上,从而控制POD能使用的CPU资源的上限。
cpu.cfs_quota_us值受cpu.cfs_period_us(CPU切换周期,默认100ms)的影响。公式近似如下:
- RAM limits
内存limits对应cgroup下memory.limit_in_bytes属性上,当节点的RAM被使用完或者POD超过了limits上限,便会触发 OOM Killed。
1.2 ResourceQuota对象
1.2.1 作用
1. 为某一个命名空间设置指定资源总量的约束,可以防止不同命名空间肆意使用宿主机资源。
2. 强制约束命名空间下POD内所有容器指定一个资源配额或者使用默认值,否则POD创建失败,报 403 FORBIDDEN 。
1.2.2 设置方式
以CPU和RAM计算资源为例,设置方式如下图所示:
该对象定义了,某个命名空间下,所有非终止态的POD:
- CPU requests之和不超过1核
- CPU limits之和不超过为2核
- RAM requests之和不超过1Gi
- RAM limits之和不超过2Gi
1.2.3 验证结论
1. ResourceQuota作用时机:不影响已经存在的pod运行(POD重启除外),对之后POD的创建合法性进行检查
2. POD定义的资源配额之和不能超过该对象中定义的资源总和,否则POD创建失败
3. ResourceQuota要求pod内所有容器(包括初始化容器)必须按要求配置上资源配额,否则创建失败
1.3 LimitRange对象
1.3.1 作用
- 为POD或者Container设置CPU、RAM资源配额的最小值和最大值
- 为POD或者Container设置CPU、RAM资源配额的limits和requests的比率
- 为POD内容器设置CPU、RAM资源配额默认的requests和limits
- LimitRange作用于POD的创建阶段,YAML文件中设置的资源配额不符合limitRange对象的约束要求,则容器会启动失败(403 FORBIDDEN);已运行的POD不受限制(POD重启除外)。
1.3.2 设置方式
字段属性说明:
1. type:取值为Pod或者Container,表示作用域为Pod或者容器
2. min:Pod或者容器CPU、RAM requests资源最小值
3. max:Pod或者容器CPU、RAM requests资源最大值
4. default:容器的CPU、RAM limits的默认值
5. defaultRequest:容器的CPU、RAM requests的默认值
6. maxLimitRequestRatio:Pod或者容器CPU、RAM的 limits值和requests值两者之间的最大比值
1.3.3 验证结论
- Type可以为POD或者Container,不同Type下资源设置值大小没有约束关系
- Type为POD的时候,不支持在该类型下设置CPU、RAM计算资源的默认值
- Min < defultRequest < defaultLimits < max ,计算资源的(limits/requests)比率 <= max/min
- POD中容器的资源配额设置需要在Limitrange的min和max之间
- POD中容器如果只设置CPU配额,RAM配额会使用Limitrange的默认值
- POD设置的资源配额的比率要小于等于limitrange的比率限制,并且K8S不检查limitrange中设置的默认值设置是否符合比率要求。
2. 资源值的获取
为了准确的获取POD的消耗的资源值,有以下2个关键点:
3.2.1 真实可靠的业务压力
特定组件根据自身特点,首先需要模拟出“正常”和“峰值”下的业务操作(或称为业务操作集合),在执行该业务压力下,去监控POD使用的资源,才更具有代表性。
3.2.2 有效的资源消耗监控手段
为了获取容器的资源使用情况,有以下2种命令行工具,如下表所示:
监控方式 |
说明 |
Kubectl top |
Kubectl top查询的是heapster组件每1分钟的聚合数据。Heapster的聚合数据是将内存中2分钟内的cAdvisor的监控数据进行整合汇总后插入数据库。cAdvisor是每10秒监控一下POD资源消耗,并将数据放在内存中。
|
Docker stats |
|
3.2.2.1 特别说明
- CPU-limits:设置过小,将会影响容器的api响应速度;设置过大,该容器内部故障时,又限制不了该容器的cpu资源使用量,导致其他容器可用cpu资源变少
- RAM-limits:设置过小,oom风险增加;设置过大,该容器内部故障时,又限制不了该容器的ram资源使用量,导致其他容器可用ram资源变少,设置oom
- CPU-requests: 设置过小,部署的容器过多导致节点资源紧张,影响每个容器;设置过大,节点资源会大大浪费
- RAM-requests: 设置过小,部署的容器过多导致节点资源紧张,影响每个容器;设置过大,节点资源会大大浪费