How Do I Use Istio to Perform a Canary Deployment? Detailed how-to guide

This section describes the Canary Deployment Tutorial for Istio

Canary deployments help introduce new versions of services because they provide a way to deploy new features gradually. When an update rolls out, it’s released to a small subset of users in stages. This allows developers to see how the update is performing before making it available to everyone.

How Do I Perform a Canary Deployment on Istio? Kubernetes is designed to perform canary deployments locally. However, the downside of this approach is that throttling traffic for Canary deployments (by changing the replica ratio) needs to be done manually. The solution to simplify this process is to use a service mesh, such as open-source Istio, to decouple traffic distribution and replica counting.

In this tutorial, you’ll learn how to deploy a canary version of your application in an Istio-enabled cluster and set up Istio to control traffic routing.

Prerequisite

  • Kubernetes cluster (minikube)
  • kubectl command-line tool
  • Istio is installed
  • Docker Hub account
  • Grafana dashboard

Step 1: Build Docker images and containers for the canary build

How Do I Use Istio to Perform a Canary Deployment? To start deploying the canary version of your app, first create a docker image that contains the version you want to deploy.

  1. Go to the directory that contains the files you need for your image. The example uses an application called test-canary, stored in a directory with the same name:
cd test-canary

2. Use the docker build command to build a Docker image. Execute the command using your Docker Hub username and image name:

docker build -t [dockerhub-username]/test-canary .

The output confirms that the image has been created successfully.

3. Use the docker images command to look at your list of images and check if the new image is in it:

docker images

4. Next, use the docker run command to build a container using the image you created earlier. Give the container a name and select an access port:

docker run --name [name] -p [port]:8080 -d [dockerhub-username]/test-canary

If the operation is successful, the full ID of the newly created container is output:

5. Use the docker ps command to see the running container:

docker ps

6. Now access it through your browser using the port you assigned to the container:

http://localhost:[port]

The browser displays the contents of the application:

Istio Executes the Canary Deployment Tutorial

7. Once you have confirmed that the application is working properly, use the docker stop command to stop the container. Add the container ID to the command, and you can copy it from the first column of docker ps output:

docker stop [container-id]

8. Finally, to push the image to your Docker Hub account, log in to Docker Hub using the command line:

docker login -u [dockerhub-username]

You will be asked to enter your password. Enter your password and press Enter:

9. Now push the image docker push with the following command:

docker push [dockerhub-username]/test-canary

Note: Please visit our article on the most common Docker commands and download our PDF cheat sheet for future reference.

Step 2: Modify the app deployment

How Do I Use Istio to Perform a Canary Deployment? To add a canary deployment to your regular application deployment, use a text editor to edit the file that contains the service and deployment specifications.

The example uses an application manifest named app-manifest.yaml:

nano app-manifest.yaml

Istio Performing Canary Deployment Tutorial: The manifest should look something like this:

apiVersion: v1
kind: Service
metadata:
  name: nodejs
  labels:
    app: nodejs
spec:
  selector:
    app: nodejs
  ports:
  - name: http
    port: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs
  labels:
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodejs
  template:
    metadata:
      labels:
        app: nodejs
        version: v1
    spec:
      containers:
      - name: nodejs
        image: markopnap/test-prod
        ports:
        - containerPort: 8080

How Do I Perform a Canary Deployment on Istio? The example manifest above depicts a production version of a Node.js application whose container is stored in markopnap/test-prod. To include the canary version of your application, first edit the deployment section of the file and add -v1 to the name of your application:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-v1

Now, attach another deployment section to the end of the file with the specification for the Canary build:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-v2
  labels:
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodejs
  template:
    metadata:
      labels:
        app: nodejs
        version: v2
    spec:
      containers:
      - name: nodejs
        image: markopnap/test-canary
        ports:
        - containerPort: 8080

Note: Remember to replace the sample Docker Hub image location with your file location.

When you’re done editing the file, save it, and then update the system configuration with kubectl apply with the following command:

kubectl apply -f app-manifest.yaml

Step 3: Configure the Istio virtual service

How Do I Use Istio to Perform a Canary Deployment? Create a new yaml file to store the Istio configuration. The example uses a file named istio.yaml, but you can give it a name of your choice:

nano istio.yaml

If you previously deployed a production version with Istio, the file already exists and should look something like this:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: nodejs-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nodejs
spec:
  hosts:
  - "*"
  gateways:
  - nodejs-gateway
  http:
  - route:
    - destination:
        host: nodejs

The file has two parts that define the Gateway and VirtualService objects. To introduce the two versions of the application and set up the routing rules that are distributed to users, modify the section at the bottom of the HTTP. The section must contain two destinations with different subsets and weights:

http:
  - route:
    - destination:
        host: nodejs
        subset: v1
      weight: 90
    - destination:
        host: nodejs
        subset: v2
      weight: 10

The weight parameter tells Istio which percentage of traffic should be routed to a specific destination. In the example above, 90% of the traffic goes to the production build, while 10% of the traffic goes to the Canary build.

Once you’ve edited the Virtual Service section, append the following line to the end of the file to create a Destination Rule:

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

The purpose of defining a destination rule is to manage incoming traffic and send it to a specified version of the application.

Save the file and use kubectl apply it to activate it:

kubectl apply -f istio.yaml

Step 4: Test your canary deployment

How Do I Use Istio to Perform a Canary Deployment? The configuration set in the previous step performs traffic routing to your production and canary deployments. To test this, use the external IP access application istio-ingressgateway, which Istio uses as a load balancer.

Note: If you’re using minikube, you’ll need to emulate a load balancer by opening another terminal window and issuing commands. Without this, the external IP field in the next step will always show up as pending.minikube tunnel

Istio Performing Canary Deployment Tutorial: istio-ingressgateway looks for the service in the list of services available in the istio-system namespace. Use the services listed with kubectl get:

kubectl get svc -n istio-system

Copy the istio-ingressgateway external IP address into your browser’s address bar:

http://[ingressgateway_ip]

The browser may display the production version of the application. Hit the refresh button multiple times to simulate some traffic:

After a few times, you should see the canary version of the app:

If you have the Grafana add-on installed, check the incoming request statistics to see the percentage of routes for each deployment. In Grafana, click the home icon:

In the Dashboards section, select Istio and click Istio Service Dashboard:

How Do I Perform a Canary Deployment on Istio? In the dashboard, find the Services field and select the service that corresponds to your application. In this example, the service is named nodejs.default.svc.cluster.local. Once you’ve selected your service, go to the Service Workloads section:

Select the chart titled Incoming Requests By Destination Workload and Response Code. The chart shows the amount of traffic you’re generating by refreshing the page. In this example, it’s clear that Istionodejs-v1 provides application versions more frequently than Canarynodejs-v2.

Conclusion of the Canary Deployment Tutorial on Istio

How Do I Use Istio to Perform a Canary Deployment? With this tutorial, you learned how to set up Istio to automatically route traffic to multiple versions of an application. The article also provides instructions on setting up routing rules for Canary app deployments.