Skip to content

Latest commit

 

History

History
494 lines (316 loc) · 23.9 KB

readme.md

File metadata and controls

494 lines (316 loc) · 23.9 KB

Integrate the Istio Service Mesh with AKS

This training module provides step-by-step guidance for integrating the Istio Service Mesh into an AKS cluster. You'll also find steps for leveraging Istio to provide targeted canary releases for rolling out application updates.

Introduction

A service mesh is a decentralized application networking layer, highly optimized for modern workloads, such as microservice applications. The mesh provides built-in capabilities that handle key infrastructure concerns:

  • Service communication and routing
  • Service identity and security
  • Policy enforcement
  • Observability

A service mesh decouples infrastructure capabilities from the application. It moves infrastructure plumbing from the application services to a proxy container that is injected alongside each of the application service containers. This side-by-side architecture is referred to as a sidecar. Although a separate component, a sidecar proxy is loosely coupled (or linked) to its corresponding service - the sidecar is created with the application service and shares its lifecycle.

Figure 1 shows an example of a service mesh architecture.

Service mesh with sidecar

Figure 1. Service mesh with sidecars

In the previous figure, note how each microservice has a corresponding sidecar proxy to handle its infrastructure concerns. When deployed to Kubernetes, an application service and sidecar proxy reside together in a Kubernetes pod.

Istio is a full featured, customizable, and extensible service mesh. It's arguably the most popular mesh. It's open source and specifically designed to secure and manage traffic between microservices running in different containers.

This lab module builds upon the completion of the Azure Kubernetes Workshop found in the Microsoft Learn training library. In that workshop, you built an AKS cluster hosting the Fruit Smoothies line-of-business application. This module will integrate the Istio Service Mesh into the application.

Pre-requisites

The following steps are required to successfully complete this module:

  • A Fruit Smoothies AKS cluster built from the Azure Kubernetes Workshop.

  • At least two node instances, if the cluster is running on Standard_DS2_v2 virtual machines (the default VM size)

  • Azure Subscription (commercial)

Tutorial: Install Isito

(15 minutes)

In this tutorial, you'll install the Istio Service Mesh into your AKS cluster.

The installation involves several steps. The instructions presented are a subset of the Install and use Istio in Azure Kubernetes Service (AKS) taken from Microsoft Docs.

Install the Istio client binary

You will start by installing the Istioctl CLI into your client. Similar to the Kubernetes, kubectl CLI, istioctl may be used to install and manage Istio within an AKS cluster.

To complete this lab, you'll use the Azure Cloud Shell. It's an interactive, authenticated, browser-accessible shell for managing Azure resources, including AKS. Conveniently, it's built into the Azure portal and is preloaded with many of the Azure libraries you will need. It provides both a Bash and PowerShell CLI experience.

Logon to the Azure Portal. Once loaded, open up an Azure Cloud Shell session by clicking on the Cloud Shell icon in the top navigation menu as shown in figure 2.

cloud-shell-launch-icon

Figure 2. Azure Cloud Shell launch icon

Next, select the Bash CLI from the drop-down list box in the upper left-hand corner as shown below in Figure 3.

cloud-shell-experience

Figure 3. Azure Cloud Shell CLI experience

You'll start by installing the Istioctl client binary.

The binary runs on the client machine enabling you to install and manage Istio in an AKS cluster.

The following commands will download and install the Istioctl client binary into your CloudShell instance. It'll be available immediately (in the current shell) and permanently (across shell restarts) via your PATH.

Use the following command to load identity credentials for your AKS cluster. You will need to provide your resource group and cluster name.

az aks get-credentials --resource-group RG-NAME --name CLUSTERNAME

From the CloudShell CLI, use the following commands to download Istio.

curl -L https://istio.io/downloadIstio | sh -

Next, open the folder in which Istio was downloaded and note the version number that is appended to the folder name: istio-X.X.X

Figure 4 shows the Istio version number of the downloaded package.

Istio version number

Figure 4. The Istio version number

Next, make the following changes:

# Change to the istio folder 
cd istio-X.X.X # Replace X.X.X. with the Istio version number
export PATH=$PWD/bin:$PATH

Next, you will use the Istioctl CLI to install Istio into your AKS cluster:

istioctl install

At this point, you've installed the Istio into your cluster. Use the following command to validate the Istio deployment.

kubectl get all -n istio-system

You should see the following components:

NAME                                        READY   STATUS    RESTARTS   AGE
pod/istio-ingressgateway-85c449d886-z98sm   1/1     Running   0          4h15m
pod/istiod-8495b6467-l2mtn                  1/1     Running   0          4h15m

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                                                      AGE
service/istio-ingressgateway   LoadBalancer   10.0.111.248   20.81.1.193   15021:30278/TCP,80:30889/TCP,443:32178/TCP,15012:30786/TCP,15443:30325/TCP   4h15m
service/istiod                 ClusterIP      10.0.164.124   <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP                                        4h15m

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/istio-ingressgateway   1/1     1            1           4h15m
deployment.apps/istiod                 1/1     1            1           4h15m

NAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/istio-ingressgateway-85c449d886   1         1         1       4h15m
replicaset.apps/istiod-8495b6467                  1         1         1       4h15m

NAME                                                       REFERENCE                         TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/istio-ingressgateway   Deployment/istio-ingressgateway   3%/80%    1         5         1          4h15m
horizontalpodautoscaler.autoscaling/istiod                 Deployment/istiod                 0%/80%    1         5         1          4h15m

Tutorial: Canary Releases with Isito

(20 minutes)

In this next tutorial, you'll use the Istio service mesh to implement a Canary release in your AKS cluster.

A canary release is a software deployment technique that reduces the risk of introducing a new software version into production by slowly rolling out the change to a small subset of users before rolling it out to the entire infrastructure and making it available to everybody.

Figure 5 shows a canary release.

Canary Release

Figure 5. Canary release

Note in the above figure how the new version of the application is rendered to only 5% of the users. You'll increase that number as you gain experience and confidence with the new version. If something were to go wrong, you could route all users back to the old version.

Deploy an application and configure the Istio Gateway

To start, you'll deploy a different application, BookInfo, to implement canary releases. The application ships as a sample with the Istio installation.

To start, you'll deploy an application entitled BookInfo to the existing cluster.

First, create a new Kubernetes namespace for the BookInfo app with the following command:

kubectl create namespace bookinfo

This command creates the bookinfo namespace in your Kubernetes cluster. To confirm, type the following command to show all namespaces from your cluster:

kubectl get namespace

You should see bookinfo in the list.

Next, enable the bookinfo namespace to use the Istio Service Mesh. Every time a bookinfo pod is created, you'll want an Istio sidecar container injected into it. The following command enables an Istio feature called automatic sidecar injection.

kubectl label namespace bookinfo istio-injection=enabled

The command adds the label istio-injection=enabled to the bookinfo namespace. Upon seeing the label, Istio will automatically inject a sidecar into any pod you instantiate in the bookinfo namespace.

Type the following command to see the newly created label:

kubectl get namespace --show-labels

You should see the newly created label for the bookinfo namespace:

NAME              STATUS   AGE     LABELS
bookinfo          Active   6m31s   istio-injection=enabled
cert-manager      Active   80d     <none>
clusterinfo       Active   37d     app.kubernetes.io/managed-by=Helm
default           Active   90d     <none>
ingress           Active   80d     <none>
istio-operator    Active   11d     istio-injection=disabled,istio-operator-managed=Reconcile,istio.io/rev=default
istio-system      Active   11d     <none>
kube-node-lease   Active   90d     <none>
kube-public       Active   90d     <none>
kube-system       Active   90d     addonmanager.kubernetes.io/mode=Reconcile,control-plane=true,kubernetes.io/cluster-service=true
ratings-app       Active   90d     istio-injection=enabled

Note the istio-injection=enabled label in the bookinfo namespace.

Now run the Istioctl analyze command to verify everything is setup correctly.

 istioctl analyze -n bookinfo

Clone the book info sample application.

# Clone the istio repo, which includes the sample application
git clone https://github.com/istio/istio.git

# Naviagate into the istio folder
cd istio

Next, deploy the BookInfo application.

Remember to add the --namespace bookinfo to end of each command!

kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml --namespace bookinfo

The command deploys the BookInfo application to the bookinfo namespace. Confirm that the bookinfo services and pods are correctly defined and running:

kubectl get services,pods --namespace bookinfo 

You should see the following services and pods:

NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.0.0.31    <none>        9080/TCP   6m
productpage   ClusterIP   10.0.0.120   <none>        9080/TCP   6m
ratings       ClusterIP   10.0.0.15    <none>        9080/TCP   6m
reviews       ClusterIP   10.0.0.170   <none>        9080/TCP   6m

NAME                             READY     STATUS    RESTARTS   AGE
details-v1-1520924117-48z17      2/2       Running   0          6m
productpage-v1-560495357-jk1lz   2/2       Running   0          6m
ratings-v1-734492171-rnr5l       2/2       Running   0          6m
reviews-v1-874083890-f0qf0       2/2       Running   0          6m
reviews-v2-1343845940-b34q5      2/2       Running   0          6m
reviews-v3-1813607990-8ch52      2/2       Running   0          6m

Next, confirm the Bookinfo application is running by sending a request to it using a curl command.

kubectl exec "$(kubectl get pods -l app=ratings --namespace  bookinfo -o jsonpath='{.items[0].metadata.name}')" -c ratings --namespace bookinfo -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"

You should see the following information returned:

<title>Simple Bookstore App</title>

Now that BookInfo is up and running, you need to make it accessible from outside of your Kubernetes cluster, e.g., from a browser. An Istio Gateway is used for this purpose.

The following command deploys the Istio ingress gateway for the application:

Remember to add the --namespace bookinfo to end of the command!

kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml --namespace bookinfo

Once complete, confirm that the gateway has been created:

kubectl get gateway --namespace bookinfo

You see the following response:

NAME               AGE
bookinfo-gateway   11s

Next, you'll set environment variables for the gateway host and port. The first command creates an environment variable entitled INGRESS_HOST with the IP address of the load balancer:

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

The next command creates an environment variable entitled INGRESS_PORT that contains the port:

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')

Finally, create a third environment variable entitled GATEWAY_URL:

export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

The $GATEWAY_URL is the external IP address of the Istio gateway. It's the ingress gateway for the BookInfo application.

Execute the following curl command to confirm the application is available from outside the cluster:

curl -s "http://${GATEWAY_URL}/productpage" | grep -o "<title>.*</title>"

If all goes right, you will see:

<title>Simple Bookstore App</title>

Input the following command to return the GATEWAY_URL for your instance:

echo $GATEWAY_URL

Finally, copy and paste the $GATEWAY_URL value into Notepad on your computer. You'll need it shortly.

Traffic Routing with Istio

The traffic routing features of Istio enables you to specify routing rules that control traffic flow between frontend APIs and backend services. Included are service-level properties that support A/B testing, canary rollouts, and staged rollouts with percentage-based traffic splits. It also provides built-in failure recovery features to make your application more robust against failures of dependent services or the network.

Two resources for traffic routing are Istio destination rules and virtual services.

Apply destination rules

Before you can use Istio to control routing to a specific version of the BookInfo application, you'll need to define the available versions, called subsets, using Istio destination rules.

Destination rules specify a subset of services to be invoked by a request. Often, subsets are grouped based upon a given version of the services.

The next command will apply a default destination rule to the BookInfo service:

kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml --namespace bookinfo

Allow a few seconds for the destination rules to propagate.

Examine the destination rules with the following command:

kubectl get destinationrules -o yaml --namespace bookinfo

Apply virtual services

In this task, you'll learn how to dynamically route requests to different versions of your application.

You'll combine Istio virtual services with Istio destination rules. Virtual services contain the routing rules that let Istio route each incoming request to a specific destination in the Istio mesh. They decouple where clients send requests from the workloads that actually implement them.

A use case might be a requirement to send traffic to different versions of a service, specified as service subsets. Clients send requests to the virtual service host as if it was a single entity. Istio routes the traffic to different application versions as configured in the virtual service rules. For example, 20% of requests route to the new version and the remainder to the current version. Or, calls from users in a specific group, maybe, an early adopter group, route to version 2. As mentioned previously, these features enable canary rollouts, where you gradually increase the percentage of traffic that’s sent to a new service version. In these scenarios, traffic routing is separate from the deployed instances. The number of instances implementing the new service version can scale up and down based on traffic load without being coupled to traffic routing component. By contrast, container orchestration platforms like Kubernetes only support traffic distribution based on instance scaling, which can quickly become complex.

Routing based on percentage-based traffic splits

The BookInfo sample application is composed from four separate microservices, each with multiple versions. The review microservice currently has three different versions which are running concurrently. Open a browser and type in the URL for the BookIinfo product page:

http://<your GATEWAY_URL>/productpage

Continue to refresh the browser with the <F5> key. Note each time that the book review sometimes contains star ratings images and other times not. Sometimes the stars are colored red, and other times, black. Without an explicitly declared default service version, Istio routes requests to all available versions in a round robin fashion. To manage routing, you'll apply rules that route traffic to a specific instance of the microservice. Keep the browser open.

To route to one version only, you'll apply a virtual service that sets the default version for a microservice. In this example, you'll apply a virtual services that routes all traffic to v1 of each microservice:

kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml --namespace bookinfo

The configuration propagation is eventually consistent, so wait a few seconds for the virtual service to take effect.

Once applied, display the newly-defined routes with the following command:

kubectl get virtualservices -o yaml --namespace bookinfo

Go back to your open browser and type the following URL:

http://<your GATEWAY_URL>/productpage

As you refresh your browser, note how none of the reviews contain stars. You have configured Istio to route all traffic to v1 version of the BookInfo application. Version 1 of the review microservice doesn't render star images.

How would you approach evaluating multiple application versions at once?

You'll next deploy a virtual service implements just that. Using a canary release strategy, it routes 33% of the incoming traffic to version 1, 33% to version 2, and %34 percent to version 3.

To do so, you'll need to edit the yaml file to adjust the routing of the VirtualService

code samples/bookinfo/networking/virtual-service-reviews-90-10.yaml

This will open this file in Visual Studio code. Update the http section to look like the following:

  http:
 - route:
   - destination:
       host: reviews
       subset: v1
     weight: 33
   - destination:
       host: reviews
       subset: v2
     weight: 33
   - destination:
       host: reviews
       subset: v3
     weight: 34

Save and close file, and then update the Virtual Service with the following command:

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-90-10.yaml --namespace bookinfo

Go back to your open browser. As you refresh it, note how some reviews contain no stars, some contain black stars, and some red stars. You are now routing requests across all three services with a equal traffic split distribution.

After running the canary release with three versions, you might decide that version 3, not 2, is your target version. You'll now modify the canary release to distribute traffic equally between the current version and version 3. Deploy the following virtual service:

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml --namespace bookinfo

Go back to your open browser. As you refresh it, note how the review alternates between version 1 which contains no stars and version 3 which contains red stars. You have implemented a 50% traffic split between version 1 and 3.

At some point, you're confident that version 3 is ready of the masses. Deploy a virtual service that routes all traffic to version 3:

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-v3.yaml --namespace bookinfo

Back in your open browser, all reviews will render red stars.

Congratulations, you have successfully accomplished the first part of this task: Implement a canary release using the Istio service mesh.

Route based on user identity

You might also have a requirement for canary deployments that route traffic to certain groups, such as early adopters, or even specific individuals.

Next, you'll change the route configuration so that all traffic from a specific user is routed to a specific service version. In this case, all traffic from a user named Jason will be routed to version 2 of the application. Version 2 includes the star ratings feature.

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-jason-v2-v3.yaml --namespace bookinfo

Go back to your open browser, as you refresh it, note how the review section does not render star images.

On the /productpage of the BookInfo app, log in as user jason.

Note: Both the login and password values: jason

Refresh the browser. What do you see? The star ratings appear next to each review.

Log in as another user (pick any name you wish).

Refresh the browser. Now the stars are gone. This is because only traffic for the user is routed to newer version.

Congratulations. You have successfully configured Istio to route traffic based on user identity.

Other Service Meshes

Linkerd

Linkerd is an easy to use and lightweight service mesh. It provides a data plane that is composed of ultralight Linkerd specialized proxy sidecars. These intelligent proxies control all network traffic in and out of your meshed apps and workloads. The proxies also expose metrics via Prometheus metrics endpoints. Update the ratings app namespace to inject istio side-cars

Microsoft's Open Service Mesh

Microsoft's Open Service Mesh (OSM) is a lightweight, extensible, Cloud Native service mesh that allows users to uniformly manage, secure, and get out-of-the-box observability features for highly dynamic microservice environments. It's designed as a "lighter-weight" version of Istio.

Similar to Istio, OSM runs an Envoy-based control plane on Kubernetes, can be configured with SMI APIs, and works by injecting an Envoy proxy as a sidecar container next to each instance of your application. The Envoy proxy executes rules specified in access control policies, implements routing configuration, and captures metrics. The control plane continually configures proxies to ensure policies and routing rules are up to date and ensures proxies are healthy.

Currently, Open Service Mesh is in preview mode.

References

The resources below provide additional information about service meshes.