-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Kaushal Vora
committed
Feb 7, 2025
1 parent
a4a105f
commit 8843a13
Showing
18 changed files
with
1,696 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
apiVersion: v2 | ||
name: istio-rate-limiter | ||
description: A Helm chart for implementing rate limiting using istio | ||
|
||
# A chart can be either an 'application' or a 'library' chart. | ||
# | ||
# Application charts are a collection of templates that can be packaged into versioned archives | ||
# to be deployed. | ||
# | ||
# Library charts provide useful utilities or functions for the chart developer. They're included as | ||
# a dependency of application charts to inject those utilities and functions into the rendering | ||
# pipeline. Library charts do not define any templates and therefore cannot be deployed. | ||
type: application | ||
|
||
# This is the chart version. This version number should be incremented each time you make changes | ||
# to the chart and its templates, including the app version. | ||
# Versions are expected to follow Semantic Versioning (https://semver.org/) | ||
version: 1.0.0 | ||
|
||
# This is the version number of the application being deployed. This version number should be | ||
# incremented each time you make changes to the application. Versions are not expected to | ||
# follow Semantic Versioning. They should reflect the version the application is using. | ||
# It is recommended to use it with quotes. | ||
appVersion: "1.16.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
# Istio Global Rate Limiting Helm Chart | ||
|
||
This Helm chart provides a mechanism to configure and deploy global rate limiting in Istio for services using sidecar and ambient mode. It dynamically creates the necessary ConfigMaps and EnvoyFilters for each service based on the provided configuration. Additionally, the chart deploys a [Rate Limit Service](https://github.com/envoyproxy/ratelimit?tab=readme-ov-file#overview) with Redis as a caching layer. | ||
|
||
## Features | ||
|
||
- Supports both Sidecar and Ambient mode | ||
- Namespace-level configuration. | ||
- Service-specific rate limiting. | ||
- Support for multiple [descriptors](https://github.com/envoyproxy/ratelimit?tab=readme-ov-file#descriptor-list-definition) and [actions](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-ratelimit-action) per service. | ||
- Automated creation of ConfigMaps and EnvoyFilters. | ||
- Deployment of a Rate Limit Service with Redis for caching. | ||
|
||
## Prerequisites | ||
|
||
1. Kubernetes cluster with Istio installed. | ||
2. Waypoint proxies enabled in Istio if Istio mode is ambient. | ||
3. Helm installed. | ||
|
||
## Installation | ||
|
||
1. Clone this repository which contains the Helm chart. | ||
2. Navigate to the Helm cloned repository: | ||
```bash | ||
cd istio-rate-limiter | ||
``` | ||
3. Install the Helm chart with a custom `values.yaml` file: | ||
```bash | ||
helm install istio-rate-limiter . -f values.yaml | ||
``` | ||
|
||
## Configuration | ||
|
||
The chart accepts configuration for mode, namespaces, waypoint proxy selectors (if Istio mode is ambient), services, workload selector (if Istio mode in sidecar), descriptors, and actions. Below is an example of the `values.yaml` structure for both sidecar and ambient mode: | ||
|
||
**Sidecar Mode**: | ||
```yaml | ||
mode: sidecar | ||
namespaces: | ||
- name: "components" | ||
services: | ||
- name: "service-a" | ||
domain: "service-a-limiter" | ||
workloadSelector: | ||
app: service-a | ||
descriptors: | ||
- key: "user_id" | ||
value: "user123" | ||
rateLimit: | ||
unit: "second" | ||
requestsPerUnit: 10 | ||
- key: "path" | ||
value: "/api/data" | ||
rateLimit: | ||
unit: "minute" | ||
requestsPerUnit: 100 | ||
actions: | ||
- header_name: "user_id" | ||
descriptor_key: "user_id" | ||
- request_headers: | ||
header_name: ":path" | ||
descriptor_key: "path" | ||
- name: "canvas" | ||
services: | ||
- name: "service-b" | ||
domain: "service-b-limiter" | ||
workloadSelector: | ||
app: service-b | ||
descriptors: | ||
- key: "client_id" | ||
value: "client_abc" | ||
rateLimit: | ||
unit: "minute" | ||
requestsPerUnit: 50 | ||
actions: | ||
- header_name: "client_id" | ||
descriptor_key: "client_id" | ||
``` | ||
**Ambient Mode**: | ||
```yaml | ||
mode: ambient | ||
namespaces: | ||
- name: "components" | ||
waypointProxySelector: | ||
labels: | ||
istio.io/gateway-name: "waypoint-proxy" | ||
services: | ||
- name: "service-a" | ||
domain: "service-a-limiter" | ||
port: 8080 | ||
descriptors: | ||
- key: "user_id" | ||
value: "user123" | ||
rateLimit: | ||
unit: "second" | ||
requestsPerUnit: 10 | ||
- key: "path" | ||
value: "/api/data" | ||
rateLimit: | ||
unit: "minute" | ||
requestsPerUnit: 100 | ||
actions: | ||
- header_name: "user_id" | ||
descriptor_key: "user_id" | ||
- request_headers: | ||
header_name: ":path" | ||
descriptor_key: "path" | ||
- name: "canvas" | ||
waypointProxySelector: | ||
labels: | ||
istio.io/gateway-name: "waypoint-proxy" | ||
services: | ||
- name: "service-b" | ||
domain: "service-b-limiter" | ||
port: 8081 | ||
descriptors: | ||
- key: "client_id" | ||
value: "client_abc" | ||
rateLimit: | ||
unit: "minute" | ||
requestsPerUnit: 50 | ||
actions: | ||
- header_name: "client_id" | ||
descriptor_key: "client_id" | ||
``` | ||
### Parameters | ||
#### Mode configuration | ||
- `mode`: (Required)Istio mode, either sidecar or ambeint default is sidecar | ||
|
||
#### Namespace Configuration | ||
- `name`: (Required)Name of the namespace. | ||
- `waypointProxySelector`: (Optional in both sidecar and ambient mode)Labels to identify the waypoint proxy for the namespace, if not provided it will use default label `name: <namespace>-waypoint`. | ||
|
||
#### Service Configuration | ||
- `name`: (Required)Name of the service. | ||
- `domain`: (Optional in both sidecar and ambient)Domain for the rate limiter, if not provided the defaul domian `<service-name>-limiter` would be added in config. | ||
- `port`: (Optional in sidecar mode, required in ambeint mode)Port for the service. | ||
- `workloadSelector1`: (Required in sidecar mode, optional in ambient mode)Pod labels to identify the Istio sidecar proxy workload | ||
- `descriptors`: (Required)List of rate limiting descriptors. | ||
- `key`: The key for the descriptor. | ||
- `value`: The value for the descriptor. | ||
- `rateLimit`: Rate limiting details. | ||
- `unit`: Time unit (`second`, `minute`, etc.). | ||
- `requestsPerUnit`: Allowed requests per unit. | ||
- `actions`: (Required)List of actions corresponding to descriptors. | ||
- `header_name`: HTTP header name to map to the descriptor key. | ||
- `request_headers`: Map a specific header to a descriptor key. | ||
|
||
### Rate Limit Service Configuration | ||
The chart deploys a Rate Limit Service that works alongside Redis for caching rate limiting data. The following parameters can be customized: | ||
|
||
- `rateLimitService.image`: Docker image for the Rate Limit Service. | ||
- `redis.image`: Docker image for Redis. | ||
|
||
Below is an example of how to configure the Rate Limit Service in `values.yaml`: | ||
|
||
```yaml | ||
rateLimitService: | ||
image: "envoyproxy/ratelimit:latest" | ||
redis: | ||
image: "redis:alpine" | ||
``` | ||
|
||
### Example Values | ||
|
||
Below is an example of a complete `values.yaml` configuration for both sidecar and ambient mode: | ||
|
||
**Sidecar Mode**: | ||
```yaml | ||
mode: sidecar | ||
namespaces: | ||
- name: "example-namespace" | ||
services: | ||
- name: "example-service" | ||
domain: "example-service-limiter" | ||
workloadSelector: | ||
app: example-service | ||
descriptors: | ||
- key: "example_key" | ||
value: "example_value" | ||
rateLimit: | ||
unit: "minute" | ||
requestsPerUnit: 50 | ||
actions: | ||
- header_name: "example_header" | ||
descriptor_key: "example_key" | ||
rateLimitService: | ||
image: "envoyproxy/ratelimit:latest" | ||
redis: | ||
image: "redis:alpine" | ||
``` | ||
|
||
**Ambient Mode**: | ||
```yaml | ||
mode: ambient | ||
namespaces: | ||
- name: "example-namespace" | ||
waypointProxySelector: | ||
labels: | ||
istio.io/gateway-name: "example-waypoint-proxy" | ||
services: | ||
- name: "example-service" | ||
domain: "example-service-limiter" | ||
port: 8080 | ||
descriptors: | ||
- key: "example_key" | ||
value: "example_value" | ||
rateLimit: | ||
unit: "minute" | ||
requestsPerUnit: 50 | ||
actions: | ||
- header_name: "example_header" | ||
descriptor_key: "example_key" | ||
rateLimitService: | ||
image: "envoyproxy/ratelimit:latest" | ||
redis: | ||
image: "redis:alpine" | ||
``` | ||
|
||
## Resources Created | ||
|
||
For each service: | ||
1. **ConfigMap**: Contains the rate limiting configuration. | ||
2. **EnvoyFilter**: Applies the rate limiting rules to the Sidecar or Waypoint Proxy. | ||
|
||
Additionally: | ||
- **Rate Limit Service**: The service that enforces rate limits using Redis as a backend. | ||
- **Redis Deployment**: A Redis instance for caching rate limiting data (if not using an external Redis). | ||
|
||
## Uninstallation | ||
|
||
To uninstall the Helm chart: | ||
```bash | ||
helm uninstall istio-rate-limiter | ||
``` |
42 changes: 42 additions & 0 deletions
42
charts/istio-rate-limiter/v1.0.0/templates/cluster-envoyfilter.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{{- if eq .Values.mode "ambient" }} | ||
{{- range .Values.namespaces }} | ||
apiVersion: networking.istio.io/v1alpha3 | ||
kind: EnvoyFilter | ||
metadata: | ||
name: ratelimit-cluster | ||
namespace: {{ .name }} | ||
spec: | ||
workloadSelector: | ||
{{- if and (hasKey . "waypointProxySelector") (.waypointProxySelector) }} | ||
{{- toYaml .waypointProxySelector |nindent 4}} | ||
{{- else }} | ||
labels: | ||
name: {{ .name }}-waypoint | ||
{{- end }} | ||
configPatches: | ||
- applyTo: CLUSTER | ||
match: | ||
cluster: | ||
service: ratelimit-service.{{ $.Release.Namespace }}.svc.cluster.local | ||
context: SIDECAR_INBOUND | ||
proxy: {} | ||
patch: | ||
operation: ADD | ||
value: | ||
connect_timeout: 10s | ||
http2_protocol_options: {} | ||
lb_policy: ROUND_ROBIN | ||
load_assignment: | ||
cluster_name: ratelimit-service | ||
endpoints: | ||
- lb_endpoints: | ||
- endpoint: | ||
address: | ||
socket_address: | ||
address: ratelimit-service.{{ $.Release.Namespace }}.svc.cluster.local | ||
port_value: 8081 | ||
name: ratelimit-service | ||
type: STRICT_DNS | ||
--- | ||
{{- end }} | ||
{{- end }} |
32 changes: 32 additions & 0 deletions
32
charts/istio-rate-limiter/v1.0.0/templates/ratelimit-configmap.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{{- if .Values.namespaces }} | ||
{{- range .Values.namespaces }} | ||
{{- $namespace := .name }} | ||
{{- range .services }} | ||
{{- if or (not (hasKey . "name")) (not .name) }} | ||
{{- fail "Each service should have named defined" }} | ||
{{- end }} | ||
{{- if or (not (hasKey . "descriptors")) (not .descriptors) }} | ||
{{- fail (printf "Service %s does not have any descriptors defined, atleast one descriptor is required for each service" .name) }} | ||
{{- end }} | ||
{{- if or (not (hasKey . "actions")) (not .actions) }} | ||
{{- fail (printf "Service %s does not have any actions defined, atleast one action is required for each service" .name) }} | ||
{{- end }} | ||
{{- $name := (printf "ratelimit-%s-%s" $namespace .name) | trunc 63 | trimSuffix "-" }} | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: {{ $name }} | ||
namespace: {{ $.Release.Namespace }} | ||
data: | ||
{{ $name }}.yaml: | | ||
{{- if and (hasKey . "domain") (.domain) }} | ||
domain: "{{ .domain }}" | ||
{{- else }} | ||
domain: "{{ .name }}-limiter" | ||
{{- end }} | ||
descriptors: | ||
{{- toYaml .descriptors | nindent 6 }} | ||
--- | ||
{{- end }} | ||
{{- end }} | ||
{{- end }} |
Oops, something went wrong.