K8s HPA终极方案:Prometheus Adapter无缝集成自定义指标
你还在为K8s弹性伸缩烦恼?
当业务高峰期来临,你的Kubernetes集群是否还在依赖CPU/内存这些基础指标进行扩缩容?Prometheus采集了成百上千的业务指标,却无法直接用于HPA(Horizontal Pod Autoscaler)?本文将带你彻底解决这一痛点——通过Prometheus Adapter实现Prometheus指标到Kubernetes自定义指标API的无缝转换,构建真正以业务为导向的弹性伸缩体系。
读完本文你将获得:
- 3种部署模式对比(Helm/Manifest/源码)及生产级配置
- 从0到1的HPA实战案例(含压测验证)
- 90%用户会踩的8个配置陷阱及解决方案
- 性能优化指南(指标缓存/查询优化/资源调优)
- 完整配置模板库(覆盖Pod/Deployment/Node等6类资源)
为什么需要Prometheus Adapter?
Kubernetes自1.6版本引入了自定义指标API(Custom Metrics API),允许用户基于业务指标进行自动扩缩容。但原生Kubernetes无法直接解析Prometheus格式的指标,这就需要一个"翻译官"——Prometheus Adapter正是为此而生。
传统弹性伸缩的3大痛点
| 痛点 | 传统方案 | Prometheus Adapter方案 |
|---|---|---|
| 指标维度有限 | 仅支持CPU/内存 | 支持任意Prometheus指标(如请求量/错误率/队列长度) |
| 实时性差 | 依赖metrics-server 60s采集周期 | 可配置10s级指标刷新 |
| 灵活性不足 | 固定指标来源 | 支持PromQL任意计算(如rate/irate/sum等函数) |
核心功能架构
Prometheus Adapter通过以下3个关键步骤实现指标转换:
- 发现:通过
seriesQuery从Prometheus发现指标 - 关联:通过
resources配置将Prometheus标签映射到K8s资源 - 转换:通过
metricsQuery将Prometheus指标转换为K8s API格式
部署指南:3种方式任选
方式1:Helm一键部署(推荐生产环境)
# 添加Helm仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# 安装稳定版(v0.10.0为例)
helm install prometheus-adapter prometheus-community/prometheus-adapter \
--namespace monitoring \
--set prometheus.url=http://prometheus-server.monitoring:80 \
--set metricsRelistInterval=30s \
--version 3.2.0
方式2:Manifest手动部署
# 创建命名空间
kubectl create namespace monitoring
# 部署基础资源
kubectl apply -f https://gitcode.com/gh_mirrors/pr/prometheus-adapter/raw/main/deploy/manifests/
# 修改Prometheus地址
kubectl edit deployment prometheus-adapter -n monitoring
# 在args中添加--prometheus-url=http://your-prometheus-server:9090
方式3:源码编译部署(开发测试)
# 克隆仓库
git clone https://gitcode.com/gh_mirrors/pr/prometheus-adapter.git
cd prometheus-adapter
# 编译二进制
make build
# 本地运行
./prometheus-adapter --config=docs/sample-config.yaml --prometheus-url=http://localhost:9090
核心配置详解
配置文件是Prometheus Adapter的灵魂,决定了哪些指标会被暴露以及如何暴露。以下是一个生产级配置模板:
完整配置示例(yaml)
rules:
- seriesQuery: '{__name__=~"^http_requests_total$",namespace!="",pod!=""}'
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "^(.*)_total"
as: "${1}_per_second"
metricsQuery: "sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)"
配置参数解析
| 配置项 | 作用 | 示例 |
|---|---|---|
| seriesQuery | Prometheus指标发现规则 | {__name__=~"^http_requests_total$"} |
| resources.overrides | 标签与K8s资源映射 | pod: {resource: "pod"} |
| name.matches | 指标名称匹配正则 | ^(.*)_total |
| name.as | 指标名称转换模板 | ${1}_per_second |
| metricsQuery | 指标计算PromQL模板 | sum(rate(<<.Series>>[2m])) by (<<.GroupBy>>) |
高级配置技巧
- 多规则配置:针对不同类型指标创建多个rule块
- 标签过滤:使用
seriesFilters排除不需要的指标 - 资源模板:通过
template批量映射资源标签
# 批量映射资源标签示例
resources:
template: "kube_<<.Group>>_<<.Resource>>"
overrides:
service: {resource: "service"}
实战案例:基于请求量的HPA
环境准备
- 部署示例应用:暴露
http_requests_total指标
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
spec:
replicas: 1
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- image: luxas/autoscale-demo:v0.1.2
name: metrics-provider
ports:
- name: http
containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: sample-app
spec:
selector:
app: sample-app
ports:
- port: 80
targetPort: 8080
- 配置Prometheus监控:创建ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: sample-app
namespace: monitoring
spec:
selector:
matchLabels:
app: sample-app
endpoints:
- port: http
配置Prometheus Adapter
rules:
- seriesQuery: '{__name__=~"^http_requests_total$",namespace!="",pod!=""}'
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "^(.*)_total"
as: "${1}_per_second"
metricsQuery: "sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)"
创建HPA资源
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: sample-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: Value
averageValue: 500m # 0.5请求/秒/副本
压测验证
# 安装压测工具
kubectl apply -f https://raw.githubusercontent.com/rakyll/hey/master/deploy/hey.yaml
# 执行压测(100并发,共10000请求)
kubectl exec -it hey-xxxx -- hey -z 2m -q 10 -c 5 http://sample-app.default:80/metrics
# 观察HPA状态
kubectl get hpa sample-app -w
预期结果:HPA会在3-5分钟内将副本数扩展到满足500m请求/秒的水平。
8个常见问题解决方案
Q1:指标不显示怎么办?
A1:检查以下3点:
- Prometheus是否能正常采集到指标(在Prometheus UI执行
http_requests_total{pod=~"sample-app.*"}) - Adapter配置的
seriesQuery是否匹配指标名称 - 查看Adapter日志:
kubectl logs -f deployment/prometheus-adapter -n monitoring
Q2:HPA显示"metric not found"?
A2:确保指标名称与HPA中配置一致,可通过以下命令验证API是否返回数据:
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta2/namespaces/default/pods/*/http_requests_per_second" | jq .
Q3:指标值波动剧烈?
A3:调整PromQL查询窗口,例如将rate(<<.Series>>[2m])改为irate(<<.Series>>[1m]),irate对短期波动更敏感。
Q4:如何暴露节点级指标?
A4:配置资源映射为node:
resources:
overrides:
node: {resource: "node"}
Q5:如何聚合多个Pod的指标?
A5:使用PromQL的sum函数并按资源标签分组:
metricsQuery: "sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (deployment)"
Q6:Adapter性能问题?
A6:调整以下参数:
--metrics-relist-interval=30s:延长指标发现间隔--metrics-max-age=5m:增加指标缓存时间- 为Adapter Pod分配更多资源:
resources: {requests: {cpu: "100m", memory: "128Mi"}}
Q7:如何使用外部Prometheus?
A7:部署时指定外部Prometheus地址:
--set prometheus.url=https://prometheus.example.com --set prometheus.tls.insecureSkipVerify=true
Q8:版本兼容性问题?
A8:参考以下兼容性矩阵:
| Kubernetes版本 | Adapter版本 | API版本 |
|---|---|---|
| 1.21+ | v0.10+ | custom.metrics.k8s.io/v1beta2 |
| 1.16-1.20 | v0.8-v0.9 | custom.metrics.k8s.io/v1beta1 |
| 1.15及以下 | v0.7及以下 | custom.metrics.k8s.io/v1beta1 |
性能优化指南
指标查询优化
- 使用精确标签匹配:避免大范围正则匹配,如
{pod=~"app-.*"}改为{pod=~"app-[a-z0-9]{8}"} - 限制时间范围:
[2m]而非[10m],减少Prometheus查询负载 - 预聚合指标:在Prometheus采集时通过relabel_configs合并标签
资源配置建议
| 集群规模 | CPU请求 | 内存请求 | 并发查询限制 |
|---|---|---|---|
| 小型(<50节点) | 100m | 128Mi | 10 |
| 中型(50-200节点) | 500m | 512Mi | 20 |
| 大型(>200节点) | 1000m | 1Gi | 50 |
缓存策略
rules:
- seriesQuery: 'http_requests_total'
resources: {overrides: {pod: {resource: "pod"}}}
name: {matches: "http_requests_total", as: "http_requests"}
metricsQuery: "sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)"
cacheDuration: "2m" # 缓存查询结果2分钟
总结与展望
Prometheus Adapter作为Kubernetes生态中连接监控与弹性伸缩的关键组件,已经成为生产环境中的事实标准。通过本文介绍的部署、配置和优化方法,你可以轻松构建基于业务指标的弹性伸缩体系。
最佳实践清单
- ✅ 始终使用Helm或Operator管理部署
- ✅ 为不同类型指标创建独立的配置规则
- ✅ 定期清理不再使用的指标规则
- ✅ 对关键指标配置告警(如指标缺失、查询错误)
- ✅ 监控Adapter自身性能(
adapter_request_count等内置指标)
未来趋势
- 原生支持Prometheus:Kubernetes社区正讨论将Prometheus指标直接接入APIServer
- 动态配置:支持通过CRD动态管理指标规则,无需重启Adapter
- 多Prometheus集群:支持从多个Prometheus实例聚合指标
如果你在使用过程中遇到问题,欢迎通过以下渠道获取支持:
- GitHub Issues:https://gitcode.com/gh_mirrors/pr/prometheus-adapter/issues
- Slack:#prometheus-adapter频道(Kubernetes Slack)
- 邮件列表:kubernetes-sig-instrumentation@googlegroups.com
最后,别忘了点赞、收藏、关注三连,下期我们将带来《Prometheus Adapter高级实战:多维度指标聚合与联邦》!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



