Canaries with Istio and Argo RolloutsStep 11 of 13: Migrating Deployments to Argo Rollouts
All Labs

Migrating Deployments to Argo Rollouts

At the moment, our demo application is using standard Kubernetes Deployments to manage the frontend and API Services. These object types do not support advanced deployment strategies such as canary or blue-green deployments and typically, we need to use additional tools to achieve this. Argo Rollouts provides a custom resource named Rollout that extends the standard Deployment with additional features. To enable canary deployments using Argo Rollouts, we need to migrate our existing Deployments to Rollouts.

To migrate the frontend Deployment, copy the existing Deployment manifests from 01_app_manifests/ to new files (rollout-frontend.yaml and rollout-api.yaml, change the kind and apiVersion fields, and add a strategy section as shown below:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
[...]
spec:
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {duration: 1m}
      - setWeight: 50
      - pause: {duration: 3m}
      trafficRouting:
        istio:
          virtualService:
            name: learning-tracker-frontend
            routes:
            - learning-tracker-frontend
          destinationRule:
            name: learning-tracker-frontend
            canarySubsetName: canary
            stableSubsetName: stable
[...]

For the API Deployment, the final manifest should look like this:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  creationTimestamp: null
  labels:
    app: learning-tracker-api
  name: learning-tracker-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: learning-tracker-api
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: learning-tracker-api
    spec:
      containers:
        - image: ghcr.io/tsclabs-eu/lab-istio-rollouts/learning-tracker-api:v1
          name: learning-tracker-api
          resources: {}
          env:
            - name: LOG_OUTPUT
              value: "console"
            - name: LOG_LEVEL
              value: "debug"
            - name: DB_TYPE
              value: "mysql"
            - name: DB_USER
              value: "app"
            - name: DB_PASSWORD
              value: "my_password"
            - name: DB_HOST
              value: "mariadb"
            - name: DB_NAME
              value: "learning.db"
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 3
  strategy:
    canary:
      trafficRouting:
        istio:
          virtualService:
            name: learning-tracker-api
            routes:
              - learning-tracker-api
          destinationRule:
            name: learning-tracker-api
            canarySubsetName: canary
            stableSubsetName: stable
      steps:
        - setWeight: 20
        - pause:
            duration: 1m
        - setWeight: 50
        - pause:
            duration: 3m

The strategy section defines the canary deployment strategy. In this example, we are using a simple canary strategy that shifts 20% of the traffic to the new version, waits for 1 minute, then shifts 50% of the traffic, and finally waits for 3 minutes before completing the rollout. The trafficRouting section specifies the Istio Virtual Service and Destination Rule to use for routing traffic during the rollout. As we're using the subsets defined in the previous step, we specify the names of the subsets to use for the stable and canary versions.

This shows a very basic canary strategy. In a real-world scenario, you would also add analyses to automatically verify the health of the new version before shifting more traffic to it. Furthermore, you could make previews of the new version available to a subset of users before rolling it out to everyone.

As soon as you have created the Rollout manifests, remove the existing Deployments using the following commands:

kubectl delete deployment learning-tracker-frontend -n learning-tracker
kubectl delete deployment learning-tracker-api -n learning-tracker

After that, apply the new Rollout manifests using the following commands:

kubectl apply -f rollout-frontend.yaml -n learning-tracker
kubectl apply -f rollout-api.yaml -n learning-tracker

Now, you can verify that the Rollouts are created and running using the following command:

kubectl get rollouts -n learning-tracker

You should see output similar to this:

NAME                        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
learning-tracker-api        3         3         3            3           38s
learning-tracker-frontend   2         2         2            2           46s

When browsing the demo application, you should still see the same functionality as before. However, now the frontend and API services are managed by Argo Rollouts, and we can use the canary deployment strategy defined in the Rollout manifests.

🎉Congratulations

You migrated the existing Deployments to Argo Rollouts. In our final step, we will perform a canary deployment to demonstrate how traffic is shifted between different versions of the frontend and backend services.