Posted on 

Argo Rollout Canary Deployment

this post aim to understand how Argo Rollout works.

prerequisites

  1. k8s cluster
  2. istio with full addon (easy to monitor and inspect)
  3. argo-rollout v1.7.0

1. create a cluster

Now. I use minikube to create a cluster. why me not use kind anymore? because kind is very simple not support tunnel for forwarding port.

1
minikube start

with default driver docker.

2. install istio

first of all. the user should download the istio binary from the official site.

1
2
$ istioctl install --set profile=demo -y
$ kubectl label namespace default istio-injection=enabled

and install some addons for monitoring and inspecting.

1
$ kubectl apply -f samples/addons

start browser to access kiali dashboard.

1
$ istioctl dashboard kiali
img.png
img.png

3. install argo-rollout

install argo-rollout with helm.

1
2
3
4
5
6
7
8
9
$ cd charts/argo-rollouts/
$ helm install -n argo-rollouts \ [19:42:40]
--set dashboard.enabled=true \
--set dashboard.service.type=NodePort \
--set controller.image.pullPolicy=IfNotPresent \
--set controller.image.registry="quay.io" \
--set controller.image.repository="argoproj/argo-rollouts" \
--set controller.image.tag="v1.7.0" \
argo-rollout .

4. install a rollout

As we know, The istio use a lb for accept the traffic.

traffic -> istio-ingressgateway -> gateway -> virtualservice -> service -> pod

4.1 gateway

This resource is a logical concept of the service grid, but it does not actually have a running entity.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: rollouts-demo-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"

4.2 virtualservice

The VirtualService resource is used to configure the routing rules for the traffic. acctually, it is a CRD of istio.
The most important parts of this virtualservice are the two services under the http field.
The implementation of the rollout controller will automatically adjust the weight of traffic forwarding according to the degree of rollout.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: rollouts-demo
spec:
gateways:
- rollouts-demo-gateway # bind the gateway
hosts:
- rollouts-demo.local # HTTP host header, help to route the traffic
http:
- name: primary # this is an usefully for canary deployment
route:
- destination:
host: rollouts-demo-stable # this required the service name
port:
number: 80
weight: 100
- destination:
host: rollouts-demo-canary # this required the service name too
port:
number: 80
weight: 0

4.3 service

The service is a k8s resource, it is used to expose the pod to the outside world.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: v1
kind: Service
metadata:
name: rollouts-demo-canary
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: rollouts-demo
---
apiVersion: v1
kind: Service
metadata:
name: rollouts-demo-stable
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: rollouts-demo

4.4 rollout

The Rollout resource is a custom resource provided by the argo-rollout controller. It is used to manage the deployment of the application.
to explain the Rollout resource, we need to know the canary strategy. the following example is a simple canary strategy.
that means is the canary service will receive 25% of the traffic, and the stable service will receive 75% of the traffic with first step.
the second step is the canary service will receive 50% of the traffic, and the stable service will receive 50% of the traffic.
the last step is the canary service will receive 100% of the traffic, and the stable service will receive 0% of the traffic.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
spec:
replicas: 4
strategy:
canary:
canaryService: rollouts-demo-canary
stableService: rollouts-demo-stable
trafficRouting:
istio:
virtualServices:
- name: rollouts-demo
routes:
- primary
steps:
- setWeight: 25
- pause: {}
- setWeight: 50
- pause: {}
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollouts-demo
template:
metadata:
labels:
app: rollouts-demo
istio-injection: enabled
version: "1"
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:blue
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m

5 test

start a tunnel for the istio-ingressgateway service.

1
2
3
4
5
6
7
8
9
$ minikube tunnel                                                                                                                                                                             [19:58:01]
✅ Tunnel successfully started

📌 NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ...

❗ The service/ingress istio-ingressgateway requires privileged ports to be exposed: [80 443]
🔑 sudo permission will be asked for it.
🏃 Starting tunnel for service istio-ingressgateway.
Password:

and set the /etc/hosts

1
2
$ cat /etc/hosts |grep rollout                                                                                                                                         [20:01:12]
127.0.0.1 localhost rollouts-demo-vsvc1.local rollouts-demo-vsvc2.local rollouts-demo.local

to check the rollout-demo VirtualService resource.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ kubectl get vs rollouts-demo -o yaml                                                                                                                                 [19:59:17]
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"rollouts-demo","namespace":"default"},"spec":{"gateways":["rollouts-demo-gateway"],"hosts":["rollouts-demo.local"],"http":[{"name":"primary","route":[{"destination":{"host":"rollouts-demo-stable","port":{"number":80}},"weight":100},{"destination":{"host":"rollouts-demo-canary","port":{"number":80}},"weight":0}]}]}}
creationTimestamp: "2024-07-04T10:00:19Z"
generation: 6
name: rollouts-demo
namespace: default
resourceVersion: "55486"
uid: 037f970f-1fc8-43cc-a651-aa1bf1910dd6
spec:
gateways:
- rollouts-demo-gateway
hosts:
- rollouts-demo.local
http:
- name: primary
route:
- destination:
host: rollouts-demo-stable
port:
number: 80
weight: 50
- destination:
host: rollouts-demo-canary
port:
number: 80
weight: 50

from the VirtualService resource, you can find the weight of the canary service is 50, and the weight of the stable service is 50. this value is the second step of the canary strategy.

try to access the rollouts-demo.local in the browser, you can see the result is blue color. because the canary service is 50% of the traffic.

rollouts-demo.local.png
rollouts-demo.local.png