当多个应用共享固定节点数目的集群时,可能会出现某些应用过度使用系统资源,从而影响其他服务正常运行的情况。为了提升集群内应用运行的稳定性,尽量避免上述现象的发生,需要设定一些规则,来保证应用能获得其运行所需的合理资源。
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的值。
- 如果Pod配置的Requests和Limits值相等,那么该Pod可以获得的资源是完全可靠的。
如果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掉。
#未定义Requests值,默认等于Limits值
containers:
- name: foo
resources:
limits:
cpu: 10m
memory: 1Gi
- name: bar
resources:
limits:
cpu: 100m
memory: 100Mi
{/tabs-pane}
{tabs-pane label="G级示例2"}
#每个容器都定义了Requests和Limits,且两者的值相等
containers:
- name: foo
resources:
limits:
cpu: 10m
memory: 1Gi
requests:
cpu: 10m
memory: 1Gi
- name: bar
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
{/tabs-pane}
{tabs-pane label="BestEffort级示例1"}
#未定义资源配置
containers:
- name: foo
resources:
name: bar
resources:
{/tabs-pane}
{tabs-pane label="Bur级示例1"}
#Pod中有一个容器的Requests值和Limits值不同
containers:
- name: foo
resources:
limits:
cpu: 10m
memroy: 1Gi
requests:
cpu: 5m
memory: 1Gi
- name: bar
resources:
limits:
cpu: 10m
memory: 1Gi
request:
cpu: 10m
memory: 1Gi
{/tabs-pane}
{tabs-pane label="Bur级示例2"}
#容器bar未定义资源配置,容器foo定义了资源配置
containers:
- name: foo
resources:
limits:
cpu: 10m
memory: 1Gi
requests:
cpu: 10m
memory: 1Gi
- name: bar
{/tabs-pane}
{tabs-pane label="Bur级示例3"}
#容器foo未定义CPU,容器bar未定义内存
containers:
- name: foo
resources:
limits:
memory: 1Gi
- name: bar
resources:
limits:
cpu: 100m
{/tabs-pane}
{tabs-pane label="Bur级示例4"}
#容器bar未定义资源配置,容器foo未定义limits的值
containers:
- name: foo
resources:
requests:
cpu: 10m
memory: 1Gi
- name: bar
{/tabs-pane}
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的总上限 |
所有与 | |
所有与 | |
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 |
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-resourcequota
namespace: development
spec:
hard:
persistentvolumeclaims: "2" #最多定义2个PVC
services.loadbalancers: "2" #可以赋予公网访问地址的Service数量最多为2个
services.nodeports: "0" #禁止任何Service定义NodePort
pods: "4" #最多创建4个Pod
#所有Pod的Request CPU总和不超过1 CPU,limit总和不超过2 CPu。
#所有Pod的Request memory 总和不超过1Gi,limit总和不超过2Gi。
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
{/tabs-pane}
{tabs-pane label="示例2"}
---
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limitrange
namespace: development
spec:
limits:
- max:
cpu: "4"
memory: 2Gi
min:
cpu: 200m
memory: 6Mi
maxLimitRequestRatio: #限制了Pod中所有容器Limits值总和与Requests值总和的比例上限
cpu: 3
memory: 2
type: Pod
- default: #Pod中所有未指定limits值的容器的默认Limits值
cpu: 300m
memory: 200Mi
defaultRequest: #Pod中所有未指定requests值的容器的默认Requests值
cpu: 200m
memory: 100Mi
max: #Pod中所有容器的limits值上限
cpu: "2"
memory: 1Gi
min: #Pod中所有容器的requests值下限
cpu: 100m
memory: 3Mi
maxLimitRequestRatio: # Pod中所有容器的Limits值与Requests值的比例上限
cpu: 5
memory: 4
type: Container
#Min≤Deafult Request≤Default Limit≤Max
{/tabs-pane}
{tabs-pane label="示例3"}
#BestEffort级别的Pod数量最多为10个。
#NotBestEffort级别的Pod数量最多为4个,并且CPU request之和最大为1,CPU limit之和最大为2,memory request 之和最大为1Gi,memory limit之和最大为2Gi。
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: besteffort-resourcequota-development
namespace: development
spec:
hard:
pods: "10"
scopes:
- BestEffort
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: notbesteffort-resourcequota-development
spec:
hard:
pods: "4"
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
scopes:
- NotBestEffort
{/tabs-pane}
针对示例2的一些说明:
- 如果设置了Container的Max,则对于该类资源而言,整个集群中的所有容器都必须设置Limits,否则无法创建成功。在Pod内的容器未配置Limits时,将使用Default Limit的值,如果也未配置Default,则无法创建成功。
- 如果设置了Container的Min,那么对于该类资源而言,整个集群中的所有容器都必须设置Requests。如果在创建Pod的容器时未配置该类资源的Requests,那么在创建过程中系统会报验证错误。Pod里容器的Requests在未配置时,可以使用默认值(defaultRequest);如果未配置且没有使用默认值defaultRequest,那么Request默认等于该容器的Limits;如果容器的Limits也未定义,则会报错。
评论 (0)