mcpField
K
k8s-hpa-cost-tuning

k8s-hpa-cost-tuning

github.com/microlinkhq云与 DevOps449 次安装今天更新
代码仓库

关于 k8s-hpa-cost-tuning

面向使用 Kubernetes HPA 和 Cluster Autoscaler 的团队,辅助审计集群资源浪费并分析扩缩容事件。通过 Datadog 指标脚本和三层扩缩容模型,定位副本、调度与节点回收之间的成本障碍。

主要功能

  1. 01按集群或部署审计资源利用率
  2. 02分析事故窗口内的扩缩容指标
  3. 03评估副本、节点与请求量
  4. 04提供逐项调优建议

适用场景

  1. 01定期发现集群资源过度预留
  2. 02排查生产事件中的扩容原因
  3. 03验证负载下降后节点能否回收

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/microlinkhq/skills --skill k8s-hpa-cost-tuning

安装后在 Claude Code 中输入/k8s-hpa-cost-tuning确认已加载。

附带文件scripts/audit-metrics.mjsscripts/incident-metrics.mjs

详细介绍

Kubernetes HPA 成本与缩容调优

模式选择(必需)

执行此技能前,必须声明模式。所有推理、阈值和建议都取决于此选择。

mode = audit | incident

如果未提供模式,请拒绝运行并请求澄清。

适用场景

mode = audit — 定期成本节省审计

按计划运行(每周或每两周一次),以便:

  • 尽早发现过度预留
  • 验证缩容和节点整合仍可正常工作
  • 找出安全降低集群成本的机会

此模式假设没有正在发生的事故,并优先提供有助于维持稳定性的建议。

mode = incident — 事故后的扩缩容分析

在生产事故或异常发生后运行,并附上:

  • 生产日志
  • HPA 事件
  • 扩缩容时间线

此模式侧重于:

  • 解释扩缩容行为的原因
  • 区分由流量驱动和由配置驱动的事故
  • 防止问题再次发生,同时避免过度纠正

此技能假设使用 Datadog 进行可观测性监控,并使用标准 Kubernetes HPA 和 Cluster Autoscaler。

核心思维模型

Kubernetes 扩缩容是一个三层系统:

  1. HPA 决定需要多少个 Pod(基于使用量 / 请求量)
  2. 调度器 决定Pod 放置在哪里(基于请求量和约束)
  3. Cluster Autoscaler 决定需要多少个节点(仅当节点可以清空时)

只有这三层都能向下调整,成本优化才能奏效。

关键要点:HPA 决定数量,调度器决定放置位置,自动伸缩器决定成本。扩容可以积极一些;缩容则必须可行。如果副本数减少了,但节点数没有减少,瓶颈就在调度器。

关键 Datadog 指标

实用脚本会查询三类指标:

  • CPU 使用率 % — 实际利用率(kubernetes.cpu.usage.total / node.cpu_allocatable)
  • CPU 请求率 % — 纸面预留量(kubernetes.cpu.requests / node.cpu_allocatable)
  • 内存使用量与请求量 — 与 HPA 相关的比率

缩容后,CPU 请求率 % 必须下降,节省成本才是真实的。 如果内存使用量一直高于目标,即使 CPU 空闲,内存也会驱动扩容。

将缩容作为核心成本控制手段

缩容缓慢或受阻时:

  • 副本数停滞不变
  • Pod 仍然均匀分布
  • 节点始终无法清空
  • Cluster Autoscaler 无法移除节点

结果:持续过度预留。

推荐的 HPA 缩容策略
scaleDown:
  stabilizationWindowSeconds: 60
  selectPolicy: Max
  policies:
    - type: Percent
      value: 50
      periodSeconds: 30

效果:负载下降后快速响应,副本数可预测地减少,且不易出现抖动。

拓扑分布:关键的成本杠杆

拓扑分布绝不能阻止缩容期间的 Pod 整合。

严格约束会限制调度器的灵活性,并导致集群规模无法缩小。

反模式(破坏成本优化)
maxSkew: 1
whenUnsatisfiable: DoNotSchedule

Pod 无法集中到更少的节点上。节点始终无法排空。预留的 CPU / 内存始终不会减少。

推荐默认配置(成本安全)
topologySpreadConstraints:
- topologyKey: kubernetes.io/hostname
  maxSkew: 2
  whenUnsatisfiable: ScheduleAnyway

优先分散,同时允许缩容期间进行装箱,并支持移除节点。

严格隔离(仅限可用区级别)

需要硬性保证时:

topologySpreadConstraints:
- topologyKey: topology.kubernetes.io/zone
  maxSkew: 1
  whenUnsatisfiable: DoNotSchedule

不要将其与严格的主机名级别拓扑分布结合使用。

将反亲和性作为软性替代方案

为避免节点过载,同时不阻碍缩容:

podAntiAffinity:
  preferredDuringSchedulingIgnoredDuringExecution:
  - weight: 100
    podAffinityTerm:
      topologyKey: kubernetes.io/hostname
      labelSelector:
        matchLabels:
          app: your-app

反亲和性仅提供建议,不会影响成本优化。

资源请求调优

  • CPU 请求过高 = 缩容更慢
  • 内存请求过高 = 意外扩容

实用默认值:

  • targetCPUUtilizationPercentage: 70
  • targetMemoryUtilizationPercentage: 75–80

每次只调整一个参数。

验证流程

每周运行一次(或在变更后运行):

  1. 检查 HPA 的 current/target 值
  2. 比较 CPU 使用率 % 与 CPU 请求率 %
  3. 观察负载下降后副本数是否减少
  4. 确认节点已排空并消失
  5. 重新检查延迟、错误和 OOM
快速验证命令
kubectl -n <namespace> get hpa <deployment>
kubectl -n <namespace> describe hpa <deployment>
kubectl -n <namespace> top pod --containers
kubectl top node
kubectl -n <namespace> get pods -o wide | sort -k7

实用脚本

两个脚本都需要 Datadog 凭据:

export DD_API_KEY=...
export DD_APP_KEY=...
export DD_SITE=datadoghq.com   # optional, defaults to datadoghq.com
audit-metrics.mjs — 节省成本机会发现

在较长时间窗口(默认为 24 h)内扫描集群,查找资源预留过多和浪费的情况。

# Cluster-wide audit
node scripts/audit-metrics.mjs --cluster <cluster>

# With deployment deep-dive
node scripts/audit-metrics.mjs \
  --cluster <cluster> \
  --namespace <namespace> \
  --deployment <deployment>

报告内容:

  • 集群:CPU/内存已用百分比、请求百分比和浪费百分比(请求量减去已用量)
  • Deployment(如有提供):CPU/内存用量与请求量对比、HPA 副本范围
  • 节省机会:根据阈值提供可执行的建议
incident-metrics.mjs — 事件后分析

收集较短事件时间窗口内的指标,并获取调优建议。

node scripts/incident-metrics.mjs \
  --cluster <cluster> \
  --namespace <namespace> \
  --deployment <deployment> \
  --from <ISO8601> \
  --to <ISO8601>

报告内容:

  • 集群:CPU 已用百分比和可分配资源中的请求百分比
  • Deployment:CPU/内存用量与请求量对比、不可用百分比
  • HPA:当前/目标/最大副本数
  • 容量规划:在 80 % 和 70 % 预留上限下所需的可分配核心数
  • 调优顺序:分步骤建议(每次调整一个参数)
解读说明
  • 除非已确认发生 OOMKills 或内存用量接近上限,否则请保持 limits.memory 不变
  • 使用 --out <path> 保存完整 JSON,以便深入分析或对比多次运行结果
  • 在任一脚本中运行 --help,查看所有选项(相对时间窗口、自定义 HPA 名称、美化 JSON)

评论

支持 Markdown