使用ASMGlobalRateLimiter對應(yīng)用服務(wù)入口流量配置全局限流
限流是一種限制發(fā)送到服務(wù)端的請求數(shù)量的機制。它指定客戶端在給定時間段內(nèi)可以向服務(wù)端發(fā)送的最大請求數(shù),通常表示為一段時間內(nèi)的請求數(shù),例如每分鐘300個請求或每秒10個請求等。服務(wù)網(wǎng)格ASM自1.18.0.131版本起,支持針對入口網(wǎng)關(guān)和注入了Sidecar的應(yīng)用服務(wù)的入口流量配置全局限流。本文介紹如何在ASM中使用ASMGlobalRateLimiter對應(yīng)用服務(wù)入口流量配置全局限流。
前提條件
已添加Kubernetes托管版集群到ASM實例,且ASM實例為1.18.X.XXX及以上。具體操作,請參見添加集群到ASM實例。
已為Kubernetes集群中的default命名空間開啟自動注入。具體操作,請參見啟用自動注入。
已創(chuàng)建名為ingressgateway的入口網(wǎng)關(guān),并開啟80端口。具體操作,請參見創(chuàng)建入口網(wǎng)關(guān)。
已完成sleep和httpbin示例應(yīng)用的部署。具體操作,請參見在數(shù)據(jù)面集群中部署httpbin應(yīng)用和在數(shù)據(jù)面集群部署sleep服務(wù)。
部署限流服務(wù)
您需要先在數(shù)據(jù)面集群中部署限流服務(wù),才能使全局限流功能生效。部署限流服務(wù)和示例應(yīng)用的步驟如下。
Envoy代理實現(xiàn)限流主要有兩種方式:全局限流、本地限流。本文僅介紹全局限流的配置方法。關(guān)于限流的相關(guān)概念以及如何配置本地限流,請參見在流量管理中心配置本地限流。
使用以下內(nèi)容,創(chuàng)建ratelimit-svc.yaml。
apiVersion: v1 kind: ServiceAccount metadata: name: redis --- apiVersion: v1 kind: Service metadata: name: redis labels: app: redis spec: ports: - name: redis port: 6379 selector: app: redis --- apiVersion: apps/v1 kind: Deployment metadata: name: redis spec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis sidecar.istio.io/inject: "false" spec: containers: - image: redis:alpine imagePullPolicy: Always name: redis ports: - name: redis containerPort: 6379 restartPolicy: Always serviceAccountName: redis --- apiVersion: v1 kind: ConfigMap metadata: name: ratelimit-config data: config.yaml: | {} --- apiVersion: v1 kind: Service metadata: name: ratelimit labels: app: ratelimit spec: ports: - name: http-port port: 8080 targetPort: 8080 protocol: TCP - name: grpc-port port: 8081 targetPort: 8081 protocol: TCP - name: http-debug port: 6070 targetPort: 6070 protocol: TCP selector: app: ratelimit --- apiVersion: apps/v1 kind: Deployment metadata: name: ratelimit spec: replicas: 1 selector: matchLabels: app: ratelimit strategy: type: Recreate template: metadata: labels: app: ratelimit sidecar.istio.io/inject: "false" spec: containers: # Latest image from https://hub.docker.com/r/envoyproxy/ratelimit/tags - image: envoyproxy/ratelimit:e059638d imagePullPolicy: Always name: ratelimit command: ["/bin/ratelimit"] env: - name: LOG_LEVEL value: debug - name: REDIS_SOCKET_TYPE value: tcp - name: REDIS_URL value: redis:6379 - name: USE_STATSD value: "false" - name: RUNTIME_ROOT value: /data - name: RUNTIME_SUBDIRECTORY value: ratelimit - name: RUNTIME_WATCH_ROOT value: "false" - name: RUNTIME_IGNOREDOTFILES value: "true" ports: - containerPort: 8080 - containerPort: 8081 - containerPort: 6070 volumeMounts: - name: config-volume # $RUNTIME_ROOT/$RUNTIME_SUBDIRECTORY/$RUNTIME_APPDIRECTORY/config.yaml mountPath: /data/ratelimit/config volumes: - name: config-volume configMap: name: ratelimit-config
在ACK集群對應(yīng)的KubeConfig環(huán)境下,執(zhí)行以下命令,在集群中創(chuàng)建限流服務(wù)和限流服務(wù)依賴的Redis服務(wù)。
kubectl apply -f ratelimit-svc.yaml
場景一:對服務(wù)的特定端口配置全局限流
對httpbin服務(wù)的8000端口進(jìn)行限流。配置限流規(guī)則后,發(fā)往httpbin服務(wù)8000端口的所有請求都將受到流量速率限制。
使用以下內(nèi)容,創(chuàng)建global-ratelimit-svc.yaml。
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMGlobalRateLimiter metadata: name: global-svc-test namespace: default spec: workloadSelector: labels: app: httpbin rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 isGateway: false configs: - name: httpbin limit: unit: MINUTE quota: 1 match: vhost: name: '*' port: 8000
部分字段說明如下。關(guān)于字段的更多信息,請參見ASMGlobalRateLimiter CRD說明。
字段
說明
workloadSelector
用于匹配限流生效的工作負(fù)載。本場景中全局限流生效于httpbin服務(wù)的工作負(fù)載,設(shè)置為
app: httpbin
。isGateway
是否作用于網(wǎng)關(guān)。本示例中設(shè)定為
false
。rateLimitService
限流服務(wù)的域名、端口和連接超時設(shè)置。根據(jù)場景一:對服務(wù)的特定端口配置全局限流中部署的限流服務(wù),配置如下:
host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5
limit
需要生效的限流配置參數(shù)。其中
unit
表示限流檢測的時間單位,quota
表示單位時間內(nèi)允許的請求總量。本示例配置
unit
為MINUTE
、quota
為1
,表示匹配路由上每分鐘只能發(fā)送一個請求,超出的請求將被限流。vhost
限流匹配的域名和路由項配置。在生效于應(yīng)用服務(wù)時,
name
需要填寫為'*'
,port
需要填寫為服務(wù)的Service端口。在ASM實例對應(yīng)的KubeConfig環(huán)境下,執(zhí)行以下命令,創(chuàng)建生效于應(yīng)用服務(wù)httpbin入口流量的全局限流規(guī)則。
kubectl apply -f global-ratelimit-svc.yaml
執(zhí)行以下命令,獲取調(diào)諧完成的全局限流規(guī)則配置內(nèi)容。
kubectl get asmglobalratelimiter global-svc-test -o yaml
apiVersion: istio.alibabacloud.com/v1 kind: ASMGlobalRateLimiter metadata: name: global-svc-test namespace: default spec: configs: - limit: quota: 1 unit: MINUTE match: vhost: name: '*' port: 8000 name: httpbin isGateway: false rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 workloadSelector: labels: app: httpbin status: config.yaml: | descriptors: - key: generic_key rate_limit: requests_per_unit: 1 unit: MINUTE value: RateLimit[global-svc-test.default]-Id[3833670472] domain: ratelimit.default.svc.cluster.local message: ok status: successful
將上一步預(yù)期輸出的ASMGlobalRateLimiter資源中
status
字段的config.yaml
內(nèi)容,粘貼至ratelimit-config.yaml,生成全局限流服務(wù)配置。ASMGlobalRateLimiter中
status
字段下的config.yaml
字段中的字符串內(nèi)容,需原樣粘貼至ConfigMap中data
中的同名config.yaml
字段中。apiVersion: v1 kind: ConfigMap metadata: name: ratelimit-config data: config.yaml: | descriptors: - key: header_match rate_limit: requests_per_unit: 1 unit: MINUTE value: RateLimit[global-svc-test.default]-Id[1492204717] domain: ratelimit.default.svc.cluster.local
在ACK集群對應(yīng)的KubeConfig環(huán)境下,執(zhí)行以下命令,在集群中更新全局限流服務(wù)配置。
kubectl apply -f ratelimit-config.yaml
執(zhí)行以下命令,進(jìn)入sleep應(yīng)用開啟bash。
kubectl exec -it deploy/sleep -- sh
執(zhí)行以下命令,連續(xù)訪問httpbin服務(wù)兩次。
curl httpbin:8000/get -v curl httpbin:8000/get -v
預(yù)期輸出:
< HTTP/1.1 429 < x-envoy-ratelimited: true < x-ratelimit-limit: 1, 1;w=60 < x-ratelimit-remaining: 0 < x-ratelimit-reset: 5 < date: Thu, 26 Oct 2023 04:23:54 GMT < server: envoy < content-length: 0 < x-envoy-upstream-service-time: 2 < * Connection #0 to host httpbin left intact
在全局限流配置中,限制1分鐘之內(nèi)只能有一次訪問httpbin服務(wù)的請求。當(dāng)連續(xù)兩次訪問httpbin服務(wù)時,可以看到第二條請求被限流,表明對注入Sidecar的應(yīng)用服務(wù)入口流量配置全局限流成功。
場景二:在服務(wù)特定端口上,針對發(fā)往指定路徑的請求進(jìn)行限流
對httpbin服務(wù)的8000端口進(jìn)行限流,并限制限流只生效在訪問/headers
路徑的請求上。配置限流規(guī)則后,發(fā)往httpbin服務(wù)8000端口、且訪問路徑/headers
的所有請求都將受到流量速率限制。
根據(jù)ASM版本,按需選擇以下內(nèi)容,創(chuàng)建global-ratelimit-svc.yaml。
ASM版本為1.19.0以下:
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMGlobalRateLimiter metadata: name: global-svc-test namespace: default spec: workloadSelector: labels: app: httpbin rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 isGateway: false configs: - name: httpbin limit: unit: MINUTE quota: 1 match: vhost: name: '*' port: 8000 route: header_match: - name: ":path" prefix_match: "/headers"
ASM版本為1.19.0及以上:
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMGlobalRateLimiter metadata: name: global-svc-test namespace: default spec: workloadSelector: labels: app: httpbin rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 isGateway: false configs: - name: httpbin limit: unit: SECOND quota: 100000 match: vhost: name: '*' port: 8000 limit_overrides: - request_match: header_match: - name: ":path" prefix_match: "/headers" limit: unit: MINUTE quota: 1
部分字段說明如下。關(guān)于字段的更多信息,請參見ASMGlobalRateLimiter CRD說明。
字段
說明
workloadSelector
用于匹配限流生效的工作負(fù)載。本場景中全局限流生效于httpbin服務(wù)的工作負(fù)載,設(shè)置為
app: httpbin
。isGateway
是否作用于網(wǎng)關(guān)。本示例設(shè)定為
false
。rateLimitService
限流服務(wù)的域名、端口和連接超時設(shè)置。根據(jù)場景二:在服務(wù)特定端口上,針對發(fā)往指定路徑的請求進(jìn)行限流中部署的限流服務(wù),配置如下:
host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5
limit
需要生效的限流配置參數(shù)。其中
unit
表示限流檢測的時間單位,quota
表示單位時間內(nèi)允許的請求總量。本示例配置
unit
為MINUTE
、quota
為1
,表示匹配路由上每分鐘只能發(fā)送一個請求,超出的請求將被限流。在ASM實例為1.19.0及以上版本,限流配置參數(shù)為每秒100000個請求,約等于沒有限流,因為針對滿足特定條件請求的限流生效在
limit_overrides
字段中。vhost
限流匹配的域名和路由項配置。在生效于應(yīng)用服務(wù)時,
name
需要填寫為'*'
,port
需要填寫為服務(wù)的Service端口。在ASM實例為1.19.0以下版本,您還可以在
route
中配置針對請求的Header匹配規(guī)則。本示例中匹配名為:path
的特殊Header,即匹配請求的路徑,語義為匹配所有路徑以/
開頭的請求。在ASM實例為1.19.0及以上版本,在
route
中配置針對請求的Header匹配規(guī)則被移動到limit_overrides
字段中。
limit_overrides
限流覆蓋配置,僅支持ASM實例為1.19.0及以上版本。支持匹配請求的不同屬性,并對匹配到的特定請求應(yīng)用單獨的限流配置。在本示例中,
limit_overrides
字段里指定了匹配特殊的Header:path
,即匹配請求的路徑,語義為匹配所有路徑以/headers
開頭的請求。
在ASM實例對應(yīng)的KubeConfig環(huán)境下,執(zhí)行以下命令,創(chuàng)建生效于應(yīng)用服務(wù)httpbin入口流量的全局限流規(guī)則。
kubectl apply -f global-ratelimit-svc.yaml
執(zhí)行以下命令,獲取調(diào)諧完成的全局限流規(guī)則配置內(nèi)容。
kubectl get asmglobalratelimiter global-svc-test -o yaml
apiVersion: istio.alibabacloud.com/v1 kind: ASMGlobalRateLimiter metadata: name: global-svc-test namespace: default spec: configs: - limit: quota: 100000 unit: SECOND limit_overrides: - limit: quota: 1 unit: MINUTE request_match: header_match: - name: :path prefix_match: /headers match: vhost: name: '*' port: 8000 name: httpbin isGateway: false rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 workloadSelector: labels: app: httpbin status: config.yaml: | descriptors: - descriptors: - key: header_match rate_limit: requests_per_unit: 1 unit: MINUTE value: RateLimit[global-svc-test.default]-Id[2613586978] key: generic_key rate_limit: requests_per_unit: 100000 unit: SECOND value: RateLimit[global-svc-test.default]-Id[2613586978] domain: ratelimit.default.svc.cluster.local message: ok status: successful
將上一步預(yù)期輸出的ASMGlobalRateLimiter資源中
status
字段的config.yaml
內(nèi)容,粘貼至ratelimit-config.yaml,生成全局限流服務(wù)配置。ASMGlobalRateLimiter中
status
字段下的config.yaml
字段中的字符串內(nèi)容,需原樣粘貼至ConfigMap中data
中的同名config.yaml
字段中。apiVersion: v1 kind: ConfigMap metadata: name: ratelimit-config data: config.yaml: | descriptors: - descriptors: - key: header_match rate_limit: requests_per_unit: 1 unit: MINUTE value: RateLimit[global-svc-test.default]-Id[2613586978] key: generic_key rate_limit: requests_per_unit: 100000 unit: SECOND value: RateLimit[global-svc-test.default]-Id[2613586978] domain: ratelimit.default.svc.cluster.local
在ACK集群對應(yīng)的KubeConfig環(huán)境下,執(zhí)行以下命令,在集群中更新全局限流服務(wù)配置。
kubectl apply -f ratelimit-config.yaml
執(zhí)行以下命令,進(jìn)入sleep應(yīng)用開啟bash。
kubectl exec -it deploy/sleep -- sh
執(zhí)行以下命令,連續(xù)訪問httpbin服務(wù)的
/headers
路徑兩次。curl httpbin:8000/headers -v curl httpbin:8000/headers -v
預(yù)期輸出:
< HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true < x-ratelimit-limit: 1, 1;w=60 < x-ratelimit-remaining: 0 < x-ratelimit-reset: 5 < date: Thu, 26 Oct 2023 04:23:54 GMT < server: envoy < content-length: 0 < x-envoy-upstream-service-time: 2 < * Connection #0 to host httpbin left intact
在全局限流配置中,限制在
/headers
路徑上,1分鐘之內(nèi)只能有一次訪問httpbin服務(wù)的請求。當(dāng)連續(xù)兩次訪問httpbin服務(wù)的/headers路徑時,可以看到第二條請求被限流,表明對注入Sidecar的應(yīng)用服務(wù)入口流量配置全局限流成功。執(zhí)行以下命令,訪問httpbin服務(wù)的
/get
路徑。curl httpbin:8000/get -v
* Trying 192.168.243.21:8000... * Connected to httpbin (192.168.243.21) port 8000 (#0) > GET /get HTTP/1.1 > Host: httpbin:8000 > User-Agent: curl/8.1.2 > Accept: */* > < HTTP/1.1 200 OK < server: envoy < date: Thu, 11 Jan 2024 06:25:09 GMT < content-type: application/json < content-length: 431 < access-control-allow-origin: * < access-control-allow-credentials: true < x-envoy-upstream-service-time: 7 < { "args": {}, "headers": { "Accept": "*/*", "Host": "httpbin:8000", "User-Agent": "curl/8.1.2", "X-Envoy-Attempt-Count": "1", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=be10819991ba1a354a89e68b3bed1553c12a4fba8b65fbe0f16299d552680b29;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/sleep" }, "origin": "127.0.0.6", "url": "http://httpbin:8000/get" } * Connection #0 to host httpbin left intact
可以看到發(fā)往httpbin服務(wù)其它路徑的請求并未受到全局限流配置的影響,仍然可以正常訪問。
相關(guān)操作
查看全局限流相關(guān)指標(biāo)
全局限流會產(chǎn)生以下指標(biāo):
指標(biāo) | 指標(biāo)類型 | 描述 |
envoy_cluster_ratelimit_ok | Counter | 被全局限流服務(wù)放行的請求總數(shù) |
envoy_cluster_ratelimit_over_limit | Counter | 被全局限流服務(wù)判定為觸發(fā)限流的請求總數(shù) |
envoy_cluster_ratelimit_error | Counter | 調(diào)用全局限流服務(wù)失敗的請求總數(shù) |
您可以通過配置Sidecar代理的proxyStatsMatcher使Sidecar代理上報相關(guān)指標(biāo),然后使用Prometheus采集并查看限流相關(guān)指標(biāo)。
通過proxyStatsMatcher配置Sidecar代理上報限流指標(biāo)。在配置proxyStatsMatcher時,選中正則匹配,配置為
.*ratelimit.*
。具體操作,請參見proxyStatsMatcher。重新部署httpbin服務(wù)。具體操作,請參見重新部署工作負(fù)載。
參照場景一或在流量管理中心配置本地限流,完成本地限流配置及請求訪問。
執(zhí)行以下命令,查看httpbin服務(wù)的全局限流相關(guān)指標(biāo)。
kubectl exec -it deploy/httpbin -c istio-proxy -- curl localhost:15090/stats/prometheus|grep envoy_cluster_ratelimit
預(yù)期輸出:
# TYPE envoy_cluster_ratelimit_ok counter envoy_cluster_ratelimit_ok{cluster_name="inbound|80||"} 904 # TYPE envoy_cluster_ratelimit_over_limit counter envoy_cluster_ratelimit_over_limit{cluster_name="inbound|80||"} 3223
配置全局限流指標(biāo)采集和告警
您可以配置Prometheus實例采集網(wǎng)格代理暴露的全局限流相關(guān)指標(biāo),并基于關(guān)鍵指標(biāo)配置告警規(guī)則,實現(xiàn)限流發(fā)生時的及時告警。本文以可觀測監(jiān)控Prometheus版為例說明如何配置全局限流指標(biāo)采集和告警。
在可觀測監(jiān)控Prometheus版中,為數(shù)據(jù)面集群接入阿里云ASM組件或升級至最新版,以保證可觀測監(jiān)控Prometheus版可以采集到暴露的全局限流指標(biāo)。關(guān)于接入組件的具體操作,請參見接入組件管理。(如果您已經(jīng)集成自建Prometheus實現(xiàn)網(wǎng)格監(jiān)控來采集服務(wù)網(wǎng)格指標(biāo),則無需做額外操作。)
創(chuàng)建針對全局限流的告警規(guī)則。具體操作,請參見通過自定義PromQL創(chuàng)建Prometheus告警規(guī)則。配置告警規(guī)則的關(guān)鍵參數(shù)的填寫示例如下,其余參數(shù)可參考上述文檔根據(jù)實際需求填寫。
參數(shù)
示例
說明
自定義PromQL語句
(sum by(namespace, service_istio_io_canonical_name) (increase(envoy_cluster_ratelimit_over_limit[1m]))) > 0
通過increase查詢最近1分鐘之內(nèi)被限流的請求數(shù)量,并根據(jù)觸發(fā)限流的服務(wù)所在命名空間以及服務(wù)名稱進(jìn)行分組。當(dāng)1分鐘內(nèi)被限流的請求數(shù)量大于0時觸發(fā)告警。
告警內(nèi)容
發(fā)生全局限流!命名空間:{{$labels.namespace}},觸發(fā)限流的服務(wù):{{$labels.service_istio_io_canonical_name}}。當(dāng)前1分鐘內(nèi)被限流的請求數(shù)量:{{ $value }}
示例的告警信息展示了觸發(fā)限流的服務(wù)所在命名空間以及服務(wù)名稱,以及最近1分鐘內(nèi)發(fā)往該服務(wù)被限流的請求數(shù)量。
相關(guān)文檔
關(guān)于ASMGlobalRateLimiter的字段說明,請參見ASMGlobalRateLimiter CRD說明。
關(guān)于如何在流量管理中心配置本地限流,請參見在流量管理中心配置本地限流。
關(guān)于如何為ASM網(wǎng)關(guān)配置全局限流,請參見為入口網(wǎng)關(guān)配置全局限流。