Step by Step – Istio up and running

Service Mesh is a pretty hot topic in the Kubernetes ecosystem currently, and I wanted to get it up and running in my own lab environment. Istio’s documentation has a pre-baked solution to demonstrate some of its capabilities (a book app, if memory serves me correctly), but I wanted to deploy my own app to get more “hands-on” experience with the tech, even if it’s only very basic to start with.

Install Istio

There are a number of prerequisite steps that need to be satisfied prior to installing Istio. These are specific to my environment, others may differ.

Install the Helm client

sudo snap install helm --classic

Grab Istio (1.2.0 in this example)

curl -L https://git.io/getLatestIstio | ISTIO_VERSION=1.2.0 sh - cd istio-1.2.0/

Create the Helm service account (named “tiller”)

kubectl apply -f install/kubernetes/helm/helm-service-account.yaml

Initialise Helm using the service account specified in the previous step

helm init --service-account tiller

Create a namespace to accommodate the Istio components

kubectl create ns istio-system

Initialise Istio into the aforementioned namespace:

helm install install/kubernetes/helm/istio-init --name istio-init --namespace istio-system

Monitor the state of the pods – it will take some time for the pods to finish – these create the CRD’s required for Istio

kubectl get pods -n istio-system NAME READY STATUS RESTARTS AGE istio-init-crd-10-t82m6 0/1 ContainerCreating 0 95s istio-init-crd-11-42622 0/1 ContainerCreating 0 95s istio-init-crd-12-65m5v 0/1 ContainerCreating 0 95s

Install Istio into the aforementioned namespace

helm install install/kubernetes/helm/istio --name istio --namespace istio-system

Configure a namespace for automatic sidecar injection

By this point, we have the internal foundations for Istio, but we’re not leveraging it. One of the fundamental workings of Istio is the use of pod sidecars. Sidecars act as the data plane, facilitating a lot of the features we want to leverage from Istio.

Istio doesn’t do this automatically, out of the box for all pods deployed into an environment, but Istio will inject sidecars into pods deployed into namespaces that have the istio-injection=enabled label set.

kubectl create ns app-with-injection namespace/app-with-injection created kubectl label namespace app-with-injection istio-injection=enabled namespace/app-with-injection labeled

We can validate this by creating a pod into this namespace:

kubectl run nginx -n app-with-injection --image nginx

And checking the Pod contents (notice how this pod has two containers)

kubectl get pods -n app-with-injection NAME READY STATUS RESTARTS AGE nginx-7cdbd8cdc9-96mbz 2/2 Running 0 52s

The proxy sidecar:



Environment Anatomy

The diagram below shows how my test environment is set up

Key considerations:

The Istio gateway will reside on the edge

80% of all traffic will be routed to v1 of my web application

20% of all traffic will be routed to v2 of my web application

The application manifest can be found at https://raw.githubusercontent.com/David-VTUK/istioexample/master/webapp.yaml

To accomplish this we need to implement two key objects:

Gateway

This is our entry point into our application. By default, Istio deploys the gateway object (we must note the external IP)

kubectl get svc -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP istio-citadel ClusterIP 10.100.200.47 istio-galley ClusterIP 10.100.200.149 istio-ingressgateway LoadBalancer 10.100.200.244 10.10.20.150,100.64.80.1 istio-pilot ClusterIP 10.100.200.170 istio-policy ClusterIP 10.100.200.3 istio-sidecar-injector ClusterIP 10.100.200.169 istio-telemetry ClusterIP 10.100.200.141 prometheus ClusterIP 10.100.200.238

We configure the Gateway by deploying a gateway manifest file:

apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: http-gateway spec: selector: istio: ingressgateway # use Istio default gateway implementation servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"

Kind : Type of object. Gateway is a CRD (Custom Resource Definition) that Istio implements

: Type of object. Gateway is a CRD (Custom Resource Definition) that Istio implements Selector : What this applies to, in this case the default Ingress Gateway

: What this applies to, in this case the default Ingress Gateway Ports : Which ports we want to listen to on the external IP address, together with a name and protocol

: Which ports we want to listen to on the external IP address, together with a name and protocol Hosts : We can implement layer 7 load balancing on the edge, but as I’ll be testing this out via IP address, “*” will suffice. In production, this would likely be an FQDN of an external facing website

VirtualService

A gateway object helps us define the entry point into the cluster, but we have yet to effectively tell the gateway where to route traffic to. This is where the VirtualService object type comes in. This is where we define routing intelligence.

apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: demoapp spec: hosts: - "*" gateways: - http-gateway http: - route: - destination: port: number: 80 host: vt-webapp-v1.app-with-injection.svc.cluster.local weight: 80 - destination: port: number: 80 host: vt-webapp-v2.app-with-injection.svc.cluster.local weight: 20

What the above effectively does is listen for all HTTP requests (hence the “*” under “hosts”) and route 80% of traffic to V1 of the webapp, by directing traffic at the respective service and 20% to v2.

Testing

The “WebApp” is pretty simple. It simply displays one of the following (depending on the version)

What we should now see from accessing the external IP is traffic being split across both services via a 80/20 split:

Out of 10 curl commands 8 were routed to v1 of my app, 2 were routed to v2 of my app.

Conclusion

Admittedly, this is an extremely simple example of a more simple use case of Istio, but as I’m learning, I think it’s a decent start, and I hope others find it useful.