ALB 限流不是把流量挡在 K8s 集群外,而是把”超额请求”在云厂商的边缘负载均衡上直接拒绝。本文基于 alibaba-load-balancer-controller 源码梳理 ACK ALB Ingress 的 TrafficLimit 用法,包括注解、自定义 Action、组合写法与避坑指南。

为什么要在 ALB 上做限流?

在 Kubernetes 集群里,限流通常有两种做法:

位置 典型实现 优点 缺点
业务代码 / 中间件 Sentinel、Istio 限流 Filter 灵活、可基于业务维度 回源后才拦截,浪费带宽;与业务耦合
云负载均衡边缘 ALB TrafficLimit Action 拒绝在边缘发生、不回源、纯声明式 维度有限,只看 IP / 全局 QPS

对于”防爬虫、防刷、秒杀压测兜底、批量接口保护”这类典型场景,把限流下推到 ALB 才是最经济的

  • ALB 直接返回 HTTP 503,请求不会到达后端 Pod,省回源带宽、省 Pod 算力;
  • 通过 Ingress 注解或 actions 自定义即可下发,无需修改业务代码;
  • 限流阈值随 Ingress 一起 kubectl apply,与 GitOps 流水线天然契合。

能力概览

ACK ALB Controller 通过 Ingress Annotation自定义 Action 两种方式下发 ALB 的 TrafficLimit 规则。

维度 说明
作用对象 单条 Ingress 路由(或通过自定义 Action 精确到路径)
生效位置 ALB 七层监听器(HTTP / HTTPS),四层监听器不生效
维度 1 全局限流:限制整个 Ingress 的总 QPS(TrafficLimitConfig.QPS
维度 2 单 IP 限流:限制每个客户端 IP 的 QPS(TrafficLimitConfig.PerIpQps
生效顺序 两个维度同时存在时,ALB 取”先触发”的那一个(源码校验 PerIpQps < QPS
取值范围 1 ~ 100000(整数,源码在 model_build_listener_rules.go 做范围校验)
超出行为 直接返回 HTTP 503,请求不回源

源码位置(alibaba-load-balancer-controller):

  • 注解常量:pkg/controller/ingress/reconcile/annotations/annotations.go(L82-83)
  • 模型定义:pkg/model/alb/alb.go :: TrafficLimitConfig(L248-251)
  • 取值范围:pkg/util/constant.go :: ActionTrafficLimitQpsMin = 1(L342)
  • 构建逻辑:pkg/controller/ingress/reconcile/builder/albconfig_manager/model_build_listener_rules.go :: buildQpsLimitAction(L736-793)
  • SDK 转换:pkg/provider/alibaba/alb/rule.go(L387-396 / L757-792)

两种使用方式

方式 1:注解形式(整 Ingress 范围生效,最简单)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-with-rate-limit
namespace: default
annotations:
alb.ingress.kubernetes.io/traffic-limit-qps: "1000" # 全局
alb.ingress.kubernetes.io/traffic-limit-ip-qps: "10" # 每 IP
spec:
ingressClassName: alb
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-api-svc
port:
number: 80

要点:

  • 两个注解都是可选的,只填一个也可生效。
  • 两个都填时,源码会校验 PerIpQps < QPS,否则 reconcile 失败并提示 traffic limit action qps per ip must less than qps

方式 2:自定义 Action 形式(路径级,可与转发策略组合)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-path-level-limit
namespace: default
annotations:
alb.ingress.kubernetes.io/actions.heavy-svc: |
[{"type":"TrafficLimit","TrafficLimitConfig":{"QPS":"50"}}]
alb.ingress.kubernetes.io/actions.light-svc: |
[{"type":"TrafficLimit","TrafficLimitConfig":{"PerIpQps":"20"}}]
spec:
ingressClassName: alb
rules:
- host: api.example.com
http:
paths:
- path: /heavy
pathType: Prefix
backend:
service: { name: heavy-svc, port: { number: 80 } }
- path: /light
pathType: Prefix
backend:
service: { name: light-svc, port: { number: 80 } }

要点:

  • actions.<svcName> 的 JSON 数组里可以ForwardGroup / InsertHeader / Rewrite 等组合,实现”先限流再转发”。
  • QPS / PerIpQps 必须是字符串数字(如 "50"),来自源码 transSDKTrafficLimitConfigToCreateRules

互斥规则

源码(model_build_listener_rules.go:867-873)中明确:注解形式(traffic-limit-qps / traffic-limit-ip-qps)与自定义 Action 中的 TrafficLimit 不能同时存在,否则 reconcile 报错:

1
can't exist action trafficlimit and annotation traffic-limit-qps at the same time

4 个典型用法配置

下面给出一份可一键 kubectl apply -f 的完整示例,覆盖最常见的 4 种用法。

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# =============================================================================
# ALB 限流基础用法配置示例
# 来源:alibaba-load-balancer-controller
# - 注解常量:pkg/controller/ingress/reconcile/annotations/annotations.go
# AlbTrafficLimitQps = alb.ingress.kubernetes.io/traffic-limit-qps
# AlbTrafficLimitIpQps = alb.ingress.kubernetes.io/traffic-limit-ip-qps
# - 模型字段:pkg/model/alb/alb.go :: TrafficLimitConfig { QPS, PerIpQps }
# - 取值范围:pkg/util/constant.go :: ActionTrafficLimitQpsMin = 1(实际 1~100000)
# - 构建逻辑:pkg/controller/ingress/reconcile/builder/albconfig_manager/
# model_build_listener_rules.go :: buildQpsLimitAction
# =============================================================================

apiVersion: v1
kind: Namespace
metadata:
name: alb-demo
---
# 演示用后端 Service(2 副本,提供 / 与 /healthz)
apiVersion: v1
kind: Service
metadata:
name: backend-api-svc
namespace: alb-demo
spec:
selector:
app: backend-api
ports:
- name: http
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-api
namespace: alb-demo
spec:
replicas: 2
selector:
matchLabels:
app: backend-api
template:
metadata:
labels:
app: backend-api
spec:
containers:
- name: app
image: nginx:1.25-alpine
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
---
# -----------------------------------------------------------------------------
# 1) 全局限流:traffic-limit-qps
# 整个 Ingress 路由的请求被限制为 100 QPS,超额返回 HTTP 503。
# -----------------------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-global-qps
namespace: alb-demo
annotations:
alb.ingress.kubernetes.io/traffic-limit-qps: "100" # 全局 100 QPS
spec:
ingressClassName: alb
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-api-svc
port:
number: 80
---
# -----------------------------------------------------------------------------
# 2) 单 IP 限流:traffic-limit-ip-qps
# 每个客户端 IP 最多 5 QPS,防止单 IP 滥用。
# -----------------------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-per-ip-qps
namespace: alb-demo
annotations:
alb.ingress.kubernetes.io/traffic-limit-ip-qps: "5" # 单 IP 5 QPS
spec:
ingressClassName: alb
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-api-svc
port:
number: 80
---
# -----------------------------------------------------------------------------
# 3) 组合限流:全局 + 单 IP
# 同时启用两层限流:全局 1000 QPS + 每 IP 10 QPS(取两者最小生效)。
# 注意:源码校验要求 PerIpQps < QPS,否则构建失败并报
# "traffic limit action qps per ip must less than qps"。
# -----------------------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-combined-qps
namespace: alb-demo
annotations:
alb.ingress.kubernetes.io/traffic-limit-qps: "1000"
alb.ingress.kubernetes.io/traffic-limit-ip-qps: "10"
spec:
ingressClassName: alb
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-api-svc
port:
number: 80
---
# -----------------------------------------------------------------------------
# 4) 路径级细粒度限流:通过 alb.ingress.kubernetes.io/actions.<svc> 自定义
# 不同路径使用不同 Service,并对每条路径单独设置 TrafficLimit Action。
# 该写法对应源码 :: model_build_listener_rules.go :: buildQpsLimitAction
# 其中 QPS/PerIpQps 为字符串数字(如 "50" / "20")。
# -----------------------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-path-level-qps
namespace: alb-demo
annotations:
# /heavy 路径:全局 50 QPS
alb.ingress.kubernetes.io/actions.heavy-svc: |
[{"type":"TrafficLimit","TrafficLimitConfig":{"QPS":"50"}}]
# /light 路径:每 IP 20 QPS
alb.ingress.kubernetes.io/actions.light-svc: |
[{"type":"TrafficLimit","TrafficLimitConfig":{"PerIpQps":"20"}}]
spec:
ingressClassName: alb
rules:
- host: api.example.com
http:
paths:
- path: /heavy
pathType: Prefix
backend:
service:
name: heavy-svc
port:
number: 80
- path: /light
pathType: Prefix
backend:
service:
name: light-svc
port:
number: 80

典型场景速查

场景 推荐配置 说明
活动期间保护后端 traffic-limit-qps: "100" 全局硬上限,超额直接 503
防爬虫 / 防刷 traffic-limit-ip-qps: "5" 每个客户端 IP 最多 5 QPS
生产推荐组合 traffic-limit-qps: "1000" + traffic-limit-ip-qps: "10" 全局兜底 + 每 IP 防滥用
路径级差异化 actions.<svc> + TrafficLimit 重接口 / 价值低的接口单独配

一句话原则:接口越重、价值越低,越要限——例如管理后台、报表导出、批量接口单独配限。

与 ALB 自定义转发的组合写法

TrafficLimit 类型的 Action 可以和 ForwardGroupRewriteInsertHeaderFixedResponse 等并列存在。下面是一个”先限流、再插头部、再转发到指定 server group”的例子:

1
2
3
4
5
6
7
annotations:
alb.ingress.kubernetes.io/actions.limited-fwd: |
[
{"type":"TrafficLimit","TrafficLimitConfig":{"QPS":"200","PerIpQps":"20"}},
{"type":"InsertHeader","InsertHeaderConfig":{"key":"X-Rate-Limited","value":"true","valueType":"UserDefined"}},
{"type":"ForwardGroup","ForwardConfig":{"ServerGroups":[{"ServerGroupID":"sgp-xxxxxxxx","Weight":100}]}}
]

说明:QPSPerIpQps 同时配置时,源码同样校验 PerIpQps < QPS

验证生效

压测观测

1
2
3
4
# 一次性发超过阈值的请求
ab -n 2000 -c 50 -H "Host: api.example.com" http://<ALB-endpoint>/

# 观察响应码分布:超过限流的部分会返回 HTTP 503

在 ALB 控制台确认

监控 → ALB 实例 → 选择实例 → 访问日志 / 监控指标

  • QPS
  • 丢弃请求数(限流丢弃)
  • 限流触发次数

检查控制器是否识别了注解

1
kubectl describe ingress <ingress-name> -n <ns> | grep -A 5 "Annotations"

期望看到:

1
2
alb.ingress.kubernetes.io/traffic-limit-qps:    1000
alb.ingress.kubernetes.io/traffic-limit-ip-qps: 10

如果 controller 在 reconcile 过程中判定限流值非法(例如 PerIpQps >= QPS),会在 Ingress 或 AlbConfig 的 status / 事件中报错,可通过 kubectl describe ingresskubectl get events 查看原因。

常见问题

问题 原因与处置
reconcile 一直失败:traffic limit action qps out of range QPS 取值需 >= 1,且 <= 100000
reconcile 一直失败:qps per ip must less than qps 同时配置两个注解时,PerIpQps 必须严格小于 QPS
can't exist action trafficlimit and annotation traffic-limit-qps at the same time 注解形式与自定义 Action 形式互斥,二选一
限流不生效 确认 ingressClassName: alb、且走的是 ALB 七层监听器(HTTP/HTTPS),四层监听器不生效
修改后没生效 注解变更后 controller reconcile 需要 10~30s,可用 kubectl get albconfig -w 观察

源码速查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
pkg/controller/ingress/reconcile/annotations/annotations.go
82: AlbTrafficLimitQps = AnnotationAlbPrefix + "traffic-limit-qps"
83: AlbTrafficLimitIpQps = AnnotationAlbPrefix + "traffic-limit-ip-qps"

pkg/controller/ingress/reconcile/builder/albconfig_manager/model_build_listener_rules.go
736-793: buildQpsLimitAction(qps, qpsPerIp)
- 校验 qpsi >= ActionTrafficLimitQpsMin (1)
- 校验 PerIpQps < QPS
- 构造 alb.Action{Type:"TrafficLimit", TrafficLimitConfig:{QPS, PerIpQps}}
867-873: 互斥校验:注解形式与自定义 Action 不能同时存在

pkg/model/alb/alb.go
248-251: type TrafficLimitConfig struct {
QPS int
PerIpQps int
}

pkg/util/constant.go
342: ActionTrafficLimitQpsMin = 1

pkg/provider/alibaba/alb/rule.go
387-396: 数字转字符串后写入 ALB OpenAPI QPS / PerIpQps
757-792: transSDKTrafficLimitConfigToCreateRules

总结

把限流下推到 ALB 边缘,是用 ACK 时最被低估的”省成本”手段之一。它的核心价值在于:

  1. 声明式:用 Ingress 注解就能配置,随 GitOps 一起发布;
  2. 零回源:超额请求在 ALB 边缘被直接拒绝,省回源带宽、省 Pod 算力;
  3. 双维度:全局 + 单 IP 双层防护覆盖大多数典型场景;
  4. 可组合TrafficLimit 可以与 ForwardGroup / InsertHeader 等 Action 组合,写法灵活。

踩坑要点只有三个:取值范围 1~100000、**PerIpQps < QPS注解与自定义 Action 互斥**。把这三条记牢,剩下的就交给 ALB 即可。

参考