# Kubernetes HPA 基于 Prometheus 自定义指标实现自动扩缩容实战指南
## 背景介绍
Kubernetes 的 Horizontal Pod Autoscaler(HPA)默认只能基于 CPU 和内存利用率来调整副本数。这在很多场景下不够用。比如消息处理服务,可能需要根据队列深度来伸缩;Web 服务可能更关心请求延迟或错误率,而不是 CPU 用成了什么样。
Prometheus 是 Kubernetes 生态里最常用的监控系统。配合 prometheus-adapter,可以把 Prometheus 采集的指标暴露给 HPA 使用。本文会一步步教你如何配置基于自定义指标的 HPA。
## 问题描述
假设你有一个 API 网关服务。真正的瓶颈不在 CPU 或内存,而在数据库连接池。当连接池使用率超过 70% 时,响应时间会暴涨。你想根据这个指标来自动扩容,而不是看 CPU 心情行事。
这事儿难点在于:默认 HPA 读不懂 Prometheus 里的自定义指标。你需要搭一条路:Prometheus 采集数据、prometheus-adapter 转换格式、HPA 消费指标。链路打通才能跑起来。
## 详细步骤
### 第一步:安装 Prometheus 和 prometheus-adapter
如果集群里还没有 Prometheus,用 kube-prometheus-stack 快速搭一个:
“`bash
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack \
–namespace monitoring \
–create-namespace
“`
prometheus-adapter 这样装:
“`bash
helm install prometheus-adapter prometheus-community/prometheus-adapter \
–namespace monitoring \
–set prometheus.url=http://prometheus-server.monitoring.svc.cluster.local
“`
### 第二步:配置自定义指标规则
prometheus-adapter 需要知道怎么从 Prometheus 里查指标。改一下 adapter 的配置:
“`yaml
rules:
custom:
– seriesQuery: ‘http_requests_total{kubernetes_pod_name!=””}’
resources:
overrides:
kubernetes_pod_name:
resource: pod
kubernetes_namespace:
resource: namespace
name:
matches: “^(.*)$”
as: “http_requests_per_second”
metricsQuery: ‘sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)’
“`
这个配置把 `http_requests_total` 转换成 HPA 能看懂的 `http_requests_per_second`。
### 第三步:部署示例应用
写个简单的 Golang API 服务当测试对象:
“`go
package main
import (
“fmt”
“net/http”
“sync/atomic”
)
var requestCount int64
func main() {
http.HandleFunc(“/api”, func(w http.ResponseWriter, r *http.Request) {
atomic.AddInt64(&requestCount, 1)
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, “OK”)
})
http.HandleFunc(“/metrics”, func(w http.ResponseWriter, r *http.Request) {
count := atomic.LoadInt64(&requestCount)
fmt.Fprintf(w, “http_requests_total %d\n”, count)
})
http.ListenAndServe(“:8080”, nil)
}
“`
打包成镜像,扔到 Kubernetes 里跑:
“`yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
spec:
replicas: 2
selector:
matchLabels:
app: api-gateway
template:
metadata:
labels:
app: api-gateway
spec:
containers:
– name: api-gateway
image: your-registry/api-gateway:v1
ports:
– containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
—
apiVersion: v1
kind: Service
metadata:
name: api-gateway
spec:
selector:
app: api-gateway
ports:
– port: 80
targetPort: 8080
“`
配一下 ServiceMonitor 让 Prometheus 来抓指标:
“`yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: api-gateway-monitor
spec:
selector:
matchLabels:
app: api-gateway
endpoints:
– port: 8080
path: /metrics
interval: 15s
“`
### 第四步:创建基于自定义指标的 HPA
最后一步,挂载自定义指标到 HPA:
“`yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-gateway-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-gateway
minReplicas: 2
maxReplicas: 10
metrics:
– type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: “100”
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
– type: Percent
value: 50
periodSeconds: 15
scaleUp:
stabilizationWindowSeconds: 0
policies:
– type: Percent
value: 100
periodSeconds: 15
“`
每秒钟请求数超过 100 时开始扩容,副本数在 2 到 10 之间浮动。
## 运行结果
部署完以后,这样查看 HPA 状态:
“`bash
kubectl get hpa api-gateway-hpa
“`
通常会看到类似输出:
“`
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
api-gateway-hpa Deployment/api-gateway 150/100 (avg) 2 10 3 5m
“`
超过阈值时,HPA 会自动加 Pod。看详细事件:
“`bash
kubectl describe hpa api-gateway-hpa
“`
你会看到类似:
“`
Events:
Type Reason Age From Message
—- —— —- —- ——-
Normal SuccessfulRescale 2m horizontal-pod-autoscaler New size: 4; reason: pods metric http_requests_per_second above target
“`
检查 prometheus-adapter 指标暴露是否正常:
“`bash
kubectl get –raw “apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests_per_second” | jq
“`
返回:
“`json
{
“items”: [
{
“metricName”: “http_requests_per_second”,
“metricLabels”: {
“pod”: “api-gateway-7d9f8b6c4-x2m9z”
},
“timestamp”: “2026-04-05T08:00:00Z”,
“value”: “150”
}
]
}
“`
指标链路通了,HPA 能正常读取数据并执行扩缩容。
## 总结
用 Prometheus 自定义指标做 HPA,核心好处有几点:
一是指标灵活。想用队列深度就用队列深度,想用延迟就用延迟,不用被 CPU 内存绑死。
二是响应更快。业务指标往往比资源使用率更能提前反映问题,能更早触发扩容。
三是配置更细。behavior 字段可以分别调扩容和缩容的策略,避免流量抖动时反复震荡。
实际落地时注意:prometheus-adapter 的查询用 rate 函数做聚合更稳;指标采集间隔影响 HPA 反应速度,别设太慢;对核心业务别把 minReplicas 设为 0,不然缩到零的时候服务会裸奔。
这套方案特别适合微服务和有明确业务指标的场景,算是智能化运维的基本功。