Configuring Rate Limiting
In this guide, we’ll walk you through deploying an HTTPLocalRateLimitPolicy
resource to rate-limit the traffic to a given service.
For more information about Linkerd’s rate limiting check the Rate Limiting feature doc and the HTTPLocalRateLimitPolicy reference doc.
To see how clients can be configured to load balance around Services which are rate-limited, see Rate Limit Aware Load Balancing.
Prerequisites
To use this guide you’ll only need a Kubernetes cluster running a Linkerd instance. You can follow the installing Linkerd Guide.
Setup
First inject and install the Emojivoto application, then scale-down the vote-bot workload to avoid it interfering with our testing:
linkerd inject https://run.linkerd.io/emojivoto.yml | kubectl apply -f -
kubectl -n emojivoto scale --replicas 0 deploy/vote-bot
Finally, deploy a workload with an Ubuntu image, open a shell into it and install curl:
kubectl create deployment client --image ubuntu -- bash -c "sleep infinity"
kubectl exec -it client-xxx -- bash
root@client-xxx:/# apt-get update && apt-get install -y curl
Leave that shell open so we can use it below when sending requests.
Creating an HTTPLocalRateLimitPolicy resource
We need first to create a Server resource pointing to the web-svc service.
Note that this Server has accessPolicy: all-unauthenticated, which means
that traffic is allowed by default and we don’t require to declare authorization
policies associated to it:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
namespace: emojivoto
name: web-http
spec:
accessPolicy: all-unauthenticated
podSelector:
matchLabels:
app: web-svc
port: http
proxyProtocol: HTTP/1
EOF
Now we can apply the HTTPLocalRateLimitPolicy resource pointing to that
Server. For now, we’ll just set a limit of 4 RPS per identity:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1alpha1
kind: HTTPLocalRateLimitPolicy
metadata:
namespace: emojivoto
name: web-http
spec:
targetRef:
group: policy.linkerd.io
kind: Server
name: web-http
identity:
requestsPerSecond: 4
EOF
Sending requests
In the Ubuntu shell, issue 10 concurrent requests to web-svc.emojivoto:
root@client-xxx:/# results=$(for i in {1..10}; do curl -s -o /dev/null -w "%{http_code}\n" "http://web-svc.emojivoto" & done; wait)
root@client-xxx:/# echo $results
200 200 200 429 429 429 429 200 429 429
We see that only 4 requests were allowed. The requests that got rate-limited receive a response with a 429 HTTP status code.
Overrides
The former client had no identity as it was deployed in the default namespace, where workloads are not injected by default.
Now let’s create a new Ubuntu workload in the emojivoto namespace, which will be
injected by default, and whose identity will be associated to the default
ServiceAccount in the emojivoto namespace:
kubectl -n emojivoto create deployment client --image ubuntu -- bash -c "sleep infinity"
kubectl -n emojivoto exec -it client-xxx -c ubuntu -- bash
root@client-xxx:/# apt-get update && apt-get install -y curl
Before issuing requests, let’s expand the HTTPLocalRateLimitPolicy resource,
adding an override for this specific client, that’ll allow it to issue requests
up to 6 RPS:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1alpha1
kind: HTTPLocalRateLimitPolicy
metadata:
namespace: emojivoto
name: web-http
spec:
targetRef:
group: policy.linkerd.io
kind: Server
name: web-http
identity:
requestsPerSecond: 4
overrides:
- requestsPerSecond: 6
clientRefs:
- kind: ServiceAccount
namespace: emojivoto
name: default
EOF
And finally back in the shell we execute the requests:
root@client-xxx:/# results=$(for i in {1..10}; do curl -s -o /dev/null -w "%{http_code}\n" "http://web-svc.emojivoto" & done; wait)
root@client-xxx:/# echo $results
429 429 429 429 200 200 200 200 200 200
We see that now 6 requests were allowed. If we tried again with the former client, we could verify we would still be allowed to 4 requests only.


