对容器进行资源限额的几种方式
标签搜索

对容器进行资源限额的几种方式

mrui
2025-04-21 / 0 评论 / 35 阅读 / 正在检测是否收录...

当多个应用共享固定节点数目的集群时,可能会出现某些应用过度使用系统资源,从而影响其他服务正常运行的情况。为了提升集群内应用运行的稳定性,尽量避免上述现象的发生,需要设定一些规则,来保证应用能获得其运行所需的合理资源。

cpu资源
cpu资源的约束和请求以毫核(m)为单位,1m是最小的调度单元。cpu一个核心可以看做是1000m。

内存资源
memory的约束和请求以字节为单位。可以使用两种单位来配置
1000进制:E P T G M k
1024进制:Ei Pi Gi Mi ki

集群计算资源规划

Kubernetes集群中的计算资源一般都是由集群内的Node提供。Kubelet会管理计算资源Node上的资源预留和可分配资源(NodeAllocatable Resource)。

资源预留

Kubelet通过以下几个参数来管理资源预留:

  • system-reserved:为操作系统进程预留的资源;
  • kube-reserved:为Kubelet、Kube-proxy、容器运行时(Container Runtime)等核心系统进程预留的资源;
  • evicition-hard:触发驱逐Pod进行资源回收的资源低水位警戒线。

可分配资源

Node Allocatable Resource解决了以下两个关键问题:

  • Node上实际可分配资源的数量
  • 基于QoS实现了资源保护机制,当资源严重不足时,低优先级的Pod会被优先清除,包括被操作操作系统优先清除。

    Pod的3种QoS级别

Kubernetes集群中的QoS体系中,需要保证高可靠性的Pod可以申请可靠资源,一些非高可靠性的Pod可以申请可靠性较低或者不可靠的资源。

Kubernetes根据Pod的Requests和Limits的配置来实现Pod的QoS级别的划分。

Requests是Kubernetes调度时能够为容器提供的完全、可保障的资源量(最低保障),Limits是系统允许容器运行时可能使用的资源量的上限(最高上限)。

Pod级别的资源配置是通过计算Pod内所有容器的资源配置的总和得出的。Kubernetes根据Pod配置的Requests值来调度Pod。Pod调度成功后会得到Requests值定义的资源来运行。如果Pod所在的Node还有空余的资源,则Pod可以申请更多的资源,但最多不会超过Limits的值。

  1. 如果Pod配置的Requests和Limits值相等,那么该Pod可以获得的资源是完全可靠的。
  2. 如果Pod的Requests值小于Limits值,那么该Pod获得的资源可分为以下两部分:

    • 完全可靠资源:资源量等于Requests值;
    • 不可靠资源:资源量最大等于Limits与Requests的差额。这份不可靠资源能够申请到多少,取决于当时主机上容器可用资源的余量。

通过这种机制,Kubernetes可以实现Node资源的超售(Over Subscription)。比如在CPU完全充足的情况下,某机器共有32GiB内存可供容器使用,容器配置为Requests值1GiB,Limits值2GiB,那么该机器上最多可以同时运行32个容器,每个容器最多可以使用2GiB内存。如果这些容器的内存使用峰值能够错开,那么所有容器都可以正常运行。

超售机制能有效提高资源的利用率,也不会影响容器申请的“完全可靠资源”的可用性。

Guaranteed
如果Pod中的所有容器对所有资源类型都定义了Limit和Request,并且每个容器的limits值都和Requests值相等且不为0,那么该Pod的QoS级别就是Guaranteed。在这种情况下,容器可以不定义Requests,因为Requests的值在未定义时默认等于Limits。

BestEffort
如果pod中所有的容器都未定义资源配置(Requests和Limits都未定义),那么该Pod的QoS级别就是BestEffort。
Burstable
当一个Pod不属于上面两种级别时,该Pod的QoS级别就是Burstable。该级别的Pod涉及以下两种情况。

  • Pod中的一部分容器在一种或多种资源类型的资源配置中定义了Requests值和Limits值(都不为0 ),并且Requests值小于Limits。
  • Pod中的一部分容器未定义资源配置(Requests和Limits都未定义)。注:在容器未定义Limits的时,Limits的值默认等于Node资源容量的上限。
节点压力时驱逐Pod Qos的顺序

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

Pod最小配额

在Pod的containers字段指定,声明该容器所需要的最低资源额度。

containers:
- name: busybox
  image: busybox:latest
  command: ["awk","BEGIN{while(1){}}"]
  resources: #定义资源的配额
    requests: #申请最小资源配额
    memory: 1000M #申请1000M的内存资源
    cpu: 100m     # 申请100m的cpu资源

Pod最大资源配额

containers:
- name: busybox
  image: busybox
  command: ["awk","BEGIN{while{1}{}}"]
  resources:      #定义资源的配额
    limits:       #限制最大资源配额
      cpu: 800m   #计算资源最大配额
      memory: 2000Mi  # 内存资源最大配额

全局资源配额

以名称空间(namespace)为单位,限制其资源的使用与创建。在该名称空间中创建的容器都会受到规则的限制。
LimitRange:对内存、cpu、存储资源进行配额
ResourceQuota:对Pod进行配额

#为名称空间myns设置默认资源配额
apiVersion: v1
kind: LimitRange
metadata:
  name: mylimit       #规则名称
  namespace: myns     #规则生效的名称空间
spec:
  limits:             #全局限制规则 
  - type: Container   #资源类型
    default:          #默认资源配额。如果没有手动配置,以下配置生效
      cpu: 300m       #cpu限额
      memory: 500Mi   #内存限额
    defaultRequest:   #默认资源需求。如果没有手动配置,以下配置生效
      cpu: 8m         #cpu最小需求资源
      memory: 8Mi     #内存最小需求资源
    max:              #最大限额
      cpu: 8000m      #CPU最大限额
      memory: 1000Mi  #内存最大限额
    min:              #最小限额
      cpu: 2m         #cpu最小限额
      memory: 8Mi     #内存最小限额
  - type: Pod         #对整个Pod设置总限额
    max:              #整个Pod的最大限额
      cpu: 1200m      #对整个Pod的CPU最大限额
      memory: 1200Mi  #最整个Pod的内存最大限额
    min:              #对整个Pod的最小限额
      cpu: 2m         #对整个Pod最小cpu限额
      memory: 8Mi     #对整个Pod的最小内存限额

限制配额总量

---
apiVersion: v1
kind: ResourceQuota            #全局资源限额对象
metadata:
  name: myquota                #规则名称
  namespace: myns              #规则生效的名称空间
spec: 
  hard:                        #创建强制规则
    requests.cpu: 1000m        #最小CPU配额总数
    requests.memory: 2000Mi    #最小内存配额总数
    limits.cpu: 5000m          #最大CPU配额总数
    limits.memory: 8Gi         #最大内存配额总数
    pods: 3                    #限制创建资源对象总数量

ResourceQuota支持的限制的Node资源类型

资源名称说明
计算资源
requests.cpu所有非终止状态的Pod,CPU Request的总和不能超过该值
requests.memory所有非终止状态的Pod,内存Request的总和不能超过该值
limits.cpu所有非终止状态的Pod,CPU Limits的总和不能超过该值
limits.memory所有非终止状态的Pod,内存 Limits的总和不能超过该值
hugepages.$size所有非终止终止状态的Pod,针对指定$size尺寸的HugePages请求总和不能超过该值
存储资源
requests.storage所有PVC,存储总和不能超过该值
persistentvolumeclaims在该名称空间中,能存在的PVC的总上限
.storageclass.storage.k8s.io/requests.storage所有与相关的PVC请求的存储总量都不能超过该值。如gold.storageclass.storage.k8s.io/requests.storage: 500Gi,表示类型为gold的storageClass对应的PVC的申请存储总量最多可达500Gi
.storageclass.storage.k8s.io/persistentvolumeclaims所有与相关的PVC总和上限
requests.ephemeral-storage本地临时存储(ephemeral-storage)的总请求量
limits.ephemeral-storage本地临时存储(ephemeral-storage)的总上限量

ResourceQuota支持的限制的对象类型

资源名称说明
configmaps在该命名空间中能存在的ConfigMap的总数上限
persistentvolumeclaims在该命名空间中能存在的PVC总数上限
pods在该命名空间中能存在的非终止状态的Pod的总数上限
replicationcontrollers在该命名空间中能存在的RC的总数上限
Resourcequotas在该命名空间中能存在的资源配额的总数上限
service在该命名空间中能存在的Service的总数上限
service.loadbalancers在该命名空间中能存在的负载均衡的总数上限
service.nodeports在该命名空间中能存在的Nodeport的总数上限
secrets在该命名空间中能存在的Secret的总数上限

对每项资源配额都可以单独配置一组作用域(scope),配置了作用域的资源配额只会对符合其作用域的资源使用情况进行计量和限制。如果作用域范围超出了资源配额的请求,系统会报验证错误。
ResourceQuota的5种作用域

作用域说明
Terminating匹配所有spec.activeDeadlineSeconds不小于0的Pod
NotTerminating匹配所有spec.activeDeadlineSeconds都是nil的Pod
BestEffort匹配所有QoS等级是BestEffort的Pod,只作用于Pod
NotBestEffort匹配所有QoS等级不是BestEffort的Pod
PriorityClass匹配所有引用了指定优先级类的Pod

针对示例2的一些说明:

  • 如果设置了Container的Max,则对于该类资源而言,整个集群中的所有容器都必须设置Limits,否则无法创建成功。在Pod内的容器未配置Limits时,将使用Default Limit的值,如果也未配置Default,则无法创建成功。
  • 如果设置了Container的Min,那么对于该类资源而言,整个集群中的所有容器都必须设置Requests。如果在创建Pod的容器时未配置该类资源的Requests,那么在创建过程中系统会报验证错误。Pod里容器的Requests在未配置时,可以使用默认值(defaultRequest);如果未配置且没有使用默认值defaultRequest,那么Request默认等于该容器的Limits;如果容器的Limits也未定义,则会报错。
0

评论 (0)

取消