Tarun Pothulapati
Writes about Infra, Networking and Remote Life.


SMI Metrics with Istio

Posted on

As a part of my GSoC 2019 internship with Linkerd, I was tasked to add support for Istio on SMI-Metrics and also to add basic things to the repository like release automation, etc.

SMI-Metrics aims to have a common API to consume metrics from Service Meshes. Tools like flagger can be built on top of SMI, without having to use mesh specific API's. This creates a standardisation for Service Mesh metrics.

The SMI-Metrics is an extension API Server that users can install on their k8s cluster which then talks to the service mesh specific API's and returns metrics in a standard format as per the SMI spec.

As of v0.2.0, the repository supports both Linkerd and Istio.

Istio Support

Istio has a pluggable way of metrics i.e metrics can be added dynamically by submitting custom resources i.e Handler, Instances and Rules and Istio sends those metrics to prometheus in real time. More on this here

Istio support of SMI works by installing some handler and isntances that make Istio send metrics that involve the labels i.e kind, etc needed by SMI and then reading those metrics from prometheus whenever query requests come in.

Demo

First, make sure the kubernetes cluster has a working installation of Istio, by following this doc

Once this is done, let's run a demo app which has the Istio side-cars installed whose metrics we will query.

First, Let's create the emojivoto namespace.

kubectl apply -f https://gist.githubusercontent.com/Pothulapati/c8789307ec24fd73bb5ba5b892154ffd/raw/3386da4bec1472c11b1e0222c8143ca0d8c2a60b/namespace.yaml

Let's add the injection label, that makes Istio to inject sidecars automatically.

kubectl label namespace emojivoto istio-injection=enabled

Now, Let's deploy the Emojivoto services on to the same namespace.

kubectl apply -f https://gist.githubusercontent.com/Pothulapati/abed2e3f638fa0c16947b76191f89353/raw/8a891cf5d228a386bfc59cb7a1ce4c5af2f11db5/emojivoto.yaml

Now, If we check the pods in the emojivoto namespacc.

tarun@tarun-Inspiron-5559 ~/w/smi-metrics> kubectl get pods -n emojivoto
NAME                        READY   STATUS    RESTARTS   AGE
emoji-58c9579849-rp7nc      2/2     Running   0          28h
vote-bot-774764fd7f-blhzx   2/2     Running   0          28h
voting-66d5cdc46d-4fzqh     2/2     Running   0          28h
web-7f8455487f-rw9h5        2/2     Running   0          28h

We can see that all pods have two containers running i.e one application container and the Istio proxy (i.e envoy).

Regarding the emojivoto sample, vote-bot service keeps sending requests to web, which further talks to emoji and voting.

Now, Let's install SMI-Metrics Extension API Server and see the metrics of these application services.

The Smi-metrics v0.2.0 helm package can be downloaded from the link

Once it is unpacked. The package can be installed by running.

tarun@tarun-Inspiron-5559 ~/w/smi-metrics> helm install . --set adapter=istio --name dev
NAME:   dev
LAST DEPLOYED: Sat Aug 24 18:50:53 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME             DATA  AGE
dev-smi-metrics  1     4s

==> v1/Deployment
NAME             READY  UP-TO-DATE  AVAILABLE  AGE
dev-smi-metrics  1/1    1           1          4s

==> v1/Pod(related)
NAME                              READY  STATUS   RESTARTS  AGE
dev-smi-metrics-74df88c5fc-stxbk  1/1    Running  0         4s

==> v1/RoleBinding
NAME             AGE
dev-smi-metrics  4s

==> v1/Secret
NAME             TYPE               DATA  AGE
dev-smi-metrics  kubernetes.io/tls  2     4s

==> v1/Service
NAME             TYPE       CLUSTER-IP   EXTERNAL-IP  PORT(S)  AGE
dev-smi-metrics  ClusterIP  10.0.19.175  <none>       443/TCP  4s

==> v1/ServiceAccount
NAME             SECRETS  AGE
dev-smi-metrics  1        4s

==> v1alpha2/handler
NAME            AGE
smi-prometheus  4s

==> v1alpha2/instance
NAME                AGE
smirequestcount     4s
smirequestduration  4s

==> v1alpha2/rule
NAME     AGE
smiprom  3s

==> v1beta1/APIService
NAME                          AGE
v1alpha1.metrics.smi-spec.io  4s

As we can see, all the parts of the SMI installation have been installed successfully. Now, queries on the emojivoto resources can be done by running.

tarun@tarun-Inspiron-5559 ~/w/smi-metrics> kubectl get --raw /apis/metrics.smi-spec.io/v1alpha1/namespaces/emojivoto/deployments/web | jq
{
  "kind": "TrafficMetrics",
  "apiVersion": "metrics.smi-spec.io/v1alpha1",
  "metadata": {
    "name": "web",
    "namespace": "emojivoto",
    "selfLink": "/apis/metrics.smi-spec.io/v1alpha1/namespaces/emojivoto/deployments/web",
    "creationTimestamp": "2019-08-24T13:22:52Z"
  },
  "timestamp": "2019-08-24T13:22:52Z",
  "window": "30s",
  "resource": {
    "kind": "Deployment",
    "namespace": "emojivoto",
    "name": "web"
  },
  "edge": {
    "direction": "from",
    "resource": null
  },
  "metrics": [
    {
      "name": "p99_response_latency",
      "unit": "ms",
      "value": "9m"
    },
    {
      "name": "p90_response_latency",
      "unit": "ms",
      "value": "7m"
    },
    {
      "name": "p50_response_latency",
      "unit": "ms",
      "value": "3m"
    },
    {
      "name": "success_count",
      "value": "108"
    },
    {
      "name": "failure_count",
      "value": "4"
    }
  ]
}

These are the golden metrics of inbound requests that web deployment is recieving.

tarun@tarun-Inspiron-5559 ~/w/smi-metrics> kubectl get --raw /apis/metrics.smi-spec.io/v1alpha1/namespaces/emojivoto/deployments/web/edges | jq
{
  "kind": "TrafficMetricsList",
  "apiVersion": "metrics.smi-spec.io/v1alpha1",
  "metadata": {
    "selfLink": "/apis/metrics.smi-spec.io/v1alpha1/namespaces/emojivoto/deployments/web/edges"
  },
  "resource": {
    "kind": "Deployment",
    "namespace": "emojivoto",
    "name": "web"
  },
  "items": [
    {
      "kind": "TrafficMetrics",
      "apiVersion": "metrics.smi-spec.io/v1alpha1",
      "metadata": {
        "name": "web",
        "namespace": "emojivoto",
        "selfLink": "/apis/metrics.smi-spec.io/v1alpha1/namespaces/emojivoto/deployments/web/edges",
        "creationTimestamp": "2019-08-24T13:22:26Z"
      },
      "timestamp": "2019-08-24T13:22:26Z",
      "window": "30s",
      "resource": {
        "kind": "Deployment",
        "namespace": "emojivoto",
        "name": "web"
      },
      "edge": {
        "direction": "from",
        "resource": {
          "kind": "Deployment",
          "namespace": "emojivoto",
          "name": "vote-bot"
        }
      },
      "metrics": [
        {
          "name": "p99_response_latency",
          "unit": "ms",
          "value": "22m"
        },
        {
          "name": "p90_response_latency",
          "unit": "ms",
          "value": "9m"
        },
        {
          "name": "p50_response_latency",
          "unit": "ms",
          "value": "5m"
        },
        {
          "name": "success_count",
          "value": "116"
        },
        {
          "name": "failure_count",
          "value": "4"
        }
      ]
    },
    {
      "kind": "TrafficMetrics",
      "apiVersion": "metrics.smi-spec.io/v1alpha1",
      "metadata": {
        "name": "web",
        "namespace": "emojivoto",
        "selfLink": "/apis/metrics.smi-spec.io/v1alpha1/namespaces/emojivoto/deployments/web/edges",
        "creationTimestamp": "2019-08-24T13:22:26Z"
      },
      "timestamp": "2019-08-24T13:22:26Z",
      "window": "30s",
      "resource": {
        "kind": "Deployment",
        "namespace": "emojivoto",
        "name": "web"
      },
      "edge": {
        "direction": "to",
        "resource": {
          "kind": "Deployment",
          "namespace": "emojivoto",
          "name": "voting"
        }
      },
      "metrics": [
        {
          "name": "p99_response_latency",
          "unit": "ms",
          "value": "4m"
        },
        {
          "name": "p90_response_latency",
          "unit": "ms",
          "value": "4m"
        },
        {
          "name": "p50_response_latency",
          "unit": "ms",
          "value": "2m"
        },
        {
          "name": "success_count",
          "value": "30"
        },
        {
          "name": "failure_count",
          "value": "0"
        }
      ]
    },
    {
      "kind": "TrafficMetrics",
      "apiVersion": "metrics.smi-spec.io/v1alpha1",
      "metadata": {
        "name": "web",
        "namespace": "emojivoto",
        "selfLink": "/apis/metrics.smi-spec.io/v1alpha1/namespaces/emojivoto/deployments/web/edges",
        "creationTimestamp": "2019-08-24T13:22:26Z"
      },
      "timestamp": "2019-08-24T13:22:26Z",
      "window": "30s",
      "resource": {
        "kind": "Deployment",
        "namespace": "emojivoto",
        "name": "web"
      },
      "edge": {
        "direction": "to",
        "resource": {
          "kind": "Deployment",
          "namespace": "emojivoto",
          "name": "emoji"
        }
      },
      "metrics": [
        {
          "name": "p99_response_latency",
          "unit": "ms",
          "value": "4m"
        },
        {
          "name": "p90_response_latency",
          "unit": "ms",
          "value": "4m"
        },
        {
          "name": "p50_response_latency",
          "unit": "ms",
          "value": "2m"
        },
        {
          "name": "success_count",
          "value": "60"
        },
        {
          "name": "failure_count",
          "value": "0"
        }
      ]
    }
  ]
}

The above response shows the edges from web, i.e inbound and outbound requests from deployments and the respective golden metrics for the corresponding edges.

The same queries can be done for different kinds of resources i.e pods, namespaces, daemonsets, etc as specified in the smi-spec

Isito support was added pretty recently. Feel free to try out and submit feedback/issues. :smiley: