In this short blog, we will explore how to apply rate limiting to a selected microservice in our cluster.

The architecture

I have three microservices: A, B, and C.

There are two paths: /scenarioC, which starts at A, moves to B, and then proxies the request to C, and /scenarioD, where A directly requests C.

The problem

Let’s say we want to rate limit requests coming from B to C. To achieve this, we add a destination rule like so:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: app-c-destination-rule
spec:
host: app-c
trafficPolicy:
connectionPool:
tcp:
maxConnections: 10
http:
http1MaxPendingRequests: 5

This destination rule will apply the rate limit to all of my microservices. Istio will add this destination rule as an Envoy configuration to all the Istio-proxy sidecars.

"cluster": {
"circuit_breakers": {
"thresholds": [
{
"max_connections": 10,
"max_pending_requests": 5,
"max_requests": 4294967295,
"max_retries": 4294967295,
"track_remaining": true
}
]
},
"service_name": "outbound|8080||app-c.apps.svc.cluster.local"
}

I removed all the unnecessary values from the json and kept only the ones we configured in the destination rule.

The solution

It’s quite straightforward; we can select the specific workload to which the destination rule will be applied, like so:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: app-c-destination-rule
spec:
host: app-c
workloadSelector:
matchLabels:
app: app-b
trafficPolicy:
connectionPool:
tcp:
maxConnections: 10
http:
http1MaxPendingRequests: 5

We can select the workload based on a label, which means we can apply the rule to more than one workload.
This time, the Istio configuration on app-a looks like this:

"thresholds": [
{
"max_connections": 4294967295,
"max_pending_requests": 4294967295,
}
]

And for app-b:

"thresholds": [
{
"max_connections": 10,
"max_pending_requests": 5,
}
]

Which is exactly what we wanted.

Conclusion

By adding workloadSelector to the destination rule, we can instruct Istio to apply the rule to specific workloads as configured in the destination rule.

To test this, we can see that when I curl to /scenarioC, we get a 503 HTTP status code.

------Summary-------
Requests that returned 503: 5
Requests that returned 200: 15

However, in /scenarioD we get only HTTP status 200

------Summary-------
Requests that returned 200: 20

--

--

No responses yet