关于 k8s-hpa-cost-tuning
面向使用 Kubernetes HPA 和 Cluster Autoscaler 的团队,辅助审计集群资源浪费并分析扩缩容事件。通过 Datadog 指标脚本和三层扩缩容模型,定位副本、调度与节点回收之间的成本障碍。
主要功能
- 01按集群或部署审计资源利用率
- 02分析事故窗口内的扩缩容指标
- 03评估副本、节点与请求量
- 04提供逐项调优建议
适用场景
- 01定期发现集群资源过度预留
- 02排查生产事件中的扩容原因
- 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 扩缩容是一个三层系统:
- HPA 决定需要多少个 Pod(基于使用量 / 请求量)
- 调度器 决定Pod 放置在哪里(基于请求量和约束)
- 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: 70targetMemoryUtilizationPercentage: 75–80
每次只调整一个参数。
验证流程
每周运行一次(或在变更后运行):
- 检查 HPA 的
current/target值 - 比较 CPU 使用率 % 与 CPU 请求率 %
- 观察负载下降后副本数是否减少
- 确认节点已排空并消失
- 重新检查延迟、错误和 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)