• GitHub
  • Slack
  • Linkerd Forum

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.

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.