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 通过以下机制实现资源管控:
- 命名空间隔离:不同团队工作在不同的命名空间中,通过 RBAC 实现访问控制
- 配额创建:管理员为每个命名空间创建 ResourceQuota 对象定义限制规则
- 准入控制:当用户创建资源时,API 服务器会检查是否违反配额限制
- 强制拒绝:如果请求超出配额,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> | 指定大小的巨页请求总数 |
配置示例:
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 的临时存储请求总和 |
多存储类配额示例:
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 数量
配置示例:
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个DeploymentResourceQuota 特性
配额作用域(Scopes)
ResourceQuota 可以设置作用域,只有匹配作用域的资源才会被计入配额。支持的作用域包括:
| 作用域 | 描述 | 跟踪的资源 |
|---|---|---|
Terminating | 匹配设置了 activeDeadlineSeconds 的 Pod | pods |
NotTerminating | 匹配未设置 activeDeadlineSeconds 的 Pod | pods, cpu, memory 等 |
BestEffort | 匹配 QoS 为 BestEffort 的 Pod | pods |
NotBestEffort | 匹配 QoS 不为 BestEffort 的 Pod | pods, cpu, memory 等 |
PriorityClass | 匹配特定优先级的 Pod | pods, cpu, memory 等 |
作用域使用规则:
- 不能在同一配额中同时设置
Terminating和NotTerminating - 不能在同一配额中同时设置
BestEffort和NotBestEffort
作用域选择器示例:
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 分配不同的资源量:
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 设置:
- 默认资源请求和限制
- 最小/最大资源限制
- 存储请求大小限制
典型工作流程:
- 管理员创建命名空间
- 设置 ResourceQuota 定义命名空间资源上限
- 设置 LimitRange 定义单个资源的默认值和限制范围
- 用户创建资源时:
- 未设置资源需求时使用 LimitRange 默认值
- 所有资源需求总和不能超过 ResourceQuota 限制
ResourceQuota 案例
基础配置步骤
步骤1:创建测试命名空间
kubectl create ns quota-demo步骤2:创建计算资源配额
# 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"kubectl apply -f compute-quota.yaml步骤3:验证配额状态
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
# 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"kubectl apply -f pod-valid.yaml # 成功创建案例2:创建超出配额的 Pod
# 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"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对象数量配额验证
创建对象数量配额:
# 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"kubectl apply -f object-counts.yaml测试创建多个 Pod:
kubectl create deployment nginx --image=nginx:1.19 -n quota-demo --replicas=5由于 Pod 数量限制为3,只有3个 Pod 能成功运行:
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 15sesourceQuota 常用命令
# 查看指定命名空间的所有 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、内存等),这会导致一系列问题:
- 资源浪费:开发者可能忘记设置资源限制,导致容器占用过多资源
- 资源争用:单个 Pod 或容器可能独占节点资源,影响其他应用性能
- 调度不稳定:未设置资源请求的 Pod 可能导致节点资源超卖,引发随机驱逐
- 配置不一致:不同团队设置的资源值差异过大,难以统一管理
LimitRange 通过命名空间级别的资源约束,有效解决了这些问题,确保集群资源得到合理分配和使用。
LimitRange 与 ResourceQuota 的关系
LimitRange 和 ResourceQuota 都是 Kubernetes 的资源管理机制,但侧重点不同:
| 特性 | LimitRange | ResourceQuota |
|---|---|---|
| 作用对象 | 命名空间内的单个 Pod/容器/PVC | 整个命名空间的资源总量 |
| 控制粒度 | 精细控制(单个对象) | 宏观控制(命名空间总量) |
| 主要功能 | 设置默认值、定义范围、控制比例 | 限制命名空间资源使用上限 |
| 使用场景 | 确保单个资源配置合理 | 防止命名空间耗尽集群资源 |
| 互补性 | 通常与 ResourceQuota 配合使用 | 依赖 LimitRange 提供默认值 |
最佳实践是将两者结合使用:LimitRange 确保单个 Pod/容器的资源配置合理,ResourceQuota 确保命名空间不会耗尽集群资源。
LimitRange 工作原理
LimitRange 通过 Kubernetes 的准入控制机制实现资源约束,具体流程如下:
- 管理员创建 LimitRange:在命名空间中定义资源限制规则
- 用户创建资源对象:尝试创建 Pod/PVC 等资源
- 准入控制器介入:
- 如果对象未设置资源需求,注入默认值(default/defaultRequest)
- 验证显式设置的资源值是否符合 min/max 范围
- 检查 limit/request 比率是否超过 maxLimitRequestRatio
- 创建结果:
- 验证通过:创建资源对象
- 验证失败:返回 HTTP 403 错误,拒绝创建
LimitRange 核心配置详解
LimitRange 对象结构
一个完整的 LimitRange 配置包含以下主要部分:
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 支持对三种类型的对象进行资源限制:
Container:针对 Pod 中的每个容器设置资源限制
- 控制单个容器的 CPU/内存 requests 和 limits
- 可设置默认值、最小/最大值、比例限制
Pod:针对整个 Pod 的资源总和设置限制
- 控制 Pod 中所有容器的 requests/limits 总和
- 仅支持设置 max 值(最大值限制)
PersistentVolumeClaim:针对存储声明设置限制
- 控制 PVC 的存储请求大小
- 可设置最小/最大存储容量
关键参数解析
min 和 max
min:指定资源请求(request)或限制(limit)的最小值
- 对于 CPU:通常以毫核为单位(如 "100m" 表示 0.1 核)
- 对于内存:通常以 MiB/GiB 为单位(如 "128Mi" 表示 128MB)
max:指定资源请求或限制的最大值
- 确保单个容器/Pod 不会占用过多资源
- 超过 max 的资源创建请求将被拒绝
示例:
min:
cpu: "100m"
memory: "128Mi"
max:
cpu: "1"
memory: "1Gi"default 和 defaultRequest
- default:当未指定资源限制(limits)时使用的默认限制值
- defaultRequest:当未指定资源请求(requests)时使用的默认请求值
这两个参数确保即使开发者忘记设置资源需求,容器也能获得合理的默认配置。
示例:
default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "250m"
memory: "256Mi"maxLimitRequestRatio
- 定义资源限制与请求之间的最大允许比率
- 防止资源配置严重失衡(如 limit 远大于 request)
- 计算公式:
limit/request ≤ maxLimitRequestRatio
示例:
maxLimitRequestRatio:
cpu: "2" # CPU limit 最多是 request 的2倍
memory: "1.5" # 内存 limit 最多是 request 的1.5倍LimitRange 案例
未设置资源需求的 Pod
创建不指定任何资源需求的 Pod:
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:
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:
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:
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 可确保:
- 每个团队的命名空间有统一的资源标准
- 防止某个团队的应用配置异常影响其他团队
- 通过默认值降低配置门槛,减少人为错误
配置示例:
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 防止过度超卖
生产环境示例:
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 进行约束:
- 防止申请过大存储造成浪费
- 确保存储请求满足最低要求
存储限制示例:
apiVersion: v1
kind: LimitRange
metadata:
name: storage-limits
spec:
limits:
- type: PersistentVolumeClaim
min:
storage: "1Gi" # 最小1GB
max:
storage: "50Gi" # 最大50GB与 ResourceQuota 的协同配置
典型的多层次资源管控方案:
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"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"工作流程:
- 开发者创建 Pod,未设置资源需求 → 使用 LimitRange 默认值
- 所有 Pod 的资源总和不能超过 ResourceQuota 限制
- 确保既有个体合理性,又有总量控制
LimitRange 管理命令
查看 LimitRange 列表:
bashkubectl get limitrange -n [命名空间]查看 LimitRange 详情:
bashkubectl describe limitrange [名称] -n [命名空间]创建 LimitRange:
bashkubectl apply -f limitrange.yaml删除 LimitRange:
bashkubectl delete limitrange [名称] -n [命名空间]
