使用ASM全局限流实现源IP分别限流

简介: 本文介绍了如何在ASM中实现基于源IP的全局限流,防止恶意请求。内容包括前提条件、准备工作、部署步骤及验证方法,帮助用户通过配置限流策略保障业务入口的稳定性与安全性。

对于业务入口来说,为了实现公平访问,防止某些客户端恶意发送大量请求,会有需要根据不同的请求源IP分别限制每个IP的请求速率的需求。本文主要阐述如何基于ASM的全局限流能力实现源IP分别限流场景。

前提条件

  • 已添加Kubernetes托管版集群到ASM实例,且ASM实例为1.25及以上。具体操作,请参见添加集群到ASM实例
  • 已为Kubernetes集群中的default命名空间开启自动注入。具体操作,请参见启用自动注入
  • 已创建名为ingressgateway的入口网关,并开启80端口。具体操作,请参见创建入口网关

准备工作

  1. 部署全局限流服务依赖的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
  1. 部署全局限流服务
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
  1. 部署示例服务和路由规则
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

实践步骤

  1. 部署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
  1. 执行以下命令,获取全局限流服务配置
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
  1. 将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
  1. 执行以下命令用相同客户端连续访问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
<

说明限流已经生效。使用不同客户端时,可发现请求仍然可以正常访问

相关文章
|
人工智能 缓存 Kubernetes
ACK GIE配置建议
Gateway with Inference Extension是基于Kubernetes社区Gateway API及其扩展规范实现的增强型组件,支持四层/七层路由服务,并面向生成式AI推理场景提供负载均衡优化、服务管理简化等能力,适用于AI推理服务的高可用部署与性能优化。在不同的场景使用ACK Gateway with Inference Extension时,可能需要根据业务需求和高可用需要对网关和推理扩展进行不同的配置调整。本文主要介绍在实际业务场景中针对ACK GIE的配置建议,以获得更好的使用效果。
935 23
|
10月前
|
API
使用ACK推理网关基于域名路由到不同模型服务
本文介绍如何在ACK推理网关中通过Gateway API配置基于不同域名的路由规则,实现将请求按域名分发至qwen和deepseek等不同模型服务,并提供完整的操作步骤与测试示例。
|
人工智能 Java Serverless
【MCP教程系列】搭建基于 Spring AI 的 SSE 模式 MCP 服务并自定义部署至阿里云百炼
本文详细介绍了如何基于Spring AI搭建支持SSE模式的MCP服务,并成功集成至阿里云百炼大模型平台。通过四个步骤实现从零到Agent的构建,包括项目创建、工具开发、服务测试与部署。文章还提供了具体代码示例和操作截图,帮助读者快速上手。最终,将自定义SSE MCP服务集成到百炼平台,完成智能体应用的创建与测试。适合希望了解SSE实时交互及大模型集成的开发者参考。
15581 60
|
关系型数据库 数据挖掘 分布式数据库
数据库+MCP,0编码自主完成数据洞察
本文介绍了一种全新的数据分析方案,结合PolarDB MySQL版与阿里云百炼,搭配MCP工具实现智能数据库分析应用。该方案解决传统数据分析工具高门槛、低效率的问题,通过零SQL操作和一站式部署,助力企业快速挖掘数据价值。方案具备高性能查询、快响应直连加速、高安全保障及易迁移上云等优势,并详细说明了部署资源、应用配置及验证步骤,帮助用户轻松完成实践体验。
2001 15
使用Gateway with Inference Extension路由外部MaaS服务
本文介绍如何通过Gateway with Inference Extension对接百炼服务,实现请求路由时自动添加API Key并重写路径,包含操作步骤及验证方法。
|
存储 Rust 安全
Rocket框架JWT鉴权实战:保护Rust Web API的安全方案​
本篇文章是基于rust语言和rocket依赖实现网页JWT认证和鉴权,完成简单的JWT token的验证和鉴权处理,使用cargo做依赖的导入和测试。
579 0
|
Linux Docker 容器
Gentoo Linux相关资源与使用注意事项
本文介绍了基于Gentoo Linux搭建高性能Docker容器云的过程。Gentoo以高度自定义和portage包管理著称,虽安装略复杂,但提供精细化的系统控制。通过官方文档与社区资源,可逐步完成系统构建。
|
存储 监控 Java
如何对迁移到Docker容器中的应用进行性能优化?
如何对迁移到Docker容器中的应用进行性能优化?
730 59
|
Linux 数据安全/隐私保护 虚拟化
【赵渝强老师】Docker的私有镜像仓库:Harbor
Harbor是由VMware开发的企业级Docker镜像仓库管理工具,支持权限管理、LDAP集成、日志审计、镜像复制及中文界面等功能。本文详细介绍了Harbor的安装、配置及在Docker中的实战应用流程,涵盖环境准备、部署步骤、基础操作和镜像上传等内容,适用于容器化应用的镜像管理场景。
1137 4
|
关系型数据库 MySQL 数据库
【赵渝强老师】数据库不适合Docker容器化部署的原因
本文介绍了在Docker中部署MySQL数据库并实现数据持久化的方法,同时分析了数据库不适合容器化的原因。通过具体步骤演示如何拉取镜像、创建持久化目录及启动容器,确保数据安全存储。然而,由于数据安全性、硬件资源争用、网络带宽限制及额外隔离层等问题,数据库服务并不完全适合Docker容器化部署。文中还提到数据库一旦部署通常无需频繁升级,与Docker易于重构和重新部署的特点不符。
679 19
【赵渝强老师】数据库不适合Docker容器化部署的原因