Kubernetes容器编排资源调度实战:Requests与Limits配置及HPA自动伸缩调优

K8s资源调度为什么直接影响业务稳定性

Kubernetes集群里,Pod调度失败、OOMKilled、CPU Throttling是最常见的三类资源问题。根本原因几乎都是Requests和Limits配置不当——要么设太低导致Pod被频繁驱逐,要么设太高造成资源浪费和调度热点。把Requests/Limits当随便填的数字,线上迟早出事。

Requests与Limits的核心机制

Requests是调度器调度的依据——Scheduler保证Pod被分配到有足够资源的Node上。Limits是运行时的硬上限——超过CPU Limit会被Throttle,超过Memory Limit会触发OOMKilled。

# Pod资源声明示例
resources:
  requests:
    cpu: "500m"      # 调度保障:至少0.5核
    memory: "256Mi"   # 调度保障:至少256MB
  limits:
    cpu: "1000m"      # 运行上限:最多1核
    memory: "512Mi"   # 运行上限:最多512MB

CPU是可压缩资源,超限会被Throttle但不会杀进程;Memory是不可压缩资源,超限直接OOMKilled。这个区别决定了CPU Limits可以设得相对宽松,Memory Limits必须严格对齐实际用量。

资源配置的实战方法论

不要凭感觉设Requests/Limits。用数据说话:

第一步:无限制压测,采集真实用量

先不设Limits跑一段时间,用Prometheus采集CPU和Memory的P99用量:

# Prometheus查询P99内存用量
quantile_over_time(0.99, container_memory_working_set_bytes{container!="POD",namespace="prod"}[7d])

# P99 CPU用量
quantile_over_time(0.99, rate(container_cpu_usage_seconds_total{container!="POD",namespace="prod"}[5m])[7d])

第二步:按公式计算配置值

  • Requests.memory = P99用量 x 1.2(留20%缓冲)
  • Limits.memory = P99用量 x 1.5(留50%弹性空间)
  • Requests.cpu = P99用量 x 1.1
  • Limits.cpu = P99用量 x 2.0

Java应用需要特殊处理,JVM堆内存远低于容器Memory Limits时才能避免OOM。经验值:容器Memory Limits = JVM Xmx x 1.5,因为堆外内存(Metaspace、线程栈、NIO Direct Buffer)也要算进来。

第三步:设置LimitRange和ResourceQuota作为兜底

# LimitRange - 命名空间级默认值和上下限
apiVersion: v1
kind: LimitRange
metadata:
  name: prod-limits
  namespace: prod
spec:
  limits:
  - type: Container
    default:
      cpu: "500m"
      memory: "256Mi"
    defaultRequest:
      cpu: "100m"
      memory: "128Mi"
    max:
      cpu: "4"
      memory: "8Gi"
    min:
      cpu: "50m"
      memory: "64Mi"
---
# ResourceQuota - 命名空间总资源限制
apiVersion: v1
kind: ResourceQuota
metadata:
  name: prod-quota
  namespace: prod
spec:
  hard:
    requests.cpu: "20"
    requests.memory: "40Gi"
    limits.cpu: "40"
    limits.memory: "80Gi"
    pods: "100"

HPA自动伸缩:从指标配置到冷启动优化

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-server-hpa
  namespace: prod
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Pods
        value: 1
        periodSeconds: 120

HPA配置的关键坑点:

1. 扩容速度跟不上流量突增 — 默认每60秒检查一次指标,流量洪峰来时来不及。解法:配合PodDisruptionBudget和预热Pod池,或在业务层做限流兜底。

2. 扩容后新Pod冷启动慢 — Java应用启动要30-60秒。解法:开启Readiness Gate,确保Pod就绪后才接收流量;同时用--horizontal-pod-autoscaler-initial-readiness-delay调整就绪判定延迟。

3. 缩容震荡 — CPU波动导致反复扩缩。解法:stabilizationWindowSeconds设5分钟以上,缩容策略设type: Pods, value: 1,一次最多缩一个。

Node级资源压力防护:eviction与descheduler

当Node内存或磁盘压力过高,Kubelet会主动驱逐Pod。但驱逐顺序由QoS等级决定:

  • Guaranteed(Requests = Limits):最后被驱逐
  • Burstable(Requests < Limits):中间优先级
  • BestEffort(无Requests/Limits):最先被驱逐

生产环境核心业务必须设Guaranteed QoS,避免被无辜驱逐。

集群长期运行后,部分Node资源碎片化严重,Pod调度不均衡。部署descheduler定期重平衡:

apiVersion: "descheduler/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
  "RemoveDuplicates":
    enabled: true
  "LowNodeUtilization":
    enabled: true
    params:
      nodeResourceUtilizationThresholds:
        thresholds:
          cpu: 20
          memory: 20
          pods: 20
        targetThresholds:
          cpu: 50
          memory: 50
          pods: 50

资源调度是K8s运维的地基。Requests/Limits配不好,HPA调优就是空中楼阁。先用量化数据定好每类工作负载的资源基线,再用LimitRange/ResourceQuota兜底,最后才是HPA和集群重平衡。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-rong-qi-bian-pai-zi-yuan-diao-du-shi-zhan/

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

相关推荐

发表回复

登录后才能评论