Use external rate limit service
- deployment the
Envoyproxy ratelimit
service to kubernetes - deployment the redis to serve envoy proxy ratelimit
- use Envoyproxy ratelimit serivce in envoy filter chains through grpc service
- for every workloads create Envoyfilter rule
Deployment the envoy ratelimit service
- the deployment.yaml to reference
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: envoy-ratelimt
5 namespace: istio-system
6 labels:
7 app: envoy-ratelimt
8spec:
9 replicas: 2
10 selector:
11 matchLabels:
12 app: envoy-ratelimt
13 template:
14 metadata:
15 creationTimestamp: null
16 labels:
17 app: envoy-ratelimt
18 spec:
19 volumes:
20 - name: config
21 configMap:
22 name: ratelimit-config
23 defaultMode: 420
24 optional: false
25 containers:
26 - name: ratelimit
27 image: >-
28 envoyproxy/ratelimit:9d8d70a8
29 command:
30 - /bin/ratelimit
31 env:
32 - name: REDIS_SOCKET_TYPE
33 value: tcp
34 - name: REDIS_URL
35 value: redis-master:6379
36 - name: RUNTIME_ROOT
37 value: /data
38 - name: RUNTIME_SUBDIRECTORY
39 value: ratelimit
40 - name: RUNTIME_IGNOREDOTFILES
41 value: 'true'
42 - name: RUNTIME_WATCH_ROOT
43 value: 'false'
44 - name: USE_STATSD
45 value: 'false'
46 - name: LOG_LEVEL
47 value: info
48 resources:
49 limits:
50 cpu: 1024m
51 memory: 1Gi
52 requests:
53 cpu: 256m
54 memory: 256Mi
55 volumeMounts:
56 - name: config
57 mountPath: /data/ratelimit/config
58 mountPropagation: None
59 terminationMessagePath: /dev/termination-log
60 terminationMessagePolicy: File
61 imagePullPolicy: IfNotPresent
62 restartPolicy: Always
63 strategy:
64 type: RollingUpdate
65 rollingUpdate:
66 maxUnavailable: 25%
67 maxSurge: 25%
68 revisionHistoryLimit: 10
69 progressDeadlineSeconds: 600
- the
ratelimit-config
configmap
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: ratelimit-config
5 namespace: istio-system
6data:
7 config.yaml: |
8 domain: envoy-ratelimit
9 descriptors:
10 - key: FIFTY_REQ_PER_MINUTE
11 rate_limit:
12 unit: minute
13 requests_per_unit: 50
14 - key: FIVE_REQ_PER_SECOND
15 rate_limit:
16 unit: second
17 requests_per_unit: 5
18 - key: TEN_REQ_PER_SECOND
19 rate_limit:
20 requests_per_unit: 10
21 unit: second
22 - key: TEN_REQ_PER_MINUTE
23 value: "x-minute-10"
24 rate_limit:
25 requests_per_unit: 10
26 unit: minute
27 - key: TWENTY_REQ_PER_SECOND_BASE_PATH
28 rate_limit:
29 requests_per_unit: 20
30 unit: second
31 value: "/api/version"
32 - key: THREE_REQ_PER_SECOND_HEADER_MATCH
33 value: "get"
34 descriptors:
35 - key: "HEADER_RANGE"
36 value: "x-second-3"
37 rate_limit:
38 requests_per_unit: 3
39 unit: second
- create the
ratelimit-svc
service
1apiVersion: v1
2kind: Service
3metadata:
4 name: ratelimit-svc
5 namespace: istio-system
6status:
7 loadBalancer: {}
8spec:
9 ports:
10 - name: grpc
11 protocol: TCP
12 port: 8081
13 targetPort: 8081
14 - name: http
15 protocol: TCP
16 port: 8080
17 targetPort: 8080
18 selector:
19 app: envoy-ratelimt
20 type: ClusterIP
21 sessionAffinity: None
22 ipFamilies:
23 - IPv4
24 ipFamilyPolicy: SingleStack
25 internalTrafficPolicy: Cluster
Use the ratelimit service for particular workload
1apiVersion: networking.istio.io/v1alpha3
2kind: EnvoyFilter
3metadata:
4 labels:
5 app: demo-api-ratelimit
6 name: demo-api-ratelimit-envoyfilter
7 namespace: default
8spec:
9 workloadSelector:
10 labels:
11 app: demo-api
12 configPatches:
13 - applyTo: HTTP_FILTER
14 match:
15 context: SIDECAR_INBOUND
16 listener:
17 filterChain:
18 filter:
19 name: envoy.filters.network.http_connection_manager
20 subFilter:
21 name: envoy.filters.http.router
22 patch:
23 operation: INSERT_BEFORE
24 value:
25 name: envoy.filters.http.ratelimit
26 typed_config:
27 "@type": "type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit"
28 domain: hpa-ratelimit # must match domain in ratelimit ConfigMap
29 failure_mode_deny: false # run plugin in fail-open mode, no limiting happens if ratelimit is unavailable
30 enable_x_ratelimit_headers: DRAFT_VERSION_03
31 disable_x_envoy_ratelimited_header: true
32 rate_limit_service:
33 grpc_service:
34 envoy_grpc:
35 cluster_name: rate_limit_service
36 timeout: 10s
37 transport_api_version: V3
38
39 - applyTo: CLUSTER
40 match:
41 cluster:
42 # this should be the ratelimit kubernetes service FQDN
43 service: ratelimit-svc.istio-system.svc.cluster.local
44 patch:
45 # add a new cluster for rate limit service
46 operation: ADD
47 value:
48 connect_timeout: 10s
49 load_assignment:
50 cluster_name: rate_limit_service
51 endpoints:
52 - lb_endpoints:
53 - endpoint:
54 address:
55 socket_address:
56 address: ratelimit-svc.istio-system.svc.cluster.local
57 port_value: 8081
58 http2_protocol_options: {}
59 lb_policy: ROUND_ROBIN
60 name: rate_limit_service
61 type: STRICT_DNS
62
63# the match rule reference: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-headermatcher
64 - applyTo: VIRTUAL_HOST
65 match:
66 context: SIDECAR_INBOUND
67 # routeConfiguration:
68 # # portNumber: 80
69 # vhost:
70 # name: inbound|http|80 # port must be a port your Service is listening on
71 routeConfiguration:
72 vhost:
73 name: "inbound|http|80"
74 route:
75 action: ANY
76 patch:
77 operation: MERGE
78 value:
79 rate_limits:
80 - actions:
81 - header_value_match:
82 descriptor_key: "TWENTY_REQ_PER_SECOND_BASE_PATH"
83 descriptor_value: "/api/version"
84 headers:
85 - name: :path
86 prefix_match: /api/version
87 - actions:
88 - request_headers:
89 header_name: ":path"
90 descriptor_key: "FIVE_REQ_PER_SECOND"
91 - actions:
92 - header_value_match:
93 descriptor_key: "TEN_REQ_PER_MINUTE"
94 descriptor_value: "x-minute-10"
95 headers:
96 - name: :method
97 prefix_match: GET
98 - name: x-minute-10
99 range_match:
100 start: 100
101 end: 200
Now use the local ratelimit is better
use istio CR to define the envoy proxy filter
1# local rate limit reference to: https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/local_rate_limit_filter
2# configuration reference: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/local_ratelimit/v3/local_rate_limit.proto#envoy-v3-api-msg-extensions-filters-http-local-ratelimit-v3-localratelimit
3apiVersion: networking.istio.io/v1alpha3
4kind: EnvoyFilter
5metadata:
6 name: demo-api-localratelimit-envoyfilter
7 namespace: default
8spec:
9 workloadSelector:
10 labels:
11 app: demo-api-df79124
12 configPatches:
13 - applyTo: HTTP_FILTER
14 match:
15 context: SIDECAR_INBOUND
16 listener:
17 filterChain:
18 filter:
19 name: "envoy.filters.network.http_connection_manager"
20 patch:
21 operation: INSERT_BEFORE
22 value:
23 name: envoy.filters.http.local_ratelimit
24 typed_config:
25 "@type": type.googleapis.com/udpa.type.v1.TypedStruct
26 type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
27 value:
28 stat_prefix: demo-api
29 enable_x_ratelimit_headers: DRAFT_VERSION_03
30
31 - applyTo: HTTP_ROUTE
32 match:
33 context: SIDECAR_INBOUND
34 routeConfiguration:
35 vhost:
36 name: "inbound|http|80"
37 route:
38 action: ANY
39 patch:
40 operation: MERGE
41 value:
42 route:
43 rate_limits:
44 # The actions reference: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-ratelimit
45 - actions:
46 - header_value_match:
47 descriptor_key: "TEN_REQ_PER_MINUTE"
48 descriptor_value: "x-minute-10"
49 headers:
50 - name: :method
51 prefix_match: GET
52 - name: x-minute-10
53 range_match:
54 start: 100
55 end: 200
56 - actions:
57 - query_parameter_value_match:
58 descriptor_key: "ONE_REQ_PER_SECOND"
59 descriptor_value: "OnePerSec"
60 query_parameters:
61 - name: is_office
62 present_match: true
63
64 - actions:
65 - request_headers:
66 header_name: ":path"
67 descriptor_key: "TEN_REQ_PER_SECOND"
68
69
70 typed_per_filter_config:
71 envoy.filters.http.local_ratelimit:
72 "@type": type.googleapis.com/udpa.type.v1.TypedStruct
73 type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
74 value:
75 stat_prefix: demo-api
76 enable_x_ratelimit_headers: DRAFT_VERSION_03
77 descriptors:
78 - entries:
79 - key: TEN_REQ_PER_SECOND
80 value: "/api/v2"
81 token_bucket:
82 max_tokens: 500
83 tokens_per_fill: 500
84 fill_interval: 60s
85 - entries:
86 - key: ONE_REQ_PER_SECOND
87 value: "OnePerSec"
88 token_bucket:
89 max_tokens: 60
90 tokens_per_fill: 60
91 fill_interval: 60s
92 - entries:
93 - key: TEN_REQ_PER_MINUTE
94 value: "x-minute-10"
95 token_bucket:
96 max_tokens: 10
97 tokens_per_fill: 10
98 fill_interval: 60s
99 filter_enabled:
100 runtime_key: local_rate_limit_enabled
101 default_value:
102 numerator: 100
103 denominator: HUNDRED
104 filter_enforced:
105 runtime_key: local_rate_limit_enforced
106 default_value:
107 numerator: 100
108 denominator: HUNDRED
109 token_bucket:
110 max_tokens: 1000
111 tokens_per_fill: 1000
112 fill_interval: 60s
Enable the statistics for rate limit of pod template
1template:
2 metadata:
3 annotations:
4 proxy.istio.io/config: |-
5 proxyStatsMatcher:
6 inclusionRegexps:
7 - ".*http_local_rate_limit.*"