k8s 资源配额 quota
-
资源配额 原文
当多个用户或团队共享具有固定节点数目的集群时,人们会担心有人使用超过其基于公平原则所分配到的资源量。
资源配额是帮助管理员解决这一问题的工具。
资源配额,通过
ResourceQuota对象来定义,对每个命名空间的资源消耗总量提供限制。它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命令空间中的 Pod 可以使用的计算资源的总上限。资源配额的工作方式如下:
- 不同的团队可以在不同的命名空间下工作,目前这是非约束性的,在未来的版本中可能会通过 ACL (Access Control List 访问控制列表) 来实现强制性约束。
- 集群管理员可以为每个命名空间创建一个或多个资源配额对象。
- 当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会跟踪集群的资源使用情况,以确保使用的资源用量不超过资源配额中定义的硬性资源限额。
- 如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN),并在消息中给出有可能违反的约束。
- 如果命名空间下的计算资源 (如
cpu和memory)的配额被启用,则用户必须为这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用LimitRanger准入控制器来为没有设置计算资源需求的 Pod 设置默认值。 若想避免这类问题,请参考演练中的示例。
下面是使用命名空间和配额构建策略的示例:
- 在具有 32 GiB 内存和 16 核 CPU 资源的集群中,允许 A 团队使用 20 GiB 内存 和 10 核的 CPU 资源,允许 B 团队使用 10 GiB 内存和 4 核的 CPU 资源,并且预留 2 GiB 内存和 2 核的 CPU 资源供将来分配。
- 限制 "testing" 命名空间使用 1 核 CPU 资源和 1GiB 内存。允许 "production" 命名空间使用任意数量。
在集群容量小于各命名空间配额总和的情况下,可能存在资源竞争。资源竞争时,Kubernetes 系统会遵循先到先得的原则。
不管是资源竞争还是配额的修改,都不会影响已经创建的资源使用对象。
启用资源配额
资源配额的支持在很多 Kubernetes 版本中是默认开启的。当 apiserver
--enable-admission-plugins=参数中包含ResourceQuota时,资源配额会被启用。当命名空间中存在一个
ResourceQuota对象时,对于该命名空间而言,资源配额就是开启的。计算资源配额
用户可以对给定命名空间下的可被请求的计算资源总量进行限制。
配额机制所支持的资源类型:
资源名称 描述 limits.cpu所有非终止状态的 Pod,其 CPU 限额总量不能超过该值。 limits.memory所有非终止状态的 Pod,其内存限额总量不能超过该值。 requests.cpu所有非终止状态的 Pod,其 CPU 需求总量不能超过该值。 requests.memory所有非终止状态的 Pod,其内存需求总量不能超过该值。 扩展资源的资源配额
除上述资源外,在 Kubernetes 1.10 版本中,还添加了对扩展资源的支持。
由于扩展资源不可超量分配,因此没有必要在配额中为同一扩展资源同时指定
requests和limits。对于扩展资源而言,目前仅允许使用前缀为requests.的配额项。以 GPU 拓展资源为例,如果资源名称为
nvidia.com/gpu,并且要将命名空间中请求的 GPU 资源总数限制为 4,则可以如下定义配额:requests.nvidia.com/gpu: 4
有关更多详细信息,请参阅查看和设置配额。
存储资源配额
用户可以对给定命名空间下的存储资源总量进行限制。
此外,还可以根据相关的存储类(Storage Class)来限制存储资源的消耗。
资源名称 描述 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: 500Gibronze.storageclass.storage.k8s.io/requests.storage: 100Gi
在 Kubernetes 1.8 版本中,本地临时存储的配额支持已经是 Alpha 功能:
资源名称 描述 requests.ephemeral-storage在命名空间的所有 Pod 中,本地临时存储请求的总和不能超过此值。 limits.ephemeral-storage在命名空间的所有 Pod 中,本地临时存储限制值的总和不能超过此值。 对象数量配额
Kubernetes 1.9 版本增加了使用以下语法对所有标准的、命名空间域的资源类型进行配额设置的支持。
count/<resource>.<group>
这是用户可能希望利用对象计数配额来管理的一组资源示例。
count/persistentvolumeclaimscount/servicescount/secretscount/configmapscount/replicationcontrollerscount/deployments.appscount/replicasets.appscount/statefulsets.appscount/jobs.batchcount/cronjobs.batchcount/deployments.extensions
Kubernetes 1.15 版本增加了对使用相同语法来约束自定义资源的支持。 例如,要对
example.comAPI 组中的自定义资源widgets设置配额,请使用count/widgets.example.com。当使用
count/*资源配额时,如果对象存在于服务器存储中,则会根据配额管理资源。 这些类型的配额有助于防止存储资源耗尽。例如,用户可能想根据服务器的存储能力来对服务器中 Secret 的数量进行配额限制。集群中存在过多的 Secret 实际上会导致服务器和控制器无法启动!用户可以选择对 Job 进行配额管理,以防止配置不当的 CronJob 在某命名空间中创建太多作业而导致集群拒绝服务。在 Kubernetes 1.9 版本之前,可以在有限的一组资源上实施一般性的对象数量配额。 此外,还可以进一步按资源的类型设置其配额。
支持以下类型:
资源名称 描述 configmaps在该命名空间中允许存在的 ConfigMap 总数上限。 persistentvolumeclaims在该命名空间中允许存在的 PVC 的总数上限。 pods在该命名空间中允许存在的非终止状态的 pod 总数上限。Pod 终止状态等价于 Pod 的 .status.phase in (Failed, Succeeded)= truereplicationcontrollers在该命名空间中允许存在的 RC 总数上限。 resourcequotas在该命名空间中允许存在的资源配额总数上限。 services在该命名空间中允许存在的 Service 总数上限。 services.loadbalancers在该命名空间中允许存在的 LoadBalancer 类型的服务总数上限。 services.nodeports在该命名空间中允许存在的 NodePort 类型的服务总数上限。 secrets在该命名空间中允许存在的 Secret 总数上限。 例如,
pods配额统计某个命名空间中所创建的、非终止状态的Pod个数并确保其不超过某上限值。用户可能希望在某命名空间中设置pods配额,以避免有用户创建很多小的 Pod,从而耗尽集群所能提供的 Pod IP 地址。配额作用域
每个配额都有一组相关的作用域(scope),配额只会对作用域内的资源生效。配额机制仅统计所列举的作用域的交集中的资源用量。
当一个作用域被添加到配额中后,它会对作用域相关的资源数量作限制。 如配额中指定了允许(作用域)集合之外的资源,会导致验证错误。
作用域 描述 Terminating匹配所有 spec.activeDeadlineSeconds不小于 0 的 Pod。NotTerminating匹配所有 spec.activeDeadlineSeconds是 nil 的 Pod。BestEffort匹配所有 Qos 是 BestEffort 的 Pod。 NotBestEffort匹配所有 Qos 不是 BestEffort 的 Pod。 BestEffort作用域限制配额跟踪以下资源:podsTerminating、NotTerminating和NotBestEffort这三种作用域限制配额跟踪以下资源:cpulimits.cpulimits.memorymemorypodsrequests.cpurequests.memory
基于优先级类(PriorityClass)来设置资源配额
FEATURE STATE:Kubernetes 1.12 [beta]Pod 可以创建为特定的优先级。 通过使用配额规约中的
scopeSelector字段,用户可以根据 Pod 的优先级控制其系统资源消耗。仅当配额规范中的
scopeSelector字段选择到某 Pod 时,配额机制才会匹配和计量 Pod 的资源消耗。本示例创建一个配额对象,并将其与具有特定优先级的 Pod 进行匹配。 该示例的工作方式如下:
- 集群中的 Pod 可取三个优先级类之一,即 "low"、"medium"、"high"。
- 为每个优先级创建一个配额对象。
将以下 YAML 保存到文件
quota.yml中。apiVersion: v1 kind: List items: - apiVersion: v1 kind: ResourceQuota metadata: name: pods-high spec: hard: cpu: "1000" memory: 200Gi pods: "10" scopeSelector: matchExpressions: - operator : In scopeName: PriorityClass values: ["high"] - apiVersion: v1 kind: ResourceQuota metadata: name: pods-medium spec: hard: cpu: "10" memory: 20Gi pods: "10" scopeSelector: matchExpressions: - operator : In scopeName: PriorityClass values: ["medium"] - apiVersion: v1 kind: ResourceQuota metadata: name: pods-low spec: hard: cpu: "5" memory: 10Gi pods: "10" scopeSelector: matchExpressions: - operator : In scopeName: PriorityClass values: ["low"]使用
kubectl create命令运行以下操作。kubectl create -f ./quota.ymlresourcequota/pods-high created resourcequota/pods-medium created resourcequota/pods-low created使用
kubectl describe quota操作验证配额的Used值为0。kubectl describe quotaName: pods-high Namespace: default Resource Used Hard -------- ---- ---- cpu 0 1k memory 0 200Gi pods 0 10 Name: pods-low Namespace: default Resource Used Hard -------- ---- ---- cpu 0 5 memory 0 10Gi pods 0 10 Name: pods-medium Namespace: default Resource Used Hard -------- ---- ---- cpu 0 10 memory 0 20Gi pods 0 10创建优先级为 "high" 的 Pod。 将以下 YAML 保存到文件
high-priority-pod.yml中。apiVersion: v1 kind: Pod metadata: name: high-priority spec: containers: - name: high-priority image: ubuntu command: ["/bin/sh"] args: ["-c", "while true; do echo hello; sleep 10;done"] resources: requests: memory: "10Gi" cpu: "500m" limits: memory: "10Gi" cpu: "500m" priorityClassName: high使用
kubectl create运行以下操作。kubectl create -f ./high-priority-pod.yml确认 "high" 优先级配额
pods-high的 "Used" 统计信息已更改,并且其他两个配额未更改。kubectl describe quotaName: pods-high Namespace: default Resource Used Hard -------- ---- ---- cpu 500m 1k memory 10Gi 200Gi pods 1 10 Name: pods-low Namespace: default Resource Used Hard -------- ---- ---- cpu 0 5 memory 0 10Gi pods 0 10 Name: pods-medium Namespace: default Resource Used Hard -------- ---- ---- cpu 0 10 memory 0 20Gi pods 0 10scopeSelector在operator字段中支持以下值:InNotInExistDoesNotExist
请求与限制
分配计算资源时,每个容器可以为 CPU 或内存指定请求和约束。 配额可以针对二者之一进行设置。
如果配额中指定了
requests.cpu或requests.memory的值,则它要求每个容器都显式给出对这些资源的请求。同理,如果配额中指定了limits.cpu或limits.memory的值,那么它要求每个容器都显式设定对应资源的限制。查看和设置配额
Kubectl 支持创建、更新和查看配额:
kubectl create namespace myspacecat <<EOF > compute-resources.yaml apiVersion: v1 kind: ResourceQuota metadata: name: compute-resources spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi requests.nvidia.com/gpu: 4 EOFkubectl create -f ./compute-resources.yaml --namespace=myspacecat <<EOF > object-counts.yaml apiVersion: v1 kind: ResourceQuota metadata: name: object-counts spec: hard: configmaps: "10" persistentvolumeclaims: "4" pods: "4" replicationcontrollers: "20" secrets: "10" services: "10" services.loadbalancers: "2" EOFkubectl create -f ./object-counts.yaml --namespace=myspacekubectl get quota --namespace=myspaceNAME AGE compute-resources 30s object-counts 32skubectl describe quota compute-resources --namespace=myspaceName: compute-resources Namespace: myspace Resource Used Hard -------- ---- ---- limits.cpu 0 2 limits.memory 0 2Gi requests.cpu 0 1 requests.memory 0 1Gi requests.nvidia.com/gpu 0 4kubectl describe quota object-counts --namespace=myspaceName: object-counts Namespace: myspace Resource Used Hard -------- ---- ---- configmaps 0 10 persistentvolumeclaims 0 4 pods 0 4 replicationcontrollers 0 20 secrets 1 10 services 0 10 services.loadbalancers 0 2kubectl 还使用语法
count/<resource>.<group>支持所有标准的、命名空间域的资源的对象计数配额:kubectl create namespace myspacekubectl create quota test --hard=count/deployments.extensions=2,count/replicasets.extensions=4,count/pods=3,count/secrets=4 --namespace=myspacekubectl run nginx --image=nginx --replicas=2 --namespace=myspacekubectl describe quota --namespace=myspaceName: test Namespace: myspace Resource Used Hard -------- ---- ---- count/deployments.extensions 1 2 count/pods 2 3 count/replicasets.extensions 1 4 count/secrets 1 4配额和集群容量
资源配额与集群资源总量是完全独立的。它们通过绝对的单位来配置。所以,为集群添加节点时,资源配额不会自动赋予每个命名空间消耗更多资源的能力。
有时可能需要资源配额支持更复杂的策略,比如:
- 在几个团队中按比例划分总的集群资源。
- 允许每个租户根据需要增加资源使用量,但要有足够的限制以防止资源意外耗尽。
- 探测某个命名空间的需求,添加物理节点并扩大资源配额值。
这些策略可以通过将资源配额作为一个组成模块、手动编写一个控制器来监控资源使用情况,并结合其他信号调整命名空间上的硬性资源配额来实现。
注意:资源配额对集群资源总体进行划分,但它对节点没有限制:来自不同命名空间的 Pod 可能在同一节点上运行。
默认情况下限制特定优先级的资源消耗
有时候可能希望当且仅当某名字空间中存在匹配的配额对象时,才可以创建特定优先级(例如 "cluster-services")的 Pod。
通过这种机制,操作人员能够将限制某些高优先级类仅出现在有限数量的命名空间中,而并非每个命名空间默认情况下都能够使用这些优先级类。
要实现此目的,应使用 kube-apiserver 标志
--admission-control-config-file传递如下配置文件的路径:apiVersion: apiserver.config.k8s.io/v1 kind: AdmissionConfiguration plugins: - name: "ResourceQuota" configuration: apiVersion: apiserver.config.k8s.io/v1 kind: ResourceQuotaConfiguration limitedResources: - resource: pods matchScopes: - scopeName: PriorityClass operator: In values: ["cluster-services"]现在,仅当命名空间中存在匹配的
scopeSelector的配额对象时,才允许使用 "cluster-services" Pod。示例:
scopeSelector: matchExpressions: - scopeName: PriorityClass operator: In values: ["cluster-services"]有关更多信息,请参见 LimitedResources 和优先级类配额支持的设计文档。
浙公网安备 33010602011771号