This is the "latest" release of Envoy Gateway, which contains the most recent commits from the main branch.
This release might not be stable.
Please refer to the /docs documentation for the most current information.
Bandwidth Limit
5 minute read
Bandwidth limit allows users to control the throughput of traffic sent to and received from backends. Envoy throttles matching request or response bodies by pausing data transfer when the configured bandwidth is exhausted, resuming as tokens are replenished, so clients generally see slower transfers rather than bandwidth-limit rejections.
This feature is implemented using the Envoy bandwidth limit filter.
Users may want to limit bandwidth for several reasons:
- Prevent a single backend or route from consuming all available network capacity.
- Protect upstream services from being overwhelmed by large request or response bodies.
- Enforce fair usage across multiple routes or tenants sharing the same gateway.
Envoy Gateway uses the BackendTrafficPolicy CRD to express bandwidth limit settings. This instantiated resource can be linked to a Gateway, HTTPRoute, or GRPCRoute.
Note: The bandwidth limit is applied per Envoy proxy instance.
If the data plane runs multiple replicas, each replica enforces the limit independently.
When a BackendTrafficPolicy with bandwidthLimit targets a Gateway, Envoy Gateway applies the same limit to each matching route under that Gateway.
The limit is not shared across routes.
Prerequisites
Install Envoy Gateway
Follow the steps below to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP.
Expand for instructions
Install the Gateway API CRDs and Envoy Gateway using Helm:
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespaceInstall the GatewayClass, Gateway, HTTPRoute and example app:
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/latest/quickstart.yaml -n defaultVerify Connectivity:
Get the External IP of the Gateway:
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/getThe above command should succeed with status code 200.
Get the name of the Envoy service created the by the example Gateway:
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')Get the deployment of the Envoy service created the by the example Gateway:
export ENVOY_DEPLOYMENT=$(kubectl get deploy -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')Port forward to the Envoy service:
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 &Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://localhost:8888/getThe above command should succeed with status code 200.
Limit Request Bandwidth
The following example limits inbound request traffic for an HTTPRoute to 10 KiB/s.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: bandwidth-limit-policy
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: backend
bandwidthLimit:
request:
limit:
value: "10Ki"
unit: Second
EOF
Save and apply the following resources to your cluster:
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: bandwidth-limit-policy
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: backend
bandwidthLimit:
request:
limit:
value: "10Ki"
unit: Second
Verify that the policy was accepted:
kubectl get backendtrafficpolicy bandwidth-limit-policy -o yaml
Upload a large file to trigger request throttling:
dd if=/dev/zero of=/tmp/test.bin bs=1K count=50
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')
curl -X POST \
-H "Host: www.example.com" \
--data-binary @/tmp/test.bin \
http://${GATEWAY_HOST}/
Verify throttling occurred by checking Envoy’s Prometheus metrics:
egctl experimental stats envoy-proxy \
-n envoy-gateway-system \
-l gateway.envoyproxy.io/owning-gateway-name=eg,gateway.envoyproxy.io/owning-gateway-namespace=default \
| grep bandwidth_limit
Key metrics to check:
| Metric | Description |
|---|---|
envoy_http_bandwidth_limiter_http_bandwidth_limit_request_enabled | Total number of request streams for which the bandwidth limiter was consulted |
envoy_http_bandwidth_limiter_http_bandwidth_limit_request_enforced | Total number of request streams for which the bandwidth limiter was enforced |
envoy_http_bandwidth_limiter_http_bandwidth_limit_request_incoming_total_size | Total size in bytes of incoming request data to bandwidth limiter |
envoy_http_bandwidth_limiter_http_bandwidth_limit_request_allowed_total_size | Total size in bytes of outgoing request data from bandwidth limiter |
Limit Response Bandwidth
The following example limits outbound response traffic to 1 KiB/s and adds response trailers, so clients can observe the delay introduced by the filter.
Deploy httpbin as a backend. Its /bytes/{n} endpoint returns exactly n bytes, making it easy to generate large responses on demand:
kubectl create deployment httpbin --image=kennethreitz/httpbin --port=80
kubectl expose deployment httpbin --port=80
kubectl wait --for=condition=Available deployment/httpbin --timeout=60s
Apply the HTTPRoute and BackendTrafficPolicy:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: bandwidth-limit-response-route
spec:
parentRefs:
- name: eg
hostnames:
- "www.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /bytes
backendRefs:
- group: ""
kind: Service
name: httpbin
port: 80
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: bandwidth-limit-response-policy
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: bandwidth-limit-response-route
bandwidthLimit:
response:
limit:
value: "1Ki"
unit: Second
responseTrailers:
prefix: "x-eg"
EOF
Save and apply the following resources to your cluster:
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: bandwidth-limit-response-route
spec:
parentRefs:
- name: eg
hostnames:
- "www.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /bytes
backendRefs:
- group: ""
kind: Service
name: httpbin
port: 80
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: bandwidth-limit-response-policy
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: bandwidth-limit-response-route
bandwidthLimit:
response:
limit:
value: "1Ki"
unit: Second
responseTrailers:
prefix: "x-eg"
Download 10 KiB through the throttled route.
curl -v --http2-prior-knowledge -sS \
-o /dev/null \
-H "Host: www.example.com" \
http://${GATEWAY_HOST}/bytes/10240
Look for lines starting with < x-eg in the verbose output:
< x-eg-bandwidth-response-delay-ms: 9047
< x-eg-bandwidth-response-filter-delay-ms: 8850
With prefix: "x-eg", Envoy appends the following trailers to each throttled response:
| Trailer | Description |
|---|---|
x-eg-bandwidth-request-delay-ms | Total request-stream transfer delay in milliseconds, including body transfer time and filter-added delay. |
x-eg-bandwidth-response-delay-ms | Total response-stream transfer delay in milliseconds, including body transfer time and filter-added delay. |
x-eg-bandwidth-request-filter-delay-ms | Delay in milliseconds added to the request stream by the filter only. |
x-eg-bandwidth-response-filter-delay-ms | Delay in milliseconds added to the response stream by the filter only. |
Limit Both Directions
request and response can be combined in a single policy:
bandwidthLimit:
request:
limit:
value: "10Ki"
unit: Second
response:
limit:
value: "1Mi"
unit: Second
At least one of request or response must be specified.
Bandwidth Limit Values
The value field accepts Kubernetes resource quantity notation.
The unit field controls the time window: Second, Minute, or Hour.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.