Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Deprecation Schedule](#deprecation-schedule)
- [Building and Testing](#building-and-testing)
- [Docker-compose setup](#docker-compose-setup)
- [Full test environment](#full-test-environment)
- [Configuration](#configuration)
- [The configuration format](#the-configuration-format)
- [Definitions](#definitions)
Expand Down Expand Up @@ -110,6 +111,23 @@ If you want to run with [two redis instances](#two-redis-instances), you will ne
the docker-compose.yaml file to run a second redis container, and change the environment variables
as explained in the [two redis instances](#two-redis-instances) section.

## Full test environment
To run a fully configured environment to demo Envoy based rate limiting, run:
```bash
docker-compose -f docker-compose-example.yaml up
```
This will run ratelimit, redis, prom-statsd-exporter and two Envoy containers such that you can demo rate limiting by hitting the below endpoints.
```bash
curl localhost:8888/test
curl localhost:8888/header -H "foo: foo" # Header based
curl localhost:8888/twoheader -H "foo: foo" -H "bar: bar" # Two headers
curl localhost:8888/twoheader -H "foo: foo" -H "baz: baz"
curl localhost:8888/twoheader -H "foo: foo" -H "bar: banned" # Ban a particular header value
```
Edit `examples/ratelimit/config/example.yaml` to test different rate limit configs. Hot reloading is enabled.

The descriptors in `example.yaml` and the actions in `examples/envoy/proxy.yaml` should give you a good idea on how to configure rate limits.

# Configuration

## The configuration format
Expand Down Expand Up @@ -325,7 +343,7 @@ There are two methods for triggering a configuration reload:
1. Symlink RUNTIME_ROOT to a different directory.
2. Update the contents inside `RUNTIME_ROOT/RUNTIME_SUBDIRECTORY/config/` directly.

The former is the default behavior. To use the latter method, set the `RUNTIME_WATCH_ROOT` environment variable to `false`.
The former is the default behavior. To use the latter method, set the `RUNTIME_WATCH_ROOT` environment variable to `false`.

For more information on how runtime works you can read its [README](https://github.com/lyft/goruntime).

Expand Down Expand Up @@ -377,7 +395,7 @@ The ratelimit service listens to HTTP 1.1 (by default on port 8080) with two end

## /json endpoint

Takes an HTTP POST with a JSON body of the form e.g.
Takes an HTTP POST with a JSON body of the form e.g.
```json
{
"domain": "dummy",
Expand All @@ -389,7 +407,7 @@ Takes an HTTP POST with a JSON body of the form e.g.
]
}
```
The service will return an http 200 if this request is allowed (if no ratelimits exceeded) or 429 if one or more
The service will return an http 200 if this request is allowed (if no ratelimits exceeded) or 429 if one or more
ratelimits were exceeded.

The response is a RateLimitResponse encoded with
Expand Down Expand Up @@ -432,7 +450,7 @@ You can specify the debug port with the `DEBUG_PORT` environment variable. It de

# Local Cache

Ratelimit optionally uses [freecache](https://github.com/coocood/freecache) as its local caching layer, which stores the over-the-limit cache keys, and thus avoids reading the
Ratelimit optionally uses [freecache](https://github.com/coocood/freecache) as its local caching layer, which stores the over-the-limit cache keys, and thus avoids reading the
redis cache again for the already over-the-limit keys. The local cache size can be configured via `LocalCacheSizeInBytes` in the [settings](https://github.com/envoyproxy/ratelimit/blob/master/src/settings/settings.go).
If `LocalCacheSizeInBytes` is 0, local cache is disabled.

Expand Down
87 changes: 87 additions & 0 deletions docker-compose-example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
version: "3"
services:
redis:
image: redis:alpine
expose:
- 6379
ports:
- 6379:6379
networks:
- ratelimit-network

statsd:
image: prom/statsd-exporter:v0.18.0
expose:
- 9125
ports:
- 9125:9125
networks:
- ratelimit-network

ratelimit:
image: envoyproxy/ratelimit:master
command: /bin/ratelimit
ports:
- 8080:8080
- 8081:8081
- 6070:6070
depends_on:
- redis
- statsd
networks:
- ratelimit-network
volumes:
- ./examples/ratelimit/config:/data/ratelimit/config
environment:
- USE_STATSD=true
- STATSD_HOST=statsd
- STATSD_PORT=9125
- LOG_LEVEL=debug
- REDIS_SOCKET_TYPE=tcp
- REDIS_URL=redis:6379
- RUNTIME_ROOT=/data
- RUNTIME_SUBDIRECTORY=ratelimit
- RUNTIME_WATCH_ROOT=false

envoy-proxy:
image: envoyproxy/envoy-dev:latest
entrypoint: "/usr/local/bin/envoy"
command:
- "--service-node proxy"
- "--service-cluster proxy"
- "--config-path /etc/envoy/envoy.yaml"
- "--concurrency 1"
- "--mode serve"
- "--log-level info"
volumes:
- ./examples/envoy/proxy.yaml:/etc/envoy/envoy.yaml
networks:
- ratelimit-network
expose:
- "8888"
- "8001"
ports:
- "8888:8888"
- "8001:8001"

envoy-mock:
image: envoyproxy/envoy-dev:latest
entrypoint: "/usr/local/bin/envoy"
command:
- "--service-node mock"
- "--service-cluster mock"
- "--config-path /etc/envoy/envoy.yaml"
- "--concurrency 1"
- "--mode serve"
- "--log-level info"
volumes:
- ./examples/envoy/mock.yaml:/etc/envoy/envoy.yaml
networks:
- ratelimit-network
expose:
- "9999"
ports:
- "9999:9999"

networks:
ratelimit-network:
3 changes: 2 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ services:

ratelimit:
image: alpine:3.6
command: /usr/local/bin/ratelimit
command: >
sh -c "until test -f /usr/local/bin/ratelimit; do sleep 5; done; /usr/local/bin/ratelimit"
ports:
- 8080:8080
- 8081:8081
Expand Down
34 changes: 34 additions & 0 deletions examples/envoy/mock.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 9999
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress
route_config:
name: ingress
virtual_hosts:
- name: backend
domains:
- "*"
routes:
- match:
prefix: "/"
direct_response:
status: "200"
body:
inline_string: "Hello World"
http_filters:
- name: envoy.router
config: {}
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 8001
104 changes: 104 additions & 0 deletions examples/envoy/proxy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 8001
static_resources:
clusters:
- name: ratelimit
type: STRICT_DNS
connect_timeout: 1s
lb_policy: ROUND_ROBIN
protocol_selection: USE_CONFIGURED_PROTOCOL
http2_protocol_options: {}
load_assignment:
cluster_name: ratelimit
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: ratelimit
port_value: 8081
- name: mock
connect_timeout: 1s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: mock
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: envoy-mock
port_value: 9999
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 8888
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress
http_filters:
- name: envoy.rate_limit
config:
domain: rl
request_type: external
stage: 0
rate_limited_as_resource_exhausted: true
failure_mode_deny: false
rate_limit_service:
grpc_service:
envoy_grpc:
cluster_name: ratelimit
- name: envoy.router
config: {}
route_config:
name: route
virtual_hosts:
- name: backend
domains:
- "*"
routes:
- match:
prefix: /test
route:
cluster: mock
rate_limits:
- actions:
- source_cluster: {}
- destination_cluster: {}
- match:
prefix: /header
route:
cluster: mock
rate_limits:
- actions:
- request_headers:
header_name: "foo"
descriptor_key: "foo"
- match:
prefix: /twoheader
route:
cluster: mock
rate_limits:
- actions:
- request_headers:
header_name: "foo"
descriptor_key: "foo"
- request_headers:
header_name: "bar"
descriptor_key: "bar"
- actions:
- request_headers:
header_name: "foo"
descriptor_key: "foo"
- request_headers:
header_name: "baz"
descriptor_key: "baz"
29 changes: 29 additions & 0 deletions examples/ratelimit/config/example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
domain: rl
descriptors:
- key: source_cluster
value: proxy
descriptors:
- key: destination_cluster
value: mock
rate_limit:
unit: minute
requests_per_unit: 1
- key: foo
rate_limit:
unit: minute
requests_per_unit: 2
descriptors:
- key: bar
rate_limit:
unit: minute
requests_per_unit: 3
- key: bar
value: banned
rate_limit:
unit: minute
requests_per_unit: 0
- key: baz
rate_limit:
unit: second
requests_per_unit: 1