Kubernetes资源配额治理实战:ResourceQuota与LimitRange精准管控集群资源

为什么集群必须有资源配额

没有资源配额的Kubernetes集群,和一个没有红绿灯的十字路口效果相同。任何一个开发者部署一个resources未设limits的Pod,就能吃掉整台节点的CPU和内存,把同节点的其他服务挤到OOM。这不是理论风险——线上集群跑了一段时间后,一个忘了加limits的批处理任务吃掉节点96%内存,导致该节点所有Pod被驱逐,就是真实的生产事故。

Kubernetes提供两层配额机制:ResourceQuota在namespace级别限制资源总量,LimitRange在Pod/容器级别约束每个资源对象的默认值和上下限。两层配合才能形成完整的防护网。

ResourceQuota配置与实战

ResourceQuota限制一个namespace的资源使用总量。典型场景:一个多租户集群,每个团队一个namespace,限制每个团队最多用100个CPU核和200GB内存。

apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-alpha-quota
  namespace: team-alpha
spec:
  hard:
    # 计算资源
    requests.cpu: "100"
    requests.memory: "200Gi"
    limits.cpu: "200"
    limits.memory: "400Gi"
    # 对象数量
    pods: "500"
    services: "50"
    persistentvolumeclaims: "100"
    configmaps: "200"
    secrets: "200"
    # 存储资源
    requests.storage: "500Gi"
    # GPU(如果集群装了NVIDIA device plugin)
    requests.nvidia.com/gpu: "8"

关键细节:ResourceQuota同时限制了requests和limits。如果只设了requests.cpu,用户提交Pod时只声明limits不声明requests,会直接被拒绝。这是很多人踩的坑——以为只要总量够就行,其实Kubernetes要求requests和limits都必须在配额范围内。

排查配额不足的Pod创建失败:

# 查看namespace的配额使用情况
kubectl get resourcequota -n team-alpha -o yaml

# 查看被配额拒绝的事件
kubectl get events -n team-alpha --field-selector reason=FailedScheduling

# 查看具体配额冲突
kubectl describe resourcequota team-alpha-quota -n team-alpha

优先级和配额抢占:当namespace配额用满,高优先级Pod可以抢占低优先级Pod。配置PriorityClass和Pod的priorityClassName:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: critical-service
value: 1000000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: "核心服务优先级"

但要注意:抢占不是瞬间的。kube-scheduler发现高优先级Pod无法调度后,先选一个低优先级Pod”受害者”,删除该Pod,等原Pod的容器真正退出、资源释放后,再调度高优先级Pod。整个过程可能持续几十秒到几分钟(取决于被抢占Pod的terminationGracePeriodSeconds)。

LimitRange:每个Pod的默认约束

ResourceQuota管总量,LimitRange管每个资源对象的默认值和上下限。没有LimitRange的namespace,用户提交Pod不声明resources,默认就是0 CPU / 0 memory——调度器把这种Pod当besteffort处理,节点资源紧张时最先被驱逐。

apiVersion: v1
kind: LimitRange
metadata:
  name: team-alpha-limits
  namespace: team-alpha
spec:
  limits:
  - type: Container
    max:
      cpu: "16"
      memory: "32Gi"
    min:
      cpu: "50m"
      memory: "64Mi"
    default:
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:
      cpu: "100m"
      memory: "128Mi"
    maxLimitRequestRatio:
      cpu: "4"
      memory: "3"

各字段含义:

default:Pod不设limits时的默认limits值
defaultRequest:Pod不设requests时的默认requests值
max / min:limits和requests的上下限,超出直接拒绝
maxLimitRequestRatio:limits/requests比值上限。设为4表示limits.cpu最多是requests.cpu的4倍。这个参数防止”requests写很小、limits写很大”的资源超卖行为

一个常见坑:LimitRange的default只对Pod没有显式声明resources的容器生效。如果容器只声明了limits没声明requests,Kubernetes会把requests设为等于limits(而不是取defaultRequest)。如果你希望requests低于limits,必须在Pod spec中同时声明两者。

多租户场景的配额策略

多租户集群的配额治理需要分层设计:

L1-集群级:kube-scheduler的配额预过滤,防止任何namespace超分集群总资源。用ClusterResourceQuota(OpenShift)或自定义Admission Webhook实现。

L2-Namespace级:ResourceQuota限制每个租户资源总量。

L3-容器级:LimitRange约束单个容器的资源规格,防止”一个容器吃掉整个namespace配额”。

L4-业务级:HPA + KEDA根据负载自动调整Pod数量,但HPA的maxReplicas不能超过namespace配额允许的Pod数量。

一个完整的配额管理GitOps工作流:

# Argocd Application - 自动同步配额配置
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: resource-quotas
  namespace: argocd
spec:
  source:
    repoURL: git@github.com:infra/k8s-quotas.git
    path: quotas
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

所有配额配置存在Git仓库,ArgoCD自动同步到集群。这样配额变更可追溯、可回滚,避免kubectl直接修改配额导致租户资源被意外回收。

配额监控告警

ResourceQuota使用率超过80%就应该告警,给租户预留扩容时间窗口。用kube-state-metrics + Prometheus实现:

# Prometheus告警规则
groups:
- name: resource-quota
  rules:
  - alert: NamespaceCPUQuotaNearExhaustion
    expr: |
      kube_resourcequota{type="hard", resource="requests.cpu"} > 0
      and
      (kube_resourcequota{type="used", resource="requests.cpu"}
       / kube_resourcequota{type="hard", resource="requests.cpu"}) > 0.8
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "Namespace {{ $labels.namespace }} CPU配额使用率超过80%"
      runbook: "https://wiki.example.com/runbook/quota-cpu"

  - alert: NamespaceMemoryQuotaNearExhaustion
    expr: |
      kube_resourcequota{type="hard", resource="requests.memory"} > 0
      and
      (kube_resourcequota{type="used", resource="requests.memory"}
       / kube_resourcequota{type="hard", resource="requests.memory"}) > 0.8
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "Namespace {{ $labels.namespace }} 内存配额使用率超过80%"

配额治理的核心不是”卡住”开发者,而是让集群资源使用变得可预测。当每个namespace的资源预算清晰可见,集群扩容规划才有数据支撑,而不是靠”感觉快不够了”来决定加节点。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-zi-yuan-pei-e-zhi-li-shi-zhan-resourcequota-yu/

(0)
小编小编
上一篇 17小时前
下一篇 17小时前

相关推荐