Kubernetes 资源管理

Kubernetes 资源管理全解析:从配额控制到服务质量保障

目录

  • 引言:为什么 Kubernetes 资源管理至关重要
  • 第一章:ResourceQuota—— 命名空间的资源 “天花板”
    • 1.1 资源配额的核心价值:解决集群资源分配乱象
    • 1.2 定义 ResourceQuota:YAML 配置与核心参数解析
    • 1.3 实战:从零搭建 ResourceQuota 并验证效果
    • 1.4 ResourceQuota 的适用场景与注意事项
  • 第二章:LimitRange—— 单个资源的 “边界守护者”
    • 2.1 LimitRange 的核心作用:填补资源配额的 “漏洞”
    • 2.2 实战 1:为容器设置默认 CPU 与内存请求 / 限制
    • 2.3 实战 2:限制单个资源的最大 / 最小请求值
    • 2.4 实战 3:管控 PVC 存储申请的大小范围
    • 2.5 LimitRange 与 ResourceQuota 的协同策略
  • 第三章:QoS—— 资源紧张时的 “生存优先级”
    • 3.1 为什么需要 QoS:从资源不足到服务中断的连锁反应
    • 3.2 Kubernetes 的 3 种 QoS 级别:定义与核心差异
    • 3.3 实战:配置 Guaranteed、Burstable、BestEffort 级别的 Pod
    • 3.4 QoS 的实际应用:如何为业务匹配最优服务质量
  • 第四章:资源管理最佳实践与总结
    • 4.1 生产环境资源配置的 “黄金法则”
    • 4.2 常见资源管理问题与解决方案
    • 4.3 从资源管理到集群稳定性:全链路保障思路

引言:为什么 Kubernetes 资源管理至关重要

在 Kubernetes 集群中,“服务高可用” 从来不是单一维度的问题。即使应用配置了完美的健康检查、自动扩缩容和容错策略,一旦节点因资源分配不当 “宕机”,所有部署在该节点上的服务都可能受到波及。

想象这样一个场景:某公司的 Kubernetes 集群同时承载了开发、测试和生产环境的业务。开发团队为了快速验证功能,创建了 10 个未限制资源的 Pod;测试团队为了模拟高并发,启动了大量占用 CPU 的压测容器;而生产环境的核心数据库因节点内存被占满,突然被 “OOM 杀死”—— 这就是典型的 “资源失控” 灾难。

Kubernetes 资源管理的核心目标,就是通过 **“预防” 和 “调控”** 避免这类灾难:

  • 预防:通过资源配额限制命名空间的总资源使用,避免 “过量分配”;
  • 调控:通过默认资源限制避免单个 Pod 占用全部资源;
  • 优先级:通过服务质量(QoS)在资源紧张时优先保障核心业务。

本章将深入解析 Kubernetes 资源管理的三大核心工具 ——ResourceQuota、LimitRange 和 QoS,带你从理论到实战,构建稳定、可控的集群资源体系。

第一章:ResourceQuota—— 命名空间的资源 “天花板”

1.1 资源配额的核心价值:解决集群资源分配乱象

在单管理员维护的集群中,资源分配通常是可控的 —— 管理员清楚集群总资源(如 100 核 CPU、512GB 内存),并能合理分配给各个应用。但在多团队共享的集群中,问题会变得复杂:

  • 每个团队仅关注自身业务,不清楚集群总容量;
  • 未清理的废弃 Pod、Service 会持续占用资源;
  • 单个团队可能 “超额申请”,导致其他团队资源不足。

ResourceQuota(资源配额) 正是为解决这些问题而生:它为每个命名空间设定资源使用的 “总量上限”,包括 CPU、内存、Pod 数量、Service 数量等,确保单个命名空间的资源使用不超出集群承载能力。

举例来说,可为 “生产环境” 命名空间配置:

  • 最多启动 50 个 Pod;
  • CPU 请求总量不超过 16 核,上限不超过 32 核;
  • 内存请求总量不超过 64GB,上限不超过 128GB;
  • 最多创建 20 个 PVC(持久化存储声明)。

通过这种方式,既能保障生产环境有足够资源,又能避免资源浪费。

1.2 定义 ResourceQuota:YAML 配置与核心参数解析

ResourceQuota 与其他 Kubernetes 资源一样,通过 YAML 文件定义。以下是一个典型的 ResourceQuota 配置及参数说明:

yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: resource-test  # 资源配额名称
  namespace: prod  # 作用的命名空间(若不指定,默认作用于当前命名空间)
  labels:
    app: resourcequota
spec:
  hard:  # 硬限制(无法突破的上限)
    pods: "50"  # 最多创建50个Pod
    requests.cpu: "16"  # 所有Pod的CPU请求总量不超过16核
    requests.memory: "64Gi"  # 所有Pod的内存请求总量不超过64GB
    limits.cpu: "32"  # 所有Pod的CPU上限总量不超过32核
    limits.memory: "128Gi"  # 所有Pod的内存上限总量不超过128GB
    configmaps: "20"  # 最多创建20个ConfigMap
    secrets: "20"  # 最多创建20个Secret
    services: "30"  # 最多创建30个Service
    services.loadbalancers: "5"  # 最多创建5个LoadBalancer类型的Service
    persistentvolumeclaims: "10"  # 最多创建10个PVC
    requests.storage: "100Gi"  # 所有PVC的存储请求总量不超过100GB

核心参数说明

  • pods:限制命名空间内 Pod 的总数量(无论状态,包括 Running、Pending 等);
  • requests.xxx:所有 Pod 的 “初始资源请求”(requests)总和上限(xxx 可为 cpu、memory、storage);
  • limits.xxx:所有 Pod 的 “资源使用上限”(limits)总和上限;
  • 对象类参数(如 configmaps、secrets):限制特定资源的创建数量。

注意:ResourceQuota 仅作用于指定的命名空间,且仅对配置后创建的资源生效(已存在的资源不受影响)。

1.3 实战:从零搭建 ResourceQuota 并验证效果

下面通过实战演示 ResourceQuota 的使用流程,以 “限制 PVC 数量不超过 1 个” 为例。

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

首先创建一个独立的命名空间(避免影响其他资源):

bash

[root@k8s-master ~]# kubectl create ns quota-example
namespace/quota-example created
步骤 2:定义 ResourceQuota 配置文件

创建quota-objects.yaml,限制 PVC 数量上限为 1:

yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-demo  # 资源配额名称
  namespace: quota-example  # 作用的命名空间
spec:
  hard:
    persistentvolumeclaims: "1"  # PVC数量上限为1
步骤 3:创建 ResourceQuota

执行以下命令将配置应用到集群:

bash

[root@k8s-master ~]# kubectl create -f quota-objects.yaml
resourcequota/object-quota-demo created
步骤 4:查看资源配额状态

通过kubectl get quota查看配额信息:

bash

[root@k8s-master ~]# kubectl get quota object-quota-demo -n quota-example -o yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  creationTimestamp: "2023-08-19T08:10:19Z"
  name: object-quota-demo
  namespace: quota-example
spec:
  hard:
    persistentvolumeclaims: "1"
status:
  hard:
    persistentvolumeclaims: "1"
  used:
    persistentvolumeclaims: "0"  # 当前使用量为0
步骤 5:验证 PVC 限制效果

创建第一个 PVC(pvc.yaml):

yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-quota-demo
spec:
  storageClassName: manual  # 存储类(需提前创建)
  accessModes:
    - ReadWriteOnce  # 读写权限(单节点挂载)
  resources:
    requests:
      storage: 3Gi  # 请求3GB存储

创建 PVC 并查看配额状态:

bash

[root@k8s-master ~]# kubectl create -f pvc.yaml -n quota-example
persistentvolumeclaim/pvc-quota-demo created

# 再次查看配额:used变为1(已达到上限)
[root@k8s-master ~]# kubectl get quota object-quota-demo -n quota-example -o yaml
status:
  hard:
    persistentvolumeclaims: "1"
  used:
    persistentvolumeclaims: "1"

尝试创建第二个 PVC(pvc2.yaml):

yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-quota-demo2
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

创建时会提示 “超出配额”,无法创建:

bash

[root@k8s-master ~]# kubectl create -f pvc2.yaml -n quota-example
Error from server (Forbidden): error when creating "pvc2.yaml": persistentvolumeclaims "pvc-quota-demo2" is forbidden: exceeded quota: object-quota-demo, requested: persistentvolumeclaims=1, used: persistentvolumeclaims=1, limited: persistentvolumeclaims=1
步骤 6:清理环境

测试完成后,删除资源避免占用集群空间:

bash

# 删除PVC
[root@k8s-master ~]# kubectl delete -f pvc.yaml -n quota-example
persistentvolumeclaim "pvc-quota-demo" deleted

# 删除命名空间(会自动删除命名空间内的所有资源)
[root@k8s-master ~]# kubectl delete ns quota-example
namespace "quota-example" deleted

1.4 ResourceQuota 的适用场景与注意事项

适用场景
  1. 多团队共享集群:为开发、测试、生产团队分配独立命名空间,并设置不同配额(如生产环境配额更高);
  2. 资源成本控制:限制非核心业务的资源使用,避免浪费;
  3. 容量规划落地:根据集群总资源,将配额分配到各命名空间,确保不超额。
注意事项
  1. 命名空间隔离:ResourceQuota 仅作用于指定命名空间,需为每个需要限制的命名空间单独配置;
  2. 参数组合使用:建议同时限制 “资源总量”(如 requests.cpu)和 “对象数量”(如 pods),避免单一维度漏洞;
  3. 动态调整:若团队资源不足,可通过kubectl edit quota修改配额(需谨慎,避免突破集群总容量);
  4. 与 LimitRange 配合:ResourceQuota 限制总量,LimitRange 限制单个资源(如单个 Pod 的 CPU 上限),两者结合效果更佳。

第二章:LimitRange—— 单个资源的 “边界守护者”

2.1 LimitRange 的核心作用:填补资源配额的 “漏洞”

ResourceQuota 解决了 “总量控制” 问题,但存在两个明显漏洞:

  1. 未配置资源的 Pod 不受限:若一个 Pod 未设置 requests 和 limits,ResourceQuota 中对 CPU、内存的限制将失效;
  2. 单个 Pod 独占资源:即使命名空间有 16 核 CPU 配额,一个 Pod 若申请 16 核,仍会占用全部资源。

LimitRange(资源限制范围) 正是为填补这些漏洞而生:

  • 为未配置 requests/limits 的 Pod 设置默认值;
  • 限制单个资源的最大 / 最小 requests/limits;
  • 支持对容器、PVC 等资源的限制。

简单来说:ResourceQuota 是 “总量天花板”,LimitRange 是 “单个资源的边界”。

2.2 实战 1:为容器设置默认 CPU 与内存请求 / 限制

若 Pod 未配置 requests 和 limits,LimitRange 会自动添加默认值。以下是配置示例:

步骤 1:定义 LimitRange 配置

创建limitrange01.yaml,设置容器的默认资源参数:

yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-mem-limit-range  # 限制范围名称
spec:
  limits:
    - type: Container  # 作用对象为容器
      default:  # 未指定limits时的默认上限
        cpu: "1"  # 默认CPU上限1核
        memory: "512Mi"  # 默认内存上限512MiB
      defaultRequest:  # 未指定requests时的默认请求
        cpu: "500m"  # 默认CPU请求0.5核(1核=1000m)
        memory: "256Mi"  # 默认内存请求256MiB
步骤 2:创建 LimitRange

bash

[root@k8s-master ~]# kubectl create -f limitrange01.yaml
limitrange/cpu-mem-limit-range created
步骤 3:创建未配置资源的 Pod

创建pod-demo.yaml(不设置 requests 和 limits):

yaml

apiVersion: v1
kind: Pod
metadata:
  name: default-cpu-demo
spec:
  containers:
    - name: default-cpu-demo-ctr
      image: nginx  # 未配置resources字段
步骤 4:验证默认值是否生效

创建 Pod 后,查看其资源配置:

bash

[root@k8s-master ~]# kubectl create -f pod-demo.yaml
pod/default-cpu-demo created

# 查看Pod详情(重点看resources字段)
[root@k8s-master ~]# kubectl get pod default-cpu-demo -o yaml
spec:
  containers:
    - name: default-cpu-demo-ctr
      resources:
        limits:
          cpu: "1"
          memory: "512Mi"
        requests:
          cpu: "500m"
          memory: "256Mi"  # 自动添加了默认值

可见,未配置资源的 Pod 已被自动添加 LimitRange 中定义的默认值。

2.3 实战 2:限制单个资源的最大 / 最小请求值

除了默认值,LimitRange 还能限制单个资源的最大 / 最小值,避免资源独占。

步骤 1:定义最大 / 最小资源限制

创建limitrange02.yaml,限制 CPU 和内存的范围:

yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-min-max-demo-lr
spec:
  limits:
    - type: Container
      max:  # 最大限制
        cpu: "800m"  # CPU上限800m
        memory: "1Gi"  # 内存上限1Gi
      min:  # 最小限制
        cpu: "200m"  # CPU请求最小200m
        memory: "500Mi"  # 内存请求最小500Mi
步骤 2:测试限制效果

创建一个内存请求为 500Mi 的 Pod(符合 min 要求):

yaml

apiVersion: v1
kind: Pod
metadata:
  name: constraints-mem-demo-2
spec:
  containers:
    - name: constraints-mem-demo-2-ctr
      image: nginx
      resources:
        limits:
          memory: "500Mi"
        requests:
          memory: "500Mi"

创建成功;若将内存请求改为 400Mi(低于 min),则创建失败:

bash

Error from server (Forbidden): error when creating "pod-demo.yaml": pods "constraints-mem-demo-2" is forbidden: memory request 400Mi is below minimum 500Mi

2.4 实战 3:管控 PVC 存储申请的大小范围

LimitRange 不仅能限制容器,还能限制 PVC 的存储申请大小。

步骤 1:定义 PVC 存储限制

创建limitrange03.yaml,限制 PVC 的存储范围:

yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: storage-limits
spec:
  limits:
    - type: PersistentVolumeClaim  # 作用对象为PVC
      max:
        storage: "2Gi"  # 最大存储申请2Gi
      min:
        storage: "1Gi"  # 最小存储申请1Gi
步骤 2:测试 PVC 限制

创建一个申请 3Gi 存储的 PVC(超过 max):

yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc-hostpath
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: "3Gi"

创建失败,提示超出限制:

bash

Error from server (Forbidden): error when creating "pvc-hostpath.yaml": persistentvolumeclaims "mypvc-hostpath" is forbidden: maximum storage usage per PersistentVolumeClaim is 2Gi, but request is 3Gi

2.5 LimitRange 与 ResourceQuota 的协同策略

LimitRange 和 ResourceQuota 并非孤立存在,需协同使用才能实现完整的资源控制:

  1. 先配置 LimitRange:确保单个资源有合理边界,避免 “单个 Pod 独占”;
  2. 再配置 ResourceQuota:在边界内控制总量,避免 “总量超额”;
  3. 参数联动
    • 例如:LimitRange 设置单个 Pod 内存上限为 8Gi,ResourceQuota 设置命名空间内存总量为 64Gi,则最多可创建 8 个 Pod(8*8=64);
    • 避免 LimitRange 的 max * 最大 Pod 数量 > ResourceQuota 的总量,否则总量限制可能失效。

第三章:QoS—— 资源紧张时的 “生存优先级”

3.1 为什么需要 QoS:从资源不足到服务中断的连锁反应

即使配置了 ResourceQuota 和 LimitRange,仍可能面临 “资源紧张”:节点内存使用率达 90%、CPU 持续 100%。此时 Kubernetes 会通过 “杀死 Pod” 释放资源,但 “杀谁” 直接影响业务稳定性 —— 若杀死核心数据库 Pod,后果将远大于杀死非核心的日志收集 Pod。

QoS(Quality of Service,服务质量) 解决的就是 “资源紧张时优先保谁” 的问题:通过为 Pod 设置 QoS 级别,Kubernetes 在资源不足时会按优先级决定 “杀死顺序”。

3.2 Kubernetes 的 3 种 QoS 级别:定义与核心差异

Kubernetes 定义了 3 种 QoS 级别,优先级从高到低为:Guaranteed > Burstable > BestEffort。

QoS 级别 定义 资源配置要求 资源紧张时的命运
Guaranteed(保证级) 最高优先级,优先存活 所有容器的 requests 与 limits 相等(如 requests.cpu=1 核,limits.cpu=1 核) 最后被杀死(仅当其他级别 Pod 被杀死后仍资源不足时)
Burstable(弹性级) 中优先级 至少一个容器设置了 requests,且 requests < limits(如 requests.cpu=0.5 核,limits.cpu=1 核) 先于 Guaranteed 被杀死,后于 BestEffort
BestEffort(尽力而为级) 最低优先级 所有容器均未设置 requests 和 limits 最先被杀死

3.3 实战:配置 Guaranteed、Burstable、BestEffort 级别的 Pod

以下通过实战演示 3 种 QoS 级别的配置方法。

准备工作:创建测试命名空间

bash

[root@k8s-master ~]# kubectl create namespace qos-example
namespace/qos-example created
实战 1:配置 Guaranteed 级 Pod

需满足 “所有容器的 requests 与 limits 相等”:

创建qos-pod.yaml

yaml

apiVersion: v1
kind: Pod
metadata:
  name: qos-demo
  namespace: qos-example
spec:
  containers:
    - name: qos-demo-ctr
      image: nginx:1.7.9
      resources:
        limits:
          cpu: "700m"  # limits与requests相等
          memory: "200Mi"
        requests:
          cpu: "700m"
          memory: "200Mi"

创建后查看 QoS 级别:

bash

[root@k8s-master ~]# kubectl create -f qos-pod.yaml
pod/qos-demo created

# 查看QoS字段(qosClass: Guaranteed)
[root@k8s-master ~]# kubectl get pod qos-demo -n qos-example -o yaml | grep qosClass
  qosClass: Guaranteed
实战 2:配置 Burstable 级 Pod

需满足 “至少一个容器有 requests,且 requests < limits”:

创建qos-pod-2.yaml

yaml

apiVersion: v1
kind: Pod
metadata:
  name: qos-demo-2
  namespace: qos-example
spec:
  containers:
    - name: qos-demo-2-ctr
      image: nginx:1.7.9
      resources:
        limits:
          memory: "200Mi"  # limits > requests
        requests:
          memory: "100Mi"

创建后查看 QoS 级别:

bash

[root@k8s-master ~]# kubectl create -f qos-pod-2.yaml
pod/qos-demo-2 created

# 查看QoS字段(qosClass: Burstable)
[root@k8s-master ~]# kubectl get pod qos-demo-2 -n qos-example -o yaml | grep qosClass
  qosClass: Burstable
实战 3:配置 BestEffort 级 Pod

需满足 “所有容器均未设置 requests 和 limits”:

创建qos-pod-3.yaml

yaml

apiVersion: v1
kind: Pod
metadata:
  name: qos-demo-3
  namespace: qos-example
spec:
  containers:
    - name: qos-demo-3-ctr
      image: nginx:1.7.9
      # 不配置resources字段

创建后查看 QoS 级别:

bash

[root@k8s-master ~]# kubectl create -f qos-pod-3.yaml
pod/qos-demo-3 created

# 查看QoS字段(qosClass: BestEffort)
[root@k8s-master ~]# kubectl get pod qos-demo-3 -n qos-example -o yaml | grep qosClass
  qosClass: BestEffort

3.4 QoS 的实际应用:如何为业务匹配最优服务质量

核心原则:按业务重要性分配 QoS 级别
  1. 核心业务(如数据库、支付服务):配置为 Guaranteed,确保资源紧张时最后被杀死;
  2. 非核心但有资源需求的业务(如报表生成):配置为 Burstable,允许弹性使用资源,同时避免最先被杀死;
  3. 临时 / 低优先级业务(如日志清理脚本):配置为 BestEffort,不占用固定资源,资源紧张时优先释放。
配置建议
  • Guaranteed 配置:内存 requests = 实际运行最小内存(如程序启动至少需 2GB,则 requests.memory=2GB,limits.memory=2GB);
  • Burstable 配置:requests = 最小需求,limits = 最大可容忍上限(如 requests.cpu=0.5 核,limits.cpu=2 核,避免占用过多资源);
  • 避免 “过度保障”:若所有 Pod 均配置为 Guaranteed,资源紧张时 Kubernetes 将随机杀死 Pod,失去优先级意义。

第四章:资源管理最佳实践与总结

4.1 生产环境资源配置的 “黄金法则”

  1. 内存配置优先精准:内存是 “不可压缩资源”(不足时必 OOM),需按程序实际需求设置 requests(如程序稳定运行需 4GB,则 requests.memory=4GB);
  2. CPU 配置留有余地:CPU 是 “可压缩资源”(不足时仅变慢),limits 可略高于实际需求(如日常使用 0.5 核,limits.cpu=1 核);
  3. 分层限制:从 “单个 Pod(LimitRange)→ 命名空间(ResourceQuota)→ 集群(总量)” 分层控制,避免单一环节失效;
  4. QoS 与业务绑定:定期梳理业务优先级,核心业务必须配置为 Guaranteed,非核心业务合理使用 Burstable。

4.2 常见资源管理问题与解决方案

问题 原因 解决方案
Pod 创建失败,提示 “超出 ResourceQuota” 命名空间资源使用已达上限 1. 清理废弃资源(如无用 Pod、PVC);2. 临时提高配额(需评估集群容量)
Pod 未配置资源,导致节点资源被占满 未配置 LimitRange,未限制未设置资源的 Pod 为所有命名空间配置 LimitRange,设置默认 requests/limits
核心 Pod 在资源紧张时被杀死 核心 Pod 未配置为 Guaranteed 将核心 Pod 的 requests 与 limits 设为相等,确保 QoS 为 Guaranteed
PVC 申请存储失败,提示 “超出 LimitRange” 申请大小超出 PVC 的 max 限制 调整申请大小或修改 LimitRange 的 max 值(需确保不突破 ResourceQuota)

4.3 从资源管理到集群稳定性:全链路保障

Kubernetes 资源管理不是孤立的,需与其他功能协同:

  • 健康检查:配合 livenessProbe 和 readinessProbe,确保资源不足时 Pod 能被正确检测并重启;
  • 自动扩缩容:结合 HPA(Horizontal Pod Autoscaler),在资源使用率高时自动扩容,避免单个 Pod 压力过大;
  • 节点亲和性:将核心 Pod 调度到资源充足的节点,降低资源竞争风险。

只有将资源管理与这些功能结合,才能构建真正稳定、高效的 Kubernetes 集群。

你可能感兴趣的:(Kubernetes 资源管理)