1. Pod和容器的资源设置
当我们定义 Pod 时,可以选择性地为每个容器设定所需要的资源数量。
最常见的可设定资源是 CPU 和内存(RAM)大小,此外还有其他类型的资源。
当我们为 Pod 中的 Container 指定了资源 request(请求) 时, kube-scheduler 就利用该信息决定将 Pod 调度到哪个节点上。
当我们为 Container 指定了资源 limit(限制) 时,kubelet 就可以确保运行的容器不会使用超出所设限制的资源。
kubelet 还会为容器预留所 request(请求) 数量的系统资源,供其使用。
参考文档:
2. K8S中的资源单位
2.1. CPU资源单位
CPU 资源的限制和请求以 cpu 为单位,资源清单中关键字是 cpu 。
在 Kubernetes 中,1个CPU核等于1个逻辑核,1个逻辑核 等于 1个物理CPU核 或者 1个虚拟核 ,取决于节点是一台物理主机还是运行在某物理主机上的虚拟机。
我们也可以表达带小数 CPU 的请求。 当我们定义一个容器,将其 spec.containers[].resources.requests.cpu
设置为 0.5 时, 我们所请求的 CPU 是我们请求 1.0 CPU 时的一半。 对于 CPU 资源单位,数量 表达式 0.1 等价于表达式 100m,可以看作 100 millicpu
。 有些人说成是一百毫核
,其实说的是同样的事情。
CPU 资源总是设置为资源的绝对数量而非相对数量值。 例如,无论容器运行在单核、双核或者 48-核的机器上,500m CPU 表示的是大约相同的计算能力。
2.2. 内存资源单位
内存的限制和请求以字节为单位,资源清单中关键字是 memory 。
我们可以使用普通的整数,或者带有以下 数量后缀 的定点数字来表示内存:E、P、T、G、M、k。
我们也可以使用对应的 2 的幂数:Ei、Pi、Ti、Gi、Mi、Ki。
例如,以下表达式所代表的是大致相同的值:
1 | 128974848、129e6、129M、128974848000m、123Mi |
请注意后缀的大小写。如果我们请求 400m 临时存储,实际上所请求的是 0.4 字节。 如果有人这样设定资源请求或限制,可能他的实际想法是申请 400Mi 字节(400Mi) 或者 400M 字节。
2.3. PVC存储单位
PVC存储单位和内存资源的的单位相同,资源清单中的关键字是 storage 。
2.4. 本地临时性存储单位
本地临时性存储的单位和内存资源的单位相同,资源清单中关键字是 ephemeral-storage 。
本地临时性存储说明:
本地临时性存储,以Pod中的用户角度来看,就是系统盘。
节点可以具有本地的临时性存储,由本地挂接的可写入设备或者有时也用 RAM 来提供支持。
临时(Ephemeral)意味着对所存储的数据不提供长期可用性的保证。
Pods 通常可以使用临时性本地存储来实现缓冲区、保存日志等功能。 kubelet 可以为使用本地临时存储的 Pods 提供这种存储空间,允许后者使用 emptyDir 类型的卷将其挂载到容器中。
kubelet 也使用此类存储来保存节点层面的容器日志、 容器镜像文件以及运行中容器的可写入层。
详情参考文档本地临时存储
2.5. GPU资源单位
K8S中,在调度使用GPU资源时,使用不同的 Kubernets Device Plugin,GPU单位也是不同的。
参考文档:
3. 资源设置方式
3.1. 资源设置方式概述
资源设置有三种方式:
1、在Container中设置
在Container中设置资源需求是最常用的方式,其中request是容器可以使用到的最小资源,limit是宿主机资源充足的情况下容器可以使用到的最大资源
2、使用LimitRange限制
使用 LimitRange 可以设置某个命名空间的 request 与 limit 默认值,也可设定 request 与 limit 的最大值与最小值。
3、使用ResourceQuota限制
当多个用户或团队共享具有固定节点数目的集群时,人们会担心有人使用超过其基于公平原则所分配到的资源量。资源配额是帮助管理员解决这一问题的工具。
使用 ResourceQuota 可以对某个命名空间的资源消耗总量提供限制。它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命名空间中的 Pod 可以使用的计算资源的总上限。
3.2. 在Container中设置
3.2.1. 设置CPU和内存
在Container中设置CPU和内容,示例如下:
1 |
|
上面的 Pod 有两个容器。每个容器的请求为 0.25 CPU 和 64MiB(226 字节)内存, 每个容器的资源限制为 0.5 CPU 和 128MiB 内存。 我们可以认为该 Pod 的资源请求为 0.5 CPU 和 128 MiB 内存,资源限制为 1 CPU 和 256MiB 内存。
3.2.2. 设置本地临时存储
在Container中设置本地临时存储,示例如下:
1 | apiVersion: v1 |
3.3. 使用LimitRange限制
使用LimitRange,设置Request和Limit默认值和范围,示例如下:
1 | apiVersion: v1 |
注意:使用LimiteRange,目前是不支持限制本地临时存储的。
3.4. 使用ResourceQuota限制
3.4.1. 限制CPU和内存
使用ResourceQuota,限制default namespace下所有pod的request cpu总和不超过1,request memory总和不超过2G,limit cpu总和不超过2,limit memory总和不超过2G,示例如下:
1 | apiVersion: v1 |
3.4.2. 限制本地临时存储
使用ResourceQuota,也可以限制磁盘的用量。
限制default namespace下所有pod的数据写入总和不能超过1G,示例如下:
1 | apiVersion: v1 |
4. 怎样设置合理的Request和Limit?
4.1. 建议设置Request
Request 的值并不代表给容器实际分配的资源大小,而是用于提供给调度器。调度器会检测每个节点可用于分配的资源(节点可分配资源 = 节点资源总额 - 已调度到节点上的 Pod 内容器 request 之和),同时记录每个节点已经被分配的资源(节点上所有 Pod 中定义的容器 request 之和)。如发现节点剩余的可分配资源已小于当前需被调度的 Pod 的 request,则该 Pod 就不会被调度到此节点。反之,则会被调度到此节点。
如果不配置 request,调度器就无法感知节点资源使用情况,无法做出合理的调度决策,可能会造成调度不合理,引起节点状态混乱。建议给所有容器设置 request,使调度器可感知节点资源情况,以便做出合理的调度决策。集群的节点资源能够被合理的分配使用,避免因资源分配不均而导致发生故障。
4.2. 重要应用Request等于Limit
在Kubernetes中,request和limit之间的差异决定了容器的QoS类别。
- 如果
request == limit
,则容器属于Guaranteed QoS类别。 - 如果
request < limit
,则容器属于Burstable QoS类别。 - 如果没有设置request和limit,则容器属于BestEffort QoS类别。
不同的QoS类别有不同的调度和驱逐策略。
节点资源不足时,会触发自动驱逐和删除,优先删除BestEffort容器,其次是Burstable容器,最后是Guaranteed容器。
同时,request和limit之间的差值越大,Burstable类型的容器被驱逐的风险就越高。
对于生产环境中关键的服务,推荐设置 request == limit
,即Guaranteed QoS类别,以保证在节点故障时关键服务不易被驱逐导致线上业务受到影响。
4.3. 提高资源利用率
如果应用设置了较高的 request 值,而实际占用资源远小于设定值,会导致节点整体的资源利用率较低。除对时延非常敏感的业务外,敏感的业务本身并不期望节点利用率过高,影响网络包收发速度。
建议对非核心,并且资源非长期占用的应用,适当减少 request 以提高资源利用率。如果我们的服务支持水平扩容,那么除 CPU 密集型应用外,单副本的 request 值通常可设置为不大于1核。例如,coredns 设置为0.1核,即100m即可。
4.4. 避免Request和Limit值过大
如果我们的服务使用单副本或少量副本,且 request 及 limit 的值设置过大,使服务可分配到足够多的资源去支撑业务。那么某个副本发生故障时,可能会给业务带来较大影响。
当 Pod 所在节点发生故障时,由于 request 值过大,且集群内资源分配的较为碎片化,其余节点无足够可分配资源满足该 Pod 的 request,那么该 Pod 无法实现漂移,无法自愈,会加重对业务的影响。
建议尽量减小 request 及 limit,通过增加副本的方式对我们的服务支撑能力进行水平扩容,使系统更加灵活可靠。