对于业务入口来说,为了实现公平访问,防止某些客户端恶意发送大量请求,会有需要根据不同的请求源IP分别限制每个IP的请求速率的需求。本文主要阐述如何基于ASM的全局限流能力实现源IP分别限流场景。
前提条件
- 已添加Kubernetes托管版集群到ASM实例,且ASM实例为1.25及以上。具体操作,请参见添加集群到ASM实例。
- 已为Kubernetes集群中的default命名空间开启自动注入。具体操作,请参见启用自动注入。
- 已创建名为ingressgateway的入口网关,并开启80端口。具体操作,请参见创建入口网关。
准备工作
- 部署全局限流服务依赖的redis服务(可使用Tair替代)
kubectl apply -f- <<EOF kind: Namespace apiVersion: v1 metadata: name: redis-system --- apiVersion: apps/v1 kind: StatefulSet metadata: name: redis namespace: redis-system labels: app: redis spec: serviceName: "redis" replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - image: registry-cn-hangzhou.ack.aliyuncs.com/dev/redis:6.0.6-for-ack-gateway name: redis ports: - containerPort: 6379 resources: limits: cpu: 1500m memory: 512Mi requests: cpu: 200m memory: 256Mi --- apiVersion: v1 kind: Service metadata: name: redis namespace: redis-system labels: app: redis spec: ports: - name: redis port: 6379 protocol: TCP targetPort: 6379 selector: app: redis EOF
- 部署全局限流服务
kubectl apply -f- <<EOF 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: registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/envoy-ratelimit:v1.4.0-g2210ce0-aliyun imagePullPolicy: Always name: ratelimit command: ["/bin/ratelimit"] env: - name: LOG_LEVEL value: debug - name: REDIS_SOCKET_TYPE value: tcp - name: REDIS_URL value: redis.redis-system.svc.cluster.local: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 EOF
- 部署示例服务和路由规则
kubectl apply -f- <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: httpbin --- apiVersion: v1 kind: Service metadata: name: httpbin labels: app: httpbin service: httpbin spec: ports: - name: http port: 8000 targetPort: 80 selector: app: httpbin --- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin spec: replicas: 1 selector: matchLabels: app: httpbin version: v1 template: metadata: labels: app: httpbin version: v1 annotations: sidecar.istio.io/inject: "true" spec: serviceAccountName: httpbin containers: - image: registry.cn-hangzhou.aliyuncs.com/acs/httpbin:latest imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 80 --- apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: gateways: - httpbin-gateway hosts: - bf2.example.com http: - name: httpbin-route route: - destination: host: httpbin port: number: 8000
实践步骤
- 部署asmglobalratelimiter资源
kubectl apply -f- <<EOF apiVersion: istio.alibabacloud.com/v1 kind: ASMGlobalRateLimiter metadata: name: global-test2 namespace: istio-system spec: configs: - limit: quota: 100000 unit: SECOND limit_overrides: - limit: quota: 1 unit: MINUTE request_match: remote_address: distinct: true match: vhost: name: bf2.example.com port: 80 route: name_match: httpbin-route name: httpbin isGateway: true rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 workloadSelector: labels: app: istio-ingressgateway EOF
- 执行以下命令,获取全局限流服务配置
kubectl get asmglobalratelimiter global-test -n istio-system -o yaml
预期输出
apiVersion: istio.alibabacloud.com/v1 kind: ASMGlobalRateLimiter metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: > {"apiVersion":"istio.alibabacloud.com/v1","kind":"ASMGlobalRateLimiter","metadata":{"annotations":{},"name":"global-test2","namespace":"istio-system"},"spec":{"configs":[{"limit":{"quota":100000,"unit":"SECOND"},"limit_overrides":[{"limit":{"quota":1,"unit":"MINUTE"},"request_match":{"remote_address":{"distinct":true}}}],"match":{"vhost":{"name":"bf2.example.com","port":80,"route":{"name_match":"httpbin-route"}}},"name":"httpbin"}],"isGateway":true,"rateLimitService":{"host":"ratelimit.default.svc.cluster.local","port":8081,"timeout":{"seconds":5}},"workloadSelector":{"labels":{"app":"istio-ingressgateway"}}}} creationTimestamp: '2025-07-24T02:02:20Z' generation: 3 name: global-test2 namespace: istio-system resourceVersion: '35117' uid: 81f60d14-ae73-411f-b6b4-57f071e36539 spec: configs: - limit: quota: 100000 unit: SECOND limit_overrides: - limit: quota: 1 unit: MINUTE request_match: remote_address: distinct: true match: vhost: name: bf2.example.com port: 80 route: name_match: httpbin-route name: httpbin isGateway: true rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 workloadSelector: labels: app: istio-ingressgateway status: config.yaml: | descriptors: - descriptors: - key: remote_address rate_limit: requests_per_unit: 1 unit: MINUTE key: generic_key rate_limit: requests_per_unit: 100000 unit: SECOND value: RateLimit[global-test2.istio-system]-Id[3387964427] domain: ratelimit.default.svc.cluster.local message: ok status: successful
- 将asmglobalratelimiter的status中的全局限流服务配置粘贴至限流服务configmap中
kubectl apply -f- <<EOF apiVersion: v1 kind: ConfigMap metadata: name: ratelimit-config data: config.yaml: | descriptors: - descriptors: - key: remote_address rate_limit: requests_per_unit: 1 unit: MINUTE key: generic_key rate_limit: requests_per_unit: 100000 unit: SECOND value: RateLimit[global-test2.istio-system]-Id[3387964427] domain: ratelimit.default.svc.cluster.local EOF
- 执行以下命令用相同客户端连续访问ASM网关两次
export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://$GATEWAY_URL:80/get -H "host:bf2.example.com" curl http://$GATEWAY_URL:80/get -H "host:bf2.example.com"
第二次访问时预期输出如下
< HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true < x-ratelimit-limit: 1, 1;w=60, 100000;w=1 < x-ratelimit-remaining: 0 < x-ratelimit-reset: 33 < date: Thu, 24 Jul 2025 02:48:27 GMT < server: istio-envoy < content-length: 0 <
说明限流已经生效。使用不同客户端时,可发现请求仍然可以正常访问