Kubernetes 资源配额详解:ResourceQuota 与 LimitRange
前言
Request/Limit 基本概念
K8S支持在容器界别设置Request和Limit来约束容器所使用的CPU和Memory。
-
Request表示在应用发布时,对容器所使用CPU和Memory的预估,提出的申请。K8S会根据当前工作节点的资源情况,进行调度决策,K8S会把POD调度到满足资源需求的节点上去运行。如果请求的资源不能得到满足,那发布的POD会处于Pending状态。
-
Limit表示容器运行时对资源需求的限制,如果容器的CPU使用量达到或超过限制,K8S会限制容器对CPU资源的额外使用。如果容器的内存使用量达到或超过限制,K8S会Kill掉POD。
一、资源配额
资源配额,通过 ResourceQuota 对象来定义,对每个命名空间的资源消耗总量提供限制。 它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命名空间中的 Pod 可以使用的计算资源的总上限。
K8s中对资源的限制分以下情况:
-
对namespace中容器、pod等使用总和限制:
ResourceQuota
-
对namespace中容器、pod等使用单独限制:
LimitRange
资源配额的工作方式如下:
-
不同的团队可以在不同的命名空间下工作。这可以通过 RBAC 强制执行。
-
集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。
-
当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会跟踪集群的资源使用情况, 以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。
-
如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。
-
如果命名空间下的计算资源 (如 cpu 和 memory)的配额被启用, 则用户必须为这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。
说明:
-
对于 cpu 和 memory 资源:ResourceQuota 强制该命名空间中的每个(新)Pod 为该资源设置限制。 如果你在命名空间中为 cpu 和 memory 实施资源配额, 你或其他客户端必须为你提交的每个新 Pod 指定该资源的 requests 或 limits。 否则,控制平面可能会拒绝接纳该 Pod。
-
对于其他资源:ResourceQuota 可以工作,并且会忽略命名空间中的 Pod,而无需为该资源设置限制或请求。 这意味着,如果资源配额限制了此命名空间的临时存储,则可以创建没有限制/请求临时存储的新 Pod。 你可以使用限制范围自动设置对这些资源的默认请求。
1.1 计算资源配额
用户可以对给定命名空间下的可被请求的 计算资源 总量进行限制。
资源名称 |
描述 |
limits.cpu |
所有非终止状态的 Pod,其 CPU 限额总量不能超过该值。 |
limits.memory |
所有非终止状态的 Pod,其内存限额总量不能超过该值。 |
requests.cpu |
所有非终止状态的 Pod,其 CPU 需求总量不能超过该值。 |
requests.memory |
所有非终止状态的 Pod,其内存需求总量不能超过该值。 |
hugepages-<size> |
对于所有非终止状态的 Pod,针对指定尺寸的巨页请求总数不能超过此值。 |
cpu |
与 requests.cpu 相同。 |
memory |
与 requests.memory 相同 |
1.2 存储资源配额
用户可以对给定命名空间下的存储资源 总量进行限制。
资源名称 |
资源描述 |
requests.storage |
所有 PVC,存储资源的需求总量不能超过该值。 |
persistentvolumeclaims |
在该命名空间中所允许的 PVC 总量 |
<storage-class-name>.storageclass.storage.k8s.io/requests.storage |
在所有与 <storage-class-name> 相关的持久卷申领中,存储请求的总和不能超过该值。 |
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims |
在与 storage-class-name 相关的所有持久卷申领中,命名空间中可以存在的持久卷申领总数。 |
例如,如果一个操作人员针对 gold 存储类型与 bronze 存储类型设置配额, 操作人员可以定义如下配额:
-
gold.storageclass.storage.k8s.io/requests.storage: 500Gi
-
bronze.storageclass.storage.k8s.io/requests.storage: 100Gi
在 Kubernetes 1.8 版本中,本地临时存储的配额支持已经是 Alpha 功能:
资源名称 |
资源描述 |
requests.ephemeral-storage |
在命名空间的所有 Pod 中,本地临时存储请求的总和不能超过此值。 |
limits.ephemeral-storage |
在命名空间的所有 Pod 中,本地临时存储限制值的总和不能超过此值。 |
ephemeral-storage |
与 requests.ephemeral-storage 相同。 |
说明:
如果所使用的是 CRI 容器运行时,容器日志会被计入临时存储配额。 这可能会导致存储配额耗尽的 Pods 被意外地驱逐出节点。 参考日志架构 了解详细信息。
1.3 对象数量配额
你可以使用以下语法对所有标准的、命名空间域的资源类型进行配额设置:
-
count/<resource>.<group>:用于非核心(core)组的资源
-
count/<resource>:用于核心组的资源
这是用户可能希望利用对象计数配额来管理的一组资源示例。
-
count/persistentvolumeclaims
-
count/services
-
count/secrets
-
count/configmaps
-
count/replicationcontrollers
-
count/deployments.apps
-
count/replicasets.apps
-
count/statefulsets.apps
-
count/jobs.batch
-
count/cronjobs.batch
相同语法也可用于自定义资源。 例如,要对 example.com API 组中的自定义资源 widgets 设置配额,请使用 count/widgets.example.com。
当使用 count/* 资源配额时,如果对象存在于服务器存储中,则会根据配额管理资源。 这些类型的配额有助于防止存储资源耗尽。例如,用户可能想根据服务器的存储能力来对服务器中 Secret 的数量进行配额限制。 集群中存在过多的 Secret 实际上会导致服务器和控制器无法启动。 用户可以选择对 Job 进行配额管理,以防止配置不当的 CronJob 在某命名空间中创建太多 Job 而导致集群拒绝服务。
对有限的一组资源上实施一般性的对象数量配额也是可能的。
支持以下类型:
资源名称 |
描述 |
configmaps |
在该命名空间中允许存在的 ConfigMap 总数上限。 |
persistentvolumeclaims |
在该命名空间中允许存在的 PVC 的总数上限。 |
pods |
在该命名空间中允许存在的非终止状态的 Pod 总数上限。Pod 终止状态等价于 Pod 的 .status.phase in (Failed, Succeeded) 为真。 |
replicationcontrollers |
在该命名空间中允许存在的 ReplicationController 总数上限。 |
resourcequotas |
在该命名空间中允许存在的 ResourceQuota 总数上限。 |
services |
在该命名空间中允许存在的 Service 总数上限。 |
services.loadbalancers |
在该命名空间中允许存在的 LoadBalancer 类型的 Service 总数上限。 |
services.nodeports |
在该命名空间中允许存在的 NodePort 类型的 Service 总数上限。 |
secrets |
在该命名空间中允许存在的 Secret 总数上限。 |
1.4 配额作用域
每个配额都有一组相关的 scope(作用域),配额只会对作用域内的资源生效。 配额机制仅统计所列举的作用域的交集中的资源用量。
当一个作用域被添加到配额中后,它会对作用域相关的资源数量作限制。 如配额中指定了允许(作用域)集合之外的资源,会导致验证错误。
作用域 |
描述 |
Terminating |
匹配所有 spec.activeDeadlineSeconds 不小于 0 的 Pod。 |
NotTerminating |
匹配所有 spec.activeDeadlineSeconds 是 nil 的 Pod。 |
BestEffort |
匹配所有 Qos 是 BestEffort 的 Pod。 |
NotBestEffort |
匹配所有 Qos 不是 BestEffort 的 Pod。 |
PriorityClass |
匹配所有引用了所指定的优先级类的 Pods。 |
CrossNamespacePodAffinity |
匹配那些设置了跨名字空间 (反)亲和性条件的 Pod。 |
二、ResourceQuota
ResourceQuota是Kubernetes中的一种资源配额对象,它允许管理员为Namespace设置资源使用限制。管理员可以通过ResourceQuota来限制一个Namespace中每种资源的总量和每个对象的最大使用量,包括CPU、内存、存储卷、Pod等。当Namespace中的资源使用量超出ResourceQuota限制时,Kubernetes将不允许创建新的资源,直到资源使用量下降到规定的限制范围内。ResourceQuota可以帮助管理员更好地管理集群资源,避免资源被耗尽导致应用程序崩溃的情况发生。
resourcequota的资源清单
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
spec:
hard:
pods: "4"
configmaps: "10"
persistentvolumeclaims: "4"
replicationcontrollers: "20"
secrets: "10"
services: "10"
services.loadbalancers: "2"
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-demo
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
以上yaml文件定义的就是说:
ResourceQuota 在 quota-mem-cpu-example 命名空间中设置了如下要求:
每个容器必须有内存请求和限制,以及 CPU 请求和限制。
所有容器的内存请求总和不能超过1 GiB。
所有容器的内存限制总和不能超过2 GiB。
所有容器的 CPU 请求总和不能超过1 cpu。
所有容器的 CPU 限制总和不能超过2 cpu。
三、LimitRange
资源的配置范围管理(LimitRange):可以对集群内Request和Limits的配置做一个全局的统一的限制,相当于批量设置了某一个范围内(某个命名空间)的Pod的资源使用限制。
一个LimitRange资源对象可以提供的功能
-
在一个命名空间中实施对每个 Pod 或 Container 最小和最大的资源使用量的限制。
-
在一个命名空间中实施对每个 PersistentVolumeClaim 能申请的最小和最大的存储空间大小的限制。
-
在一个命名空间中实施对一种资源的申请值和限制值的比值的控制。
-
设置一个命名空间中对计算资源的默认申请/限制值,并且自动的在运行时注入到多个 Container 中
LimitRange资源清单
apiVersion: v1
kind: LimitRange
metadata:
name: limitrange
namespace: test
spec:
limits:
- type: Container #限制的资源类型
max:
cpu: "2" #限制单个容器的最大CPU
memory: "2Gi" #限制单个容器的最大内存
min:
cpu: "500m" #限制单个容器的最小CPU
memory: "512Mi" #限制单个容器的最小内存
default:
cpu: "500m" #默认单个容器的CPU限制
memory: "512Mi" #默认单个容器的内存限制
defaultRequest:
cpu: "500m" #默认单个容器的CPU创建请求
memory: "512Mi" #默认单个容器的内存创建请求
maxLimitRequestRatio:
cpu: 2 #限制CPU limit/request比值最大为2
memory: 2 #限制内存limit/request比值最大为1.5
- type: Pod
max:
cpu: "4" #限制单个Pod的最大CPU
memory: "4Gi" #限制单个Pod最大内存
- type: PersistentVolumeClaim
max:
storage: 50Gi #限制PVC最大的requests.storage
min:
storage: 30Gi #限制PVC最小的requests.storage
更多推荐
所有评论(0)