Telemetry and Policy with Istio

When you start your adventure with microservices, at some point you need to think about policy in your application. Istio allows you to manage your applications without making any changes in your business logic. This service mesh provides: access control systems, telemetry capturing systems, quota enforcement systems and billing systems. Mixer, the Istio component, is responsible for all these things.

Mixer Topology

Proxy calls Mixer before and after each request to perform precondition checks and report telemetry. Mixer also has reliability and scalability benefits.

Adapters

Mixer manages very well different infrastructure backends because of a plug-in model. Plug-ins are known as adapters and they allows Mixer to interface to different infrastructure backends that deliver core functionality, such as logging, monitoring, quotas, ACL checking, and more.

Enable Rate Limiting

Let's try to use Mixer components in practice. For example, we have a simple application with one server and two versions of bot.

We want to set some rules like:

  • the default rule is 500 requests every 1s
  • 2 requests every 5s if the destination is a server
  • 5 requests every 5s if the destination is server and request headers contain one called "source" with value "10.28.11.20"
  • no limit if request headers contain one called "user" with value "jason"

But first we need to configure destination rules:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: server
spec:
  host: server
  subsets:
  - name: v1
    labels:
      version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: bot
spec:
  host: bot
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

So now we can apply our setting for rate limiting:

apiVersion: "config.istio.io/v1alpha2"
kind: memquota
metadata:
  name: handler
  namespace: istio-system
spec:
  quotas:
  - name: requestcount.quota.istio-system
    maxAmount: 500
    validDuration: 1s
    overrides:
    - dimensions:
        destination: server
        source: "10.28.11.20"
      maxAmount: 5
      validDuration: 5s
    - dimensions:
        destination: server
      maxAmount: 2
      validDuration: 5s
---
apiVersion: "config.istio.io/v1alpha2"
kind: quota
metadata:
  name: requestcount
  namespace: istio-system
spec:
  dimensions:
    source: request.headers["source"] | "unknown"
    destination: destination.labels["app"] | destination.service | "unknown"
    destinationVersion: destination.labels["version"] | "unknown"
---
apiVersion: config.istio.io/v1alpha2
kind: QuotaSpec
metadata:
  name: request-count
  namespace: istio-system
spec:
  rules:
  - quotas:
    - charge: 1
      quota: requestcount
---
apiVersion: config.istio.io/v1alpha2
kind: QuotaSpecBinding
metadata:
  name: request-count
  namespace: istio-system
spec:
  quotaSpecs:
  - name: request-count
    namespace: istio-system
  services:
  - name: server
    namespace: default
    #  - service: '*'  # Uncomment this to bind *all* services to request-count
---
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: quota
  namespace: istio-system
spec:
  match: match(request.headers["user"], "jason") == false
  actions:
  - handler: handler.memquota
    instances:
    - requestcount.quota

Rate limit configuration is split into 2 parts.

  • Client Side
    - QuotaSpec defines quota name and amount that the client should request
    - QuotaSpecBinding connect QuotaSpec with one or more services
  • Mixer Side
    - quota instance defines how quota is dimensioned by Mixer
    - memquota adapter defines memquota adapter configuration
    - quota rule defines when quota instance is dispatched to the memquota adapter

This short demo shows how the route should look like after adding rate limiting:

  • At the beginning we can send requests without any limits
  • After this we use kubectl to add server-ratelimit.yaml
  • Changes must be loaded into our application so we must wait a little bit
  • Around 0:25s on demo video we can see our limits are ready

Telemetry

Istio includes many adapters and add-ons which let a developer clearly understand how an application works. Those are few of them:

Jaeger for tracing

Prometheus for collecting metrics and logs

Grafana for visualizing metrics

Fluentd for logging

Service Graph

=

Every adapter we can launch on localhost and deeply check our metrics. For more information follow this tutorial created by Aleksander Ziuzia and me or visit Istio website

Conclusion

Mixer is a powerful component of Istio. Configuration is simple and allows you to manage your rate limits. Additionally collects logs and metrics to distribute it to plug-ins. Adapters previously installed with Istio make your application looks clearly to viewing and finding bugs, traffic etc. I recommend everyone try it in your microservices.

Based on: https://istio.io/docs/concepts/what-is-istio/