Kubernetes ResourceQuota 及 调度原理

本文详细阐述了Kubernetes中的资源配额系统如何在命名空间层面管理资源消耗,包括CPU、内存、对象数量、存储配额及优先级控制。重点讲解了ResourceQuota对象、LimitRange和节点亲和性的使用,以及如何通过策略避免资源滥用和优化Pod调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

资源配额:

当多个用户或团队共享具有固定节点数目的集群时,人们会担心有人使用超过其基于公平原则所分配到的资源量。

资源配额是帮助管理员解决这一问题的工具。

资源配额,通过 ResourceQuota 对象来定义,对每个命名空间的资源消耗总量提供限制。 它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命令空间中的 Pod 可以使用的计算资源的总上限。

资源配额的工作方式如下:

不同的团队可以在不同的命名空间下工作,目前这是非约束性的,在未来的版本中可能会通过 ACL (Access Control List 访问控制列表) 来实现强制性约束。

集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。

当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会 跟踪集群的资源使用情况,以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。

如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。

如果命名空间下的计算资源 (如 cpu 和 memory)的配额被启用,则用户必须为 这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。

ResourceQuota 对象的名称必须是合法的 DNS 子域名。

在集群容量小于各命名空间配额总和的情况下,可能存在资源竞争。资源竞争时,Kubernetes 系统会遵循先到先得的原则。

启用资源配额 :

资源配额的支持在很多 Kubernetes 版本中是默认启用的。 当 API 服务器 的命令行标志 --enable-admission-plugins= 中包含 ResourceQuota 时, 资源配额会被启用。
当命名空间中存在一个 ResourceQuota 对象时,对于该命名空间而言,资源配额就是开启的。

计算资源配额 :

在这里插入图片描述

对象数量配额:

你可以使用以下语法对所有标准的、命名空间域的资源类型进行配额设置:

count/.:用于非核心(core)组的资源
count/:用于核心组的资源
这是用户可能希望利用对象计数配额来管理的一组资源示例。

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 而导致集群拒绝服务

在这里插入图片描述
例如,pods 配额统计某个命名空间中所创建的、非终止状态的 Pod 个数并确保其不超过某上限值。 用户可能希望在某命名空间中设置 pods 配额,以避免有用户创建很多小的 Pod, 从而耗尽集群所能提供的 Pod IP 地址。

存储资源配额:

用户可以对给定命名空间下的存储资源 总量进行限制。

此外,还可以根据相关的存储类(Storage Class)来限制存储资源的消耗
在这里插入图片描述
例如,如果一个操作人员针对 gold 存储类型与 bronze 存储类型设置配额, 操作人员可以定义如下配额:

gold.storageclass.storage.k8s.io/requests.storage: 500Gi
bronze.storageclass.storage.k8s.io/requests.storage: 100Gi

基于优先级类(PriorityClass)来设置资源配额 :

FEATURE STATE: Kubernetes v1.17 [stable]
Pod 可以创建为特定的优先级。 通过使用配额规约中的 scopeSelector 字段,用户可以根据 Pod 的优先级控制其系统资源消耗。

仅当配额规范中的 scopeSelector 字段选择到某 Pod 时,配额机制才会匹配和计量 Pod 的资源消耗。

如果配额对象通过 scopeSelector 字段设置其作用域为优先级类,则配额对象只能 跟踪以下资源:

pods
cpu
memory
ephemeral-storage
limits.cpu
limits.memory
limits.ephemeral-storage
requests.cpu
requests.memory
requests.ephemeral-storage

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"]

创建优先级为 “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 describe quota

限制范围LimitRange:

	默认情况下, Kubernetes 集群上的容器运行使用的计算资源没有限制。 使用资源配额,集群管理员可以以名字空间为单位,限制其资源的使用与创建。 在命名空间中,一个 Pod 或 Container 最多能够使用命名空间的资源配额所定义的 CPU 和内存用量。 有人担心,一个 Pod 或 Container 会垄断所有可用的资源。 LimitRange 是在命名空间内限制资源分配(给多个 Pod 或 Container)的策略对象。

一个 LimitRange(限制范围) 对象提供的限制能够做到:
1.在一个命名空间中实施对每个 Pod 或 Container 最小和最大的资源使用量的限制。
2.在一个命名空间中实施对每个 PersistentVolumeClaim 能申请的最小和最大的存储空间大小的限制。
3.在一个命名空间中实施对一种资源的申请值和限制值的比值的控制。
4.设置一个命名空间中对计算资源的默认申请/限制值,并且自动的在运行时注入到多个 Container 中。

apiVersion: v1
kind: Pod
metadata:
  name: constraints-cpu-demo
spec:
  containers:
  - name: constraints-cpu-demo-ctr
    image: nginx
    resources:
      limits:
        cpu: "800m"
      requests:
        cpu: "500m"

在这里插入图片描述
ResourceQuota: CPU,内存都限制
limitRange: 只给了CPU的合法区间
以后pod只需要写内存的合法,limitrange都指定范围,pod可以不用指定

ResourceQuota 用来限制 namespace 中所有的 Pod 占用的总的资源 request 和 limit
LimitRange 用来限制 namespace 中 单个Pod 默认资源 request 和 limit

nodeSelector:

nodeSelector 是节点选择约束的最简单推荐形式。
你可以将 nodeSelector 字段添加到 Pod 的规约中设置你希望目标节点所具有的节点标签。
Kubernetes 只会将 Pod 调度到拥有你所指定的每个标签的节点上。

亲和性的设置如下:

kubectl explain pod.spec.affinity

KIND:     Pod
VERSION:  v1

RESOURCE: affinity <Object>

DESCRIPTION:
     If specified, the pod's scheduling constraints

     Affinity is a group of affinity scheduling rules.

FIELDS:
   nodeAffinity <Object> :指定亲和的节点(机器)

   podAffinity  <Object> :指定亲和的pod,这个pod部署到哪里看他亲和的pod在哪里

   podAntiAffinity      <Object> pod的反亲和。
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution: # 硬性过滤:排除不具备指定label的node
        nodeSelectorTerms:
        - matchExpressions: #所有matchExpressions满足条件才行
          - key: kubernetes.io/os
            operator: In
            values:
            - linux
#DuringScheduling (调度期间有效)IgnoredDuringExecution(执行期间忽略):亲和策略与反亲和策略只在pod调度期间有效,执行期间(Pod运行期间)会被忽略。
      preferredDuringSchedulingIgnoredDuringExecution: # 软性平分:不具备指定label的node打低分,降低node被选中的几率
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: k8s.gcr.io/pause:2.0
apiVersion: v1
kind: Pod
metadata:
  name: "busy-affinity-shib"
  namespace: default
  labels:
    app: "busy-affinity-shib"
spec:
  containers:
    - name: busy-affinity-shib
      image: "busybox"
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:  ## 软性分
        - preference: ## 指定我们喜欢的条件  shib
            matchExpressions:
              - key: disk
                values: ["400"]
                operator: Gt
          weight: 90 # 权重 0-100
        - preference: ## 指定我们喜欢的条件
            matchExpressions:
              - key: gpu
                values: ["40000"]
                operator: Gt  # node1的gpu不满足这个条件
          weight: 10 # 权重 0-100

            # requiredDuringSchedulingIgnoredDuringExecution: ## 硬标准
            #   nodeSelectorTerms:
            #   - matchExpressions:
            #       - key: disktype
            #         values: ["ssd","hdd"]
            #         operator: In
            # In(disktype只要是"ssd"或者"hdd"),
            # NotIn(disktype只要不是"ssd"或者"hdd"),
            # Exists(disktype只要存在,无论值是什么,value不用写),
            # DoesNotExist(disktype只要不存在,无论值是什么,value不用写),
            # Gt(key大于指定的值的节点),
          # Lt(key小于指定的值的节点)

          ## FailedScheduling  26s   default-scheduler  0/3 nodes are available:
          # 1 node(s) had taint {node-role.kubernetes.io/master: },
          # that the pod didn't tolerate, (一个节点不能调)
          # 2 node(s) didn't match Pod's node affinity/selector.(两个节点不满足)
          # kubectl
          # 标签打上以后就分配成功

在这里插入图片描述

nodeAffinity:

KIND:     Pod
VERSION:  v1

RESOURCE: nodeAffinity <Object>

DESCRIPTION:
     Describes node affinity scheduling rules for the pod.

     Node affinity is a group of node affinity scheduling rules.

FIELDS:
   preferredDuringSchedulingIgnoredDuringExecution      <[]Object>
     The scheduler will prefer to schedule pods to nodes that satisfy the
     affinity expressions specified by this field, but it may choose a node that
     violates one or more of the expressions. The node that is most preferred is
     the one with the greatest sum of weights, i.e. for each node that meets all
     of the scheduling requirements (resource request, requiredDuringScheduling
     affinity expressions, etc.), compute a sum by iterating through the
     elements of this field and adding "weight" to the sum if the node matches
     the corresponding matchExpressions; the node(s) with the highest sum are
     the most preferred.

   requiredDuringSchedulingIgnoredDuringExecution       <Object>
     If the affinity requirements specified by this field are not met at
     scheduling time, the pod will not be scheduled onto the node. If the
     affinity requirements specified by this field cease to be met at some point
     during pod execution (e.g. due to an update), the system may or may not try
     to eventually evict the pod from its node.
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/os
            operator: In
            values:
            - linux
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: k8s.gcr.io/pause:2.0

affinity:

nodeName:

nodeName 是比亲和性或者 nodeSelector 更为直接的形式。nodeName 是 Pod 规约中的一个字段。如果 nodeName 字段不为空,调度器会忽略该 Pod, 而指定节点上的 kubelet 会尝试将 Pod 放到该节点上。 使用 nodeName 规则的优先级会高于使用 nodeSelector 或亲和性与非亲和性的规则。
使用 nodeName 来选择节点的方式有一些局限性:

如果所指代的节点不存在,则 Pod 无法运行,而且在某些情况下可能会被自动删除。
如果所指代的节点无法提供用来运行 Pod 所需的资源,Pod 会失败, 而其失败原因中会给出是否因为内存或 CPU 不足而造成无法运行。
在云环境中的节点名称并不总是可预测的,也不总是稳定的。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: kube-01

污点和容忍度:

污点和容忍度
节点亲和性 是 Pod 的一种属性,它使 Pod 被吸引到一类特定的节点 (这可能出于一种偏好,也可能是硬性要求)。 污点(Taint)则相反——它使节点能够排斥一类特定的 Pod。

容忍度(Toleration)是应用于 Pod 上的,允许(但并不要求)Pod 调度到带有与之匹配的污点的节点上。

污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod,是不会被该节点接受的。

#给节点添加污点
#给节点 node1 增加一个污点,它的键名是 key1,键值是 value1,效果是 NoSchedule。 这表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到 node1 这个节点。

kubectl taint nodes node1 key1=value1:NoSchedule

#移除污点
kubectl taint nodes node1 key1=value1:NoSchedule-

key1=value1
value1可以为空

NoSchedule: 不调度。不给我这里调度pod
**PreferNoSchedule:**比NoSchedule更宽容一些,Kubernetes将尽量避免将没有匹配容忍的pod调度到该节点上,但是并不是不可以
NoExecute: 不能在节点上运行(如果已经运行,将被驱逐)
master节点默认是有一个污点的:
在这里插入图片描述

这里是一个使用了容忍度的 Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "example-key"
    operator: "Exists"
    effect: "NoSchedule"

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"

tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoSchedule"

operator 的默认值是 Equal。

一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:
如果 operator 是 Exists (此时容忍度不能指定 value),或者
如果 operator 是 Equal ,则它们的 value 应该相等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值