Skip to content

Kubernets-资源管理

k8s集群中为了能够使系统正常稳定运行,通常会限制Pod的资源使用情况,在k8s集群中如果有一个程序出现异常,并占用大量的系统资源。如果未对该Pod进行资源限制的话,可能会影响其他的Pod。

k8s常见的资源管理方式

  • 计算资源管理(Compute Resources): 为Pod中的容器指定使用的计算资源(CPU和内存)。

  • 资源的配置范围管理(LimitRange):可以对集群内Request和Limits的配置做一个全局的统一的限制,相当于批量设置了某一个范围内(某个命名空间)的Pod的资源使用限制。

  • 资源的配额管理(Resource Quotas):可以为每一个命名空间(namespace)提供一个总体的资源使用限制,通过它可以限制命名空间中某个类型的对象的总数目上限,也可以设置命名空间中Pod可以使用到的计算资源的总上限。资源的配额管理有效解决了多用户或多个团队公用一个k8s集群时资源有效分配的问题。

ResourceQuota 资源配额

ResourceQuota 是 Kubernetes 中用于限制命名空间资源使用量的核心机制,它如同集群资源的"守门人",确保多租户环境下资源的公平分配与合理使用。本文将深入剖析 ResourceQuota 的工作原理、配置方法、高级特性以及最佳实践,帮助您全面掌握这一关键工具。

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

  • 不同的团队可以在不同的命名空间下工作,目前这是非约束性的,在未来的版本中可能会通过 ACL(Access Control List 访问控制列表) 来实现强制性约束。
  • 集群管理员可以为每个命名空间创建一个或多个资源配额对象。
  • 当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会 跟踪集群的资源使用情况,以确保使用的资源用量不超过资源配额中定义的硬性资源限额。
  • 如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。
  • 如果命名空间下的计算资源 (如 cpu 和 memory)的配额被启用,则用户必须为 这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。

ResourceQuota 核心概念与工作原理

什么是 ResourceQuota?

ResourceQuota 是 Kubernetes 提供的命名空间级资源配额管理机制,它通过定义硬性限制来:

  • 限制命名空间中可使用的计算资源(CPU/内存)和存储资源总量
  • 控制命名空间中特定类型对象(如 Pod、Service 等)的数量上限

典型应用场景包括:

  • 多租户隔离:防止某个团队占用过多集群资源而影响其他团队
  • 成本控制:在公有云环境中限制资源使用量以控制成本
  • 稳定性保障:避免资源耗尽导致的集群不稳定

核心工作原理

ResourceQuota 通过以下机制实现资源管控:

  1. 命名空间隔离:不同团队工作在不同的命名空间中,通过 RBAC 实现访问控制
  2. 配额创建:管理员为每个命名空间创建 ResourceQuota 对象定义限制规则
  3. 准入控制:当用户创建资源时,API 服务器会检查是否违反配额限制
  4. 强制拒绝:如果请求超出配额,API 服务器返回 HTTP 403 Forbidden 错误

特殊要求

  • 对于 CPU 和内存资源,Pod 必须明确指定 requests 或 limits,否则创建会被拒绝
  • 可使用 LimitRange 准入控制器为未设置资源需求的 Pod 提供默认值

ResourceQuota 的三种主要类型

计算资源配额

计算资源配额限制命名空间内可请求的计算资源总量,支持以下资源类型:

资源名称描述
limits.cpu所有非终止状态 Pod 的 CPU 限制总和
limits.memory所有非终止状态 Pod 的内存限制总和
requests.cpu所有非终止状态 Pod 的 CPU 请求总和
requests.memory所有非终止状态 Pod 的内存请求总和
hugepages-<size>指定大小的巨页请求总数

配置示例

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-resources
spec:
  hard:
    requests.cpu: "1"       # CPU请求总量不超过1核
    requests.memory: 1Gi     # 内存请求总量不超过1GB
    limits.cpu: "2"         # CPU限制总量不超过2核
    limits.memory: 2Gi      # 内存限制总量不超过2GB
    hugepages-2Mi: "4Gi"    # 2MB巨页请求不超过4GB

存储资源配额

存储资源配额限制命名空间内的存储资源使用,包括持久化存储和临时存储:

资源名称描述
requests.storage所有 PVC 的存储请求总和
persistentvolumeclaims允许的 PVC 总数
<storage-class>.storageclass.storage.k8s.io/requests.storage特定存储类的存储请求总和
requests.ephemeral-storage所有 Pod 的临时存储请求总和

多存储类配额示例

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: storage-resources
spec:
  hard:
    requests.storage: 100Gi                  # 所有存储类总量限制
    gold.storageclass.storage.k8s.io/requests.storage: 50Gi   # 黄金存储类限制
    bronze.storageclass.storage.k8s.io/requests.storage: 10Gi # 青铜存储类限制
    persistentvolumeclaims: "20"             # PVC总数限制

对象数量配额

对象数量配额限制命名空间中特定类型 Kubernetes 对象的数量,语法格式为:

  • 核心组资源:count/<resource>(如 count/pods
  • 非核心组资源:count/<resource>.<group>(如 count/deployments.apps

常见可限制对象

  • count/pods - 非终止状态的 Pod 数量
  • count/services - Service 数量
  • count/secrets - Secret 数量
  • count/configmaps - ConfigMap 数量
  • count/deployments.apps - Deployment 数量

配置示例

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-counts
spec:
  hard:
    count/pods: "50"               # 最多50个Pod
    count/services: "10"           # 最多10个Service
    count/secrets: "20"            # 最多20个Secret
    count/deployments.apps: "5"    # 最多5个Deployment

ResourceQuota 特性

配额作用域(Scopes)

ResourceQuota 可以设置作用域,只有匹配作用域的资源才会被计入配额。支持的作用域包括:

作用域描述跟踪的资源
Terminating匹配设置了 activeDeadlineSeconds 的 Podpods
NotTerminating匹配未设置 activeDeadlineSeconds 的 Podpods, cpu, memory 等
BestEffort匹配 QoS 为 BestEffort 的 Podpods
NotBestEffort匹配 QoS 不为 BestEffort 的 Podpods, cpu, memory 等
PriorityClass匹配特定优先级的 Podpods, cpu, memory 等

作用域使用规则

  • 不能在同一配额中同时设置 TerminatingNotTerminating
  • 不能在同一配额中同时设置 BestEffortNotBestEffort

作用域选择器示例

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: scope-selector
spec:
  hard:
    pods: "10"
    cpu: "1"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values: ["high"]    # 仅对优先级为high的Pod生效

基于优先级的资源配额

从 Kubernetes 1.17 开始稳定支持基于 Pod 优先级的配额控制,允许为不同优先级的 Pod 分配不同的资源量:

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pods-high
spec:
  hard:
    cpu: "1000"
    memory: 200Gi
    pods: "10"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values: ["high"]    # 仅限制高优先级Pod

这种机制特别适合确保关键业务应用能获得所需资源,同时限制低优先级应用的资源使用。

配额与 LimitRange 的协同工作

ResourceQuota 通常与 LimitRange 配合使用,形成完整的资源管控体系:

  • ResourceQuota:控制命名空间资源总量
  • LimitRange:为单个容器/Pod 设置:
    • 默认资源请求和限制
    • 最小/最大资源限制
    • 存储请求大小限制

典型工作流程

  1. 管理员创建命名空间
  2. 设置 ResourceQuota 定义命名空间资源上限
  3. 设置 LimitRange 定义单个资源的默认值和限制范围
  4. 用户创建资源时:
    • 未设置资源需求时使用 LimitRange 默认值
    • 所有资源需求总和不能超过 ResourceQuota 限制

ResourceQuota 案例

基础配置步骤

步骤1:创建测试命名空间

bash
kubectl create ns quota-demo

步骤2:创建计算资源配额

yaml
# compute-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: quota-demo
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi
    pods: "5"
bash
kubectl apply -f compute-quota.yaml

步骤3:验证配额状态

bash
kubectl get quota -n quota-demo
kubectl describe quota compute-quota -n quota-demo

输出示例:

Name:            compute-quota
Namespace:       quota-demo
Resource         Used  Hard
--------         ----  ----
limits.cpu       0     2
limits.memory    0     2Gi
pods             0     5
requests.cpu     0     1
requests.memory  0     1Gi

配额限制验证案例

案例1:创建合规 Pod

yaml
# pod-valid.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-valid
  namespace: quota-demo
spec:
  containers:
  - name: nginx
    image: nginx:1.19
    resources:
      requests:
        cpu: "500m"
        memory: "512Mi"
      limits:
        cpu: "1"
        memory: "1Gi"
bash
kubectl apply -f pod-valid.yaml  # 成功创建

案例2:创建超出配额的 Pod

yaml
# pod-invalid.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-invalid
  namespace: quota-demo
spec:
  containers:
  - name: nginx
    image: nginx:1.19
    resources:
      requests:
        cpu: "1.5"    # 超过requests.cpu配额(1)
        memory: "512Mi"
      limits:
        cpu: "2"
        memory: "1Gi"
bash
kubectl apply -f pod-invalid.yaml

预期错误:

Error from server (Forbidden): error when creating "pod-invalid.yaml": pods "pod-invalid" is forbidden: exceeded quota: compute-quota, requested: requests.cpu=1.5, used: requests.cpu=0.5, limited: requests.cpu=1

对象数量配额验证

创建对象数量配额

yaml
# object-counts.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-counts
  namespace: quota-demo
spec:
  hard:
    count/pods: "3"
    count/services: "2"
    count/secrets: "5"
bash
kubectl apply -f object-counts.yaml

测试创建多个 Pod

bash
kubectl create deployment nginx --image=nginx:1.19 -n quota-demo --replicas=5

由于 Pod 数量限制为3,只有3个 Pod 能成功运行:

bash
kubectl get pods -n quota-demo

输出:

NAME                     READY   STATUS    RESTARTS   AGE
nginx-6799fc88d8-4bn6x   1/1     Running   0          15s
nginx-6799fc88d8-8wq5k   1/1     Running   0          15s
nginx-6799fc88d8-kx9g7   1/1     Running   0          15s

esourceQuota 常用命令

bash
# 查看指定命名空间的所有 ResourceQuota
kubectl get resourcequotas -n <namespace>

# 查看所有命名空间的 ResourceQuota
kubectl get resourcequotas --all-namespaces

# 使用缩写形式
kubectl get quota -n <namespace>

# 查看特定 ResourceQuota 的详细配置
kubectl describe resourcequota <quota-name> -n <namespace>

# 示例:查看 dev 命名空间中 compute-quota 的详情
kubectl describe resourcequota compute-quota -n dev

# 删除指定的 ResourceQuota
kubectl delete resourcequota <quota-name> -n <namespace>

# 通过 YAML 文件删除
kubectl delete -f quota.yaml -n <namespace>

LimitRange

LimitRange 是 Kubernetes 中用于精细控制命名空间内资源分配的核心机制,它如同资源分配的"精密调节器",能够为容器和 Pod 设置默认资源值、定义资源使用范围,并确保资源配置的合理性。本文将系统性地介绍 LimitRange 的核心概念、工作原理、配置方法、使用场景以及最佳实践,帮助您全面掌握这一关键资源管理工具。

LimitRange 核心概念与价值

LimitRange 是什么?

LimitRange 是 Kubernetes 中的一种策略对象,用于约束命名空间内各种资源对象(如 Pod 和 PersistentVolumeClaim)的资源分配量。它主要提供以下关键功能:

  • 设置默认值:为未指定资源需求的 Pod 或容器自动注入合理的资源请求(request)和限制(limit)值
  • 定义资源范围:约束 Pod 或容器能够使用的资源最小值和最大值,防止配置不合理
  • 控制比例关系:限制资源请求值与限制值之间的比例,避免资源分配失衡
  • 存储限制:对 PersistentVolumeClaim 设置最小和最大存储空间限制

为什么需要 LimitRange?

在 Kubernetes 集群中,容器默认可以无限制地使用计算资源(CPU、内存等),这会导致一系列问题:

  1. 资源浪费:开发者可能忘记设置资源限制,导致容器占用过多资源
  2. 资源争用:单个 Pod 或容器可能独占节点资源,影响其他应用性能
  3. 调度不稳定:未设置资源请求的 Pod 可能导致节点资源超卖,引发随机驱逐
  4. 配置不一致:不同团队设置的资源值差异过大,难以统一管理

LimitRange 通过命名空间级别的资源约束,有效解决了这些问题,确保集群资源得到合理分配和使用。

LimitRange 与 ResourceQuota 的关系

LimitRange 和 ResourceQuota 都是 Kubernetes 的资源管理机制,但侧重点不同:

特性LimitRangeResourceQuota
作用对象命名空间内的单个 Pod/容器/PVC整个命名空间的资源总量
控制粒度精细控制(单个对象)宏观控制(命名空间总量)
主要功能设置默认值、定义范围、控制比例限制命名空间资源使用上限
使用场景确保单个资源配置合理防止命名空间耗尽集群资源
互补性通常与 ResourceQuota 配合使用依赖 LimitRange 提供默认值

最佳实践是将两者结合使用:LimitRange 确保单个 Pod/容器的资源配置合理,ResourceQuota 确保命名空间不会耗尽集群资源。

LimitRange 工作原理

LimitRange 通过 Kubernetes 的准入控制机制实现资源约束,具体流程如下:

  1. 管理员创建 LimitRange:在命名空间中定义资源限制规则
  2. 用户创建资源对象:尝试创建 Pod/PVC 等资源
  3. 准入控制器介入
    • 如果对象未设置资源需求,注入默认值(default/defaultRequest)
    • 验证显式设置的资源值是否符合 min/max 范围
    • 检查 limit/request 比率是否超过 maxLimitRequestRatio
  4. 创建结果
    • 验证通过:创建资源对象
    • 验证失败:返回 HTTP 403 错误,拒绝创建

LimitRange 核心配置详解

LimitRange 对象结构

一个完整的 LimitRange 配置包含以下主要部分:

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: [LimitRange名称]
  namespace: [命名空间名称]
spec:
  limits:
  - type: [限制类型] # Pod/Container/PersistentVolumeClaim
    # 容器/Pod级别配置
    min:  						# 资源最小值
      cpu: "100m"
      memory: "128Mi"
    max:  						# 资源最大值
      cpu: "1"
      memory: "1Gi"
    default:  					# 默认限制值
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:  			# 默认请求值
      cpu: "250m"
      memory: "256Mi"
    maxLimitRequestRatio:  		# 限制与请求的最大比率
      cpu: "2"
      memory: "1.5"

支持的限制类型

LimitRange 支持对三种类型的对象进行资源限制:

  1. Container:针对 Pod 中的每个容器设置资源限制

    • 控制单个容器的 CPU/内存 requests 和 limits
    • 可设置默认值、最小/最大值、比例限制
  2. Pod:针对整个 Pod 的资源总和设置限制

    • 控制 Pod 中所有容器的 requests/limits 总和
    • 仅支持设置 max 值(最大值限制)
  3. PersistentVolumeClaim:针对存储声明设置限制

    • 控制 PVC 的存储请求大小
    • 可设置最小/最大存储容量

关键参数解析

min 和 max

  • min:指定资源请求(request)或限制(limit)的最小值

    • 对于 CPU:通常以毫核为单位(如 "100m" 表示 0.1 核)
    • 对于内存:通常以 MiB/GiB 为单位(如 "128Mi" 表示 128MB)
  • max:指定资源请求或限制的最大值

    • 确保单个容器/Pod 不会占用过多资源
    • 超过 max 的资源创建请求将被拒绝

示例:

yaml
min:
  cpu: "100m"
  memory: "128Mi"
max:
  cpu: "1"
  memory: "1Gi"

default 和 defaultRequest

  • default:当未指定资源限制(limits)时使用的默认限制值
  • defaultRequest:当未指定资源请求(requests)时使用的默认请求值

这两个参数确保即使开发者忘记设置资源需求,容器也能获得合理的默认配置。

示例:

yaml
default:
  cpu: "500m"
  memory: "512Mi"
defaultRequest:
  cpu: "250m"
  memory: "256Mi"

maxLimitRequestRatio

  • 定义资源限制与请求之间的最大允许比率
  • 防止资源配置严重失衡(如 limit 远大于 request)
  • 计算公式:limit/request ≤ maxLimitRequestRatio

示例:

yaml
maxLimitRequestRatio:
  cpu: "2"    # CPU limit 最多是 request 的2倍
  memory: "1.5" # 内存 limit 最多是 request 的1.5倍

LimitRange 案例

未设置资源需求的 Pod

创建不指定任何资源需求的 Pod:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-limitrange-pod
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: Never

结果

  • LimitRange 会注入默认的 requests 和 limits
  • 查看 Pod 配置可见自动添加的资源设置:
    yaml
          resources:
            limits:
              cpu: 100m
              memory: 128Mi
            requests:
              cpu: 100m
              memory: 128Mi

设置部分资源需求的 Pod

创建只设置 requests 的 Pod:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: dmeo-limitrage
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: Never
    resources:
      requests:
        cpu: "180m"
        memory: "180Mi"

结果

  • requests 使用用户指定的值
  • limits 使用 LimitRange 的默认值:
    yaml
          resources:
            limits:				# pod 资源未定义limits会使用LimitRange的default的值
              cpu: 500m
              memory: 512Mi
            requests:
              cpu: 180m
              memory: 180Mi

设置 limits 但未设置 requests 的 Pod

创建只设置 limits 的 Pod:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: limit-only-spec
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: Never
    resources:
      limits:
        cpu: "300m"
        memory: "300Mi"

结果

  • Kubernetes 会将 requests 设置为与 limits 相同的值:
    yaml
    resources:
      limits:
        cpu: "300m"
        memory: "300Mi"
      requests:
        cpu: "300m"
        memory: "300Mi"

违反 min/max 限制的 Pod

尝试创建 requests 小于 min 的 Pod:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: invalid-resource-spec
spec:
  containers:
  - name: nginx
    image: nginx:1.19
    resources:
      limits:
        cpu: "300m"
        memory: "300Mi"
      requests:
        cpu: "80m"   # 小于 min.cpu (100m)
        memory: "80Mi" # 小于 min.memory (100Mi)

结果

  • API 服务器返回 403 错误:
    Error from server (Forbidden): error when creating "pod.yaml": pods "invalid-resource-spec" is forbidden: 
    [minimum cpu usage per Container is 100m, but request is 80m, 
    minimum memory usage per Container is 100Mi, but request is 80Mi]

多租户环境资源隔离

在多团队共享的 Kubernetes 集群中,LimitRange 可确保:

  • 每个团队的命名空间有统一的资源标准
  • 防止某个团队的应用配置异常影响其他团队
  • 通过默认值降低配置门槛,减少人为错误

配置示例

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: team-a-limits
  namespace: team-a
spec:
  limits:
  - type: Container
    min:
      cpu: "100m"
      memory: "256Mi"
    max:
      cpu: "2"
      memory: "4Gi"
    default:
      cpu: "500m"
      memory: "1Gi"
    defaultRequest:
      cpu: "250m"
      memory: "512Mi"

关键应用资源保障

对于关键业务应用,可通过 LimitRange 确保:

  • 设置较高的 min 值,防止资源不足
  • 限制非关键应用的 max 值,避免资源争用
  • 通过 maxLimitRequestRatio 防止过度超卖

生产环境示例

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: critical-app-limits
  namespace: production
spec:
  limits:
  - type: Container
    min:  # 关键应用最小需求
      cpu: "500m"
      memory: "1Gi"
    max:
      cpu: "4"
      memory: "8Gi"
    defaultRequest:
      cpu: "1"
      memory: "2Gi"
    maxLimitRequestRatio:
      cpu: "1.5"  # 严格限制超卖比例
      memory: "1.2"

存储资源限制

LimitRange 可对 PersistentVolumeClaim 进行约束:

  • 防止申请过大存储造成浪费
  • 确保存储请求满足最低要求

存储限制示例

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: storage-limits
spec:
  limits:
  - type: PersistentVolumeClaim
    min:
      storage: "1Gi"  # 最小1GB
    max:
      storage: "50Gi" # 最大50GB

与 ResourceQuota 的协同配置

典型的多层次资源管控方案:

  1. LimitRange:确保单个 Pod/容器的资源配置合理

    yaml
    # limitrange.yaml
    apiVersion: v1
    kind: LimitRange
    metadata:
      name: default-limits
    spec:
      limits:
      - type: Container
        default:
          cpu: "500m"
          memory: "512Mi"
        defaultRequest:
          cpu: "250m"
          memory: "256Mi"
  2. ResourceQuota:限制命名空间资源总量

    yaml
    # quota.yaml
    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: team-quota
    spec:
      hard:
        requests.cpu: "10"
        requests.memory: "20Gi"
        limits.cpu: "20"
        limits.memory: "40Gi"
  3. 工作流程

    • 开发者创建 Pod,未设置资源需求 → 使用 LimitRange 默认值
    • 所有 Pod 的资源总和不能超过 ResourceQuota 限制
    • 确保既有个体合理性,又有总量控制

LimitRange 管理命令

  • 查看 LimitRange 列表

    bash
    kubectl get limitrange -n [命名空间]
  • 查看 LimitRange 详情

    bash
    kubectl describe limitrange [名称] -n [命名空间]
  • 创建 LimitRange

    bash
    kubectl apply -f limitrange.yaml
  • 删除 LimitRange

    bash
    kubectl delete limitrange [名称] -n [命名空间]