深色模式
水位与扩容阈值
水位是"已用/总量"的比值。本文给出通用红线:70% 触发扩容评估、85% 必须处置,并给出 Prometheus 告警与 K8s HPA 的落地配置。
适用环境
- Prometheus + Alertmanager 已部署
- Kubernetes 集群(HPA)或云弹性伸缩组
- 已统计出各资源的历史峰值水位
bash
# 确认当前各资源水位(内存示例)
free -m | awk '/Mem:/{printf "used=%.1f%%\n", ($3-$6)/$2*100}'
df -h /data | awk 'NR==2{print "disk="$5}'1
2
3
2
3
操作步骤
1. 定义水位口径
text
水位 = 峰值已用量 / 可用总量
CPU :1 - idle 比例(取 5 分钟均值,取当日峰值)
内存 :1 - MemAvailable / MemTotal
磁盘 :used / size
连接 :Threads_connected / max_connections1
2
3
4
5
6
2
3
4
5
6
统一用峰值而非均值:均值会被低峰稀释,等均值到 70% 时峰值早已打满。
2. 设定双红线
| 水位 | 级别 | 动作 |
|---|---|---|
| < 70% | 正常 | 无需动作,月度审视 |
| 70% ~ 85% | warning | 排期扩容,纳入下周计划 |
| > 85% | critical | 立即处置(扩容或限流) |
| > 95% | 故障 | 已影响可用性,进入应急流程 |
为什么是 70%:留 30% 余量吸收突发流量、单实例故障后的流量转移、以及扩容动作本身的耗时。
3. 配置 Prometheus 告警规则
yaml
groups:
- name: capacity.rules
rules:
- alert: HighCPUWatermark
expr: |
max_over_time(
(1 - sum(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)
/ count(node_cpu_seconds_total{mode="idle"}) by (instance))[10m:1m]
) > 0.70
for: 30m
labels:
severity: warning
annotations:
summary: "CPU 水位 > 70%: {{ $labels.instance }}"
description: "建议在下个迭代内完成扩容评估"
- alert: CriticalCPUWatermark
expr: |
max_over_time(
(1 - sum(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)
/ count(node_cpu_seconds_total{mode="idle"}) by (instance))[10m:1m]
) > 0.85
for: 5m
labels:
severity: critical
annotations:
summary: "CPU 水位 > 85%: {{ $labels.instance }},需立即处置"1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
bash
# 校验规则语法
promtool check rules /etc/prometheus/rules/capacity.yml1
2
2
4. 配置 HPA 扩缩容阈值
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # 目标水位 70%
behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 50
periodSeconds: 60 # 快速扩容
scaleDown:
stabilizationWindowSeconds: 600
policies:
- type: Percent
value: 20
periodSeconds: 600 # 慢速缩容,防抖1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
注意区分两个阈值:告警阈值(人看)70%、HPA 目标水位(机器执行)也应设在 60%~70%,给扩容留出启动时间。
5. 磁盘与连接数的红线
yaml
- alert: DiskWatermarkHigh
expr: |
(node_filesystem_size_bytes{fstype=~"ext4|xfs"} - node_filesystem_avail_bytes{fstype=~"ext4|xfs"})
/ node_filesystem_size_bytes{fstype=~"ext4|xfs"} > 0.85
for: 10m
labels:
severity: critical
annotations:
summary: "磁盘水位 > 85%: {{ $labels.mountpoint }}"1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
数据库连接水位同理,用 Threads_connected / max_connections > 0.85 触发。
6. 建立水位周报
promql
# 一周内各实例的水位峰值排行
topk(10, max_over_time(
(1 - sum(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)
/ count(node_cpu_seconds_total{mode="idle"}) by (instance))[7d:5m]
))1
2
3
4
5
2
3
4
5
验证
bash
# 用压测把水位推过 70%,确认告警真的会发出来
wrk -t8 -c600 -d300s http://10.0.0.11:8080/api/order &
curl -s http://localhost:9090/api/v1/alerts | jq -r '.data.alerts[] | select(.labels.severity=="warning") | .labels.alertname'1
2
3
2
3
同时验证 HPA:
bash
kubectl get hpa order-api -w1
常见坑
用瞬时值触发告警
单点毛刺会引发大量误告警。水位告警必须套 max_over_time(...[10m:1m]) 并配 for: 30m。
告警阈值等于扩容耗时所需水位
扩容需要 5 分钟(拉镜像+启动),但阈值设在 95%,还没扩完就已经雪崩。阈值必须高于「扩容耗时 × 增长速率」所需的安全垫。
内存水位不能用 used/total
page cache 会让 used 长期接近 100%。必须用 MemAvailable 计算,否则告警永远在响。
HPA 只看 CPU
IO 密集或连接数瓶颈的服务 CPU 不高但已经饱和。应补充内存、自定义 QPS 或队列长度指标。