Istio Rate Limiting: Using Workload Selectors
In the last two blogs, we discussed how to implement rate limiting with Istio and explored what happens when there are multiple pods acting as either the server or client.
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