Kubernetes HPA 基于自定义指标的自动扩缩容完全指南

# Kubernetes HPA 基于自定义指标的自动扩缩容完全指南

## 背景介绍

在云原生应用架构中,容器弹性伸缩能力已经成为保障服务稳定性和资源利用效率的核心要素。Kubernetes 作为容器编排的事实标准,提供了 Horizontal Pod Autoscaler(HPA)来实现 Pod 自动扩缩容。但默认的 HPA 只支持 CPU 和内存两种资源指标,这在很多业务场景下远远不够。

一个实际的例子:在线教育平台的视频转码服务,需要根据转码队列长度来调整转码 Pod 数量。队列积压增多时应该扩容加快处理,清空时应该缩容节省资源。类似的场景还包括根据 Redis 队列长度调整 worker 数量、根据 HTTP 请求排队延迟调整服务实例、根据数据库连接池使用率调整应用副本等。这些需求都超出了默认 HPA 的能力范围。

本文详细介绍如何基于自定义指标实现 Kubernetes Pod 精准自动扩缩容,使用 Prometheus Adapter 将自定义指标接入 Kubernetes 监控系统,配置 HPA 响应这些指标变化。

## 问题描述

实际生产环境中经常遇到以下挑战:

**默认指标局限性**:标准 HPA 只支持 CPU 和内存资源指标。CPU 使用率适合计算密集型应用,但对于 I/O 密集型、队列驱动型或延迟敏感型应用,仅靠 CPU 指标往往无法准确反映真实负载状态。例如处理异步任务的 worker 服务,CPU 使用率可能一直很低,但任务队列却在不断积压。

**指标采集困难**:Kubernetes 本身不直接暴露业务指标,需要依赖监控系统采集。Prometheus 是目前最流行的云原生监控系统,但默认情况下 Kubernetes 无法直接使用 Prometheus 采集的指标进行扩缩容。

**指标适配复杂**:即使有监控系统,还需要将业务指标转换为 Kubernetes API 可以识别的格式,涉及指标适配器部署和配置,对很多开发者是技术门槛。

**扩缩容策略单一**:默认 HPA 使用简单阈值策略,无法实现更复杂的控制逻辑,如防止抖动、设置冷却时间、考虑历史趋势等。

本文逐一解决这些问题,带你从零开始搭建完整的基于自定义指标自动扩缩容系统。

## 详细步骤

### 第一步:安装 Prometheus 和 Prometheus Adapter

首先在 Kubernetes 集群中部署 Prometheus 用于指标采集。推荐使用 kube-prometheus-stack,提供预配置的 Prometheus 监控组件:

“`bash
# 使用 Helm 安装 kube-prometheus-stack
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack \
–namespace monitoring \
–create-namespace \
–set prometheus.prometheusSpec.retention=15d \
–set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=50Gi
“`

接下来部署 prometheus-adapter 将 Prometheus 指标转换为 Kubernetes API 格式:

“`yaml
# prometheus-adapter.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-adapter-config
namespace: monitoring
data:
config.yaml: |
rules:
– seriesQuery: “nginx_nginx_http_requests_total{namespace!=\”\”,pod!=\”\”}”
resources:
overrides:
namespace: {resource: “namespace”}
pod: {resource: “pod”}
service: {resource: “service”}
name:
matches: “^(.*)_total$”
as: “${1}_per_second”
metricsQuery: “sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)”

apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-adapter
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
name: prometheus-adapter
template:
metadata:
labels:
name: prometheus-adapter
spec:
containers:
– args:
– –watch-cache=false
– –config=/etc/adapter/config.yaml
image: directxman12/k8s-prometheus-adapter:v0.12.0
name: adapter
volumeMounts:
– mountPath: /etc/adapter
name: config
volumes:
– configMap:
name: prometheus-adapter-config
name: config

apiVersion: v1
kind: Service
metadata:
name: prometheus-adapter
namespace: monitoring
spec:
ports:
– port: 443
targetPort: 6443
selector:
name: prometheus-adapter
“`

应用配置:

“`bash
kubectl apply -f prometheus-adapter.yaml
“`

### 第二步:部署示例应用

以任务队列处理服务为例,演示如何根据队列长度实现自动扩缩容。首先创建应用部署:

“`yaml
# worker-deployment.yaml
apiVersion: v1
kind: Deployment
metadata:
name: queue-worker
namespace: demo
spec:
replicas: 2
selector:
matchLabels:
app: queue-worker
template:
metadata:
labels:
app: queue-worker
annotations:
prometheus.io/scrape: “true”
prometheus.io/port: “8080”
spec:
containers:
– name: worker
image: your-registry/queue-worker:latest
ports:
– containerPort: 8080
env:
– name: REDIS_URL
value: “redis://redis-service:6379”
resources:
requests:
memory: “256Mi”
cpu: “200m”
limits:
memory: “512Mi”
cpu: “500m”
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 3

apiVersion: v1
kind: Service
metadata:
name: queue-worker
namespace: demo
spec:
selector:
app: queue-worker
ports:
– port: 80
targetPort: 8080
“`

### 第三步:配置 HPA 使用自定义指标

创建 HPA 配置,根据 Redis 队列长度自动调整副本数:

“`yaml
# hpa-custom-metrics.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: queue-worker-hpa
namespace: demo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: queue-worker
minReplicas: 2
maxReplicas: 10
metrics:
– type: Pods
pods:
metric:
name: redis_queue_length
target:
type: AverageValue
averageValue: “100”
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
– type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
– type: Percent
value: 100
periodSeconds: 15
– type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
“`

这个配置的含义:每个 Pod 平均处理队列长度达到 100 时开始扩容,缩容需要等待 5 分钟稳定窗口期。

### 第四步:配置 Prometheus 抓取业务指标

在 Prometheus 中配置抓取应用暴露的指标:

“`yaml
# prometheus-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: queue-worker-monitor
namespace: monitoring
spec:
selector:
matchLabels:
app: queue-worker
namespaceSelector:
matchNames:
– demo
endpoints:
– port: 8080
interval: 15s
path: /metrics

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: queue-metrics-rules
namespace: monitoring
spec:
groups:
– name: queue-worker
rules:
– expr: |
redis_queue_length{job=”queue-worker”}
record: redis_queue_length
labels:
job: queue-worker
“`

### 第五步:验证配置

完成配置后,验证 HPA 是否正确识别自定义指标:

“`bash
# 查看 HPA 状态
kubectl get hpa queue-worker-hpa -n demo

# 查看自定义指标是否可用
kubectl get –raw “/apis/custom.metrics.k8s.io/v1beta1/namespaces/demo/pods/*/redis_queue_length”

# 查看 HPA 推荐值
kubectl describe hpa queue-worker-hpa -n demo
“`

## 完整代码示例

完整部署清单,包含所有必要资源定义:

“`yaml
# complete-deployment.yaml

apiVersion: v1
kind: Namespace
metadata:
name: demo

apiVersion: apps/v1
kind: Deployment
metadata:
name: queue-worker
namespace: demo
spec:
replicas: 2
selector:
matchLabels:
app: queue-worker
template:
metadata:
labels:
app: queue-worker
annotations:
prometheus.io/scrape: “true”
prometheus.io/port: “8080”
spec:
containers:
– name: worker
image: your-registry/queue-worker:v1.0
ports:
– containerPort: 8080
env:
– name: REDIS_URL
value: “redis://redis-service:6379”
resources:
requests:
memory: “256Mi”
cpu: “200m”
limits:
memory: “512Mi”
cpu: “500m”

apiVersion: v1
kind: Service
metadata:
name: queue-worker
namespace: demo
spec:
selector:
app: queue-worker
ports:
– port: 80
targetPort: 8080

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: queue-worker-hpa
namespace: demo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: queue-worker
minReplicas: 2
maxReplicas: 10
metrics:
– type: Pods
pods:
metric:
name: redis_queue_length
target:
type: AverageValue
averageValue: “100”
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
– type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
– type: Percent
value: 100
periodSeconds: 15
– type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
“`

## 运行结果

部署完成后,观察 HPA 实际效果:

“`bash
# 查看 HPA 详细信息
$ kubectl describe hpa queue-worker-hpa -n demo

Name: queue-worker-hpa
Namespace: demo
Reference: Deployment/queue-worker
Metrics: ( current / target )
“redis_queue_length” (pods): 150 / 100
Min replicas: 2
Max replicas: 10
Behavior:
Scale Up:
Stabilization Window: 0s
Policies:
– Percent: 100% (15s window)
– Pods: 4 (15s window)
Scale Down:
Stabilization Window: 300s
Policies:
– Percent: 50% (60s window)

Conditions:
Type Status Reason Message
—- —— —— ——-
AbleToScale True SucceededRescale
ScalingActive True ValidMetricFound
ScalingLimited False DesiredWithinRange
“`

队列长度从 150 增长到 300 时,HPA 触发扩容:

“`bash
# 观察扩容过程
$ kubectl get pods -n demo -w

NAME READY STATUS RESTARTS AGE
queue-worker-6d8f9c4d-abcde 1/1 Running 0 5m
queue-worker-6d8f9c4d-fghij 1/1 Running 0 5m
# 触发扩容
queue-worker-6d8f9c4d-klmno 0/1 Pending 0 10s
queue-worker-6d8f9c4d-pqrst 0/1 Pending 0 10s
# 新 Pod 就绪
queue-worker-6d8f9c4d-klmno 1/1 Running 0 45s
queue-worker-6d8f9c4d-pqrst 1/1 Running 0 50s
“`

通过 Prometheus 和 Grafana 可以直观看到副本数随队列长度变化趋势,验证整个自动扩缩容系统有效性。

## 总结

本文详细介绍 Kubernetes 中基于自定义指标实现 Pod 自动扩缩容的完整方案。首先分析默认 HPA 局限性,然后通过 Prometheus 采集业务指标,使用 Prometheus Adapter 将指标转换为 Kubernetes API 可识别格式,最后通过配置 HPA 实现基于业务负载的精准扩缩容。

这种方案的优势:指标采集灵活多样,支持任何应用暴露的 Prometheus 指标;扩缩容策略可定制化,支持配置稳定窗口和扩容速率;与现有监控系统无缝集成,无需额外部署组件。实际生产环境中,这种方案特别适合任务队列处理服务、异步消息消费者、批量数据处理任务等场景,能够在保证服务质量的同时最大化资源利用效率。

如果寻找更进阶方案,可以考虑使用 KEDA(Kubernetes Event-driven Autoscaling),它提供更丰富的扩缩容源支持和更简洁配置方式。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇