Evaluate Istio on OpenShift

Do you know exactly what Istio does?
Istio is an open platform to connect, manage, and secure microservices. Istio provides an easy way to create a network of deployed services with load balancing, service-to-service authentication, monitoring, and more, without requiring any changes in service code. This post will describe deployment of the latest release and show basic functionality. Hopefully, it will sum up all the information you can find in the Istio Documentation.

Note: OpenShift does not support Istio, and this post is solely an illustration of a way to evaluate the technology deployed on top of an OpenShift platform.

Installation

Note that you will need OpenShift 3.7 (soon to be released), as Istio leverages custom resource definitions. Let’s first install Istio with the following commands, used to:

  • Create the project istio-system as the location to deploy all the components.
  • Add necessary permissions.
  • Deploy Istio components.
  • Deploy additional add-ons, namely Prometheus, Grafana, Service Graph and Zipkin.
  • Expose routes for those add-ons and define handy variables to reference those routes later on in this document.

We will also install istioctl, which we will mainly use to inject Istio sidecar containers to our deployments.
Note: In order to deploy this, you must be using a cluster-admin user. This is required as this user will need to run things in a privileged way, or even with containers as root.

oc new-project istio-system
oc project istio-system
oc adm policy add-scc-to-user anyuid -z istio-ingress-service-account
oc adm policy add-scc-to-user privileged -z istio-ingress-service-account
oc adm policy add-scc-to-user anyuid -z istio-egress-service-account
oc adm policy add-scc-to-user privileged -z istio-egress-service-account
oc adm policy add-scc-to-user anyuid -z istio-pilot-service-account
oc adm policy add-scc-to-user privileged -z istio-pilot-service-account
oc adm policy add-scc-to-user anyuid -z default
oc adm policy add-scc-to-user privileged -z default
oc adm policy add-cluster-role-to-user cluster-admin -z default

curl -L https://git.io/getLatestIstio | sh -
ISTIO=`ls | grep istio`
export PATH="$PATH:~/$ISTIO/bin"
cd $ISTIO
oc apply -f install/kubernetes/istio.yaml

oc create -f install/kubernetes/addons/prometheus.yaml
oc create -f install/kubernetes/addons/grafana.yaml
oc create -f install/kubernetes/addons/servicegraph.yaml
oc create -f install/kubernetes/addons/zipkin.yaml
oc expose svc grafana
oc expose svc servicegraph
oc expose svc zipkin
SERVICEGRAPH=$(oc get route servicegraph -o jsonpath='{.spec.host}{"\n"}')
GRAFANA=$(oc get route grafana -o jsonpath='{.spec.host}{"\n"}')/dotviz
ZIPKIN=$(oc get route zipkin -o jsonpath='{.spec.host}{"\n"}')

Deploy the Sample App

We deploy a sample application called BookInfo, which displays information about a book and is composed of several microservices running in different versions.

The architecture of the app can be seen in the following diagram:

https://istio.io/docs/guides/bookinfo.html
Image from https://istio.io/docs/guides/bookinfo.html

Note that we use istioctl kube-inject to patch the deployment files of the services of this app so that it includes within each pod envoy-proxy a sidecar container to interconnect all the pods. There goes your service mesh!

Sadly, that doesn’t work at the moment with deploymentconfig resources, so it won’t play nicely yet with oc new-app.

We also generate a workload for this application to demonstrate some core features.

oc apply -f <(istioctl kube-inject -f samples/bookinfo/kube/bookinfo.yaml)
oc expose svc productpage

PRODUCTPAGE=$(oc get route productpage -o jsonpath='{.spec.host}{"\n"}')
watch -n 1 curl -o /dev/null -s -w %{http_code}\n $PRODUCTPAGE/productpage

Check Everything is Up

You can use the following to see if pods from Istio, add-ons, and our sample app microservices are properly running:

oc get pod
NAME                             READY     STATUS    RESTARTS   AGE
details-v1-2202528699-596b9      2/2       Running   0          26m
grafana-3374311966-c1kmk         1/1       Running   0          34m
istio-ca-1144596003-w7047        1/1       Running   0          43m
istio-egress-4022046676-1bjnl    1/1       Running   0          43m
istio-ingress-2692470798-f0cbr   1/1       Running   0          43m
istio-mixer-971169182-7z45q      2/2       Running   0          43m
istio-pilot-953936588-zwnwg      1/1       Running   0          43m
productpage-v1-849198989-f83db   2/2       Running   0          19m
prometheus-4086688911-1zgtk      1/1       Running   0          34m
ratings-v1-217391091-jt80h       2/2       Running   0          26m
reviews-v1-3397570414-gkqk8      2/2       Running   0          26m
reviews-v2-755907806-38f5j       2/2       Running   0          26m
reviews-v3-1808066742-jt994      2/2       Running   0          26m
servicegraph-3304329788-mrbpp    1/1       Running   0          34m
zipkin-3660596538-cgb5l          1/1       Running   0          34m

Use Istio Features

Basic Communication

If you access the bookinfo app, available at $PRODUCTPAGE, you should see the following. When you refresh, you will see black or red stars, or no stars at all, depending on which version of the reviews service you’re hitting.

There are several ways we can monitor our mesh. For instance, if we go to $SERVICEGRAPH, we will see a graphical view of the connections between our services:

Alternatively, we can connect to the $GRAFANA dashboard and visualize graphically the traffic:

Our sample application propagates specific HTTP headers so that when the proxies send span information to $ZIPKIN, the spans can be correlated correctly into a single trace.

Configuration is required to generate given metrics and send them to Prometheus in the case of your own app. This is fully described in collecting metrics.

Intelligent Routing

Istio service mesh allows one to externally control service monitoring and tracing, request (version) routing, resiliency testing, security, and policy enforcement.

Let’s direct all incoming traffic for the BookInfo application to the v1 version of the reviews service. We will also send traffic only from the specific user named “jason” to version v2:

oc create -f samples/bookinfo/kube/route-rule-all-v1.yaml
oc create -f samples/bookinfo/kube/route-rule-reviews-test-v2.yaml

You can check the added rules with the following command. Note that as per Istio’s installation, custom resources definitions, like routerule, were added:

oc get routerule -o yaml

Now, if you access your $PRODUCTPAGE URL, you should see how no stars displayed when refreshing, because you’re only hitting version v1 of the reviews service. If you login as jason, you will instead see black stars (coming from version v2 of this service).

Delays

Let’s inject a 7s delay between the reviews:v2 and ratings microservices, by making use of the httpFault field of a routing rule. It will only affect user jason, as all other users are being routed to version v1 of the reviews service. Note the delay when logged with this user. It actually makes the review fetching fail, because of a bug in this version of the service.

oc create -f samples/bookinfo/kube/route-rule-ratings-test-delay.yaml 

Timeouts

A timeout for HTTP requests can also be specified using the httpReqTimeout field of a routing rule. That allows you to combine rules for delays and timeouts so you can easily study how your applications behave when one service times out, as a dependent service takes too long to answer a call.

Weight-based version routing

We can even direct a percentage of the requests to a given version of a service. For instance, the following rule will replace the existing reviews-default route rule previously created so that it instead directs half of the requests to version v3 of the reviews service. You can see that you now get red stars roughly half of the time:

oc replace -f samples/bookinfo/kube/route-rule-reviews-50-v3.yaml

Quotas

We can also rate limit traffic to a service. In this example, we first create a memquota object specifying the rate limits, which specifies a default 5000 qps rate limit while traffic reaching the ratings service via reviews-v2 is subject to a 1qps rate limit (jason for instance), then a quota instance specifying how to make the count and finally a rule matching both elements.
With this example, if you generate a lot of workload, jason should not be able to make use of v2 reviews service.

oc create -f samples/bookinfo/kube/mixer-rule-ratings-ratelimit.yaml

Egress Routing

It’s important to note that by default, Istio-enabled services are unable to access URLs outside of the cluster. To enable such access, we can create egress rules like the following which would provide us access from the pods to httpbin.org ( you can use actually use http://httpbin.org/delay/5 to test with a given delay )

apiVersion: config.istio.io/v1alpha2
kind: EgressRule
metadata:
  name: httpbin-egress-rule
spec:
  destination:
    service: httpbin.dyndns.org
  ports:
    - port: 80
      protocol: http

You can also specify HTTPS as protocol, but then note you will have to specify the port in the requests from your pods.
You can even create routing rules ( using http_req_timeout ) against external destination

Note: This is not interfacing with egress routers, but an egress router can be added to control the source IP of the outbound traffic.

apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: httpbin-timeout-rule
spec:
  destination:
    service: httpbin.org
  http_req_timeout:
    simple_timeout:
      timeout: 3s

Alternatively, when running istioctl kubectl-inject, you can use the additional flag –includeIPRanges to specify the cidr(s) where to inject envoy side car containers.

Access control

We can limit access to a given version of a service, either using explicit denials or whitelists.
We create:

  • A denier object with the message to give to the user.
  • A checknothing object to match every request.
  • Finally, a rule to apply when no user is specified in the header.

We will effectively prevent everyone (but the now famous Jason) to actually make use of the bookinfo app:

sed -i "s/istio-config-default/istio-system/g" samples/bookinfo/kube/mixer-rule-ratings-denial.yaml
oc create -f -f samples/bookinfo/kube/mixer-rule-ratings-denial.yaml

Conclusion

Istio provides extra functionality on top of your microservices, freeing the developers to implement this kind of logic in their application. There are more things that can be done using Istio, like using its ingress controller functionality, so be sure to browse the docs!

Note: OpenShift does not support Istio, and this post is solely an illustration of a way to evaluate the technology, not to be used in a real productive cluster.

Categories
OpenShift Container Platform
Tags
,
  • Jordi Torrente

    Great article!!! Thanks.

    Just a small comment:

    SERVICEGRAPH=$(oc get route servicegraph -o jsonpath='{.spec.host}{“n”}’)
    GRAFANA=$(oc get route grafana -o jsonpath='{.spec.host}{“n”}’)/dotviz

    should be

    SERVICEGRAPH=$(oc get route servicegraph -o jsonpath='{.spec.host}{“n”}’)/dotviz
    GRAFANA=$(oc get route grafana -o jsonpath='{.spec.host}{“n”}’)