A canary deployment is more complex than a blue-green deployment. It requires a service mesh to route traffic to the canary version of the application. In this example, we will use Istio.
Requirements
Prometheus (required for analysis templates)
Configuration
Create a service definition:
Copy apiVersion: v1
kind: Service
metadata:
name: demo-app
spec:
selector:
app: demo-app
ports:
- name: http-web
appProtocol: http
port: 80
Create a destination rule definition:
Copy apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: demo-app-destination-rule
spec:
host: demo-app.demo-app.svc.cluster.local
subsets:
- name: stable
labels:
app: demo-app
- name: canary
labels:
app: demo-app
Create a virtual service definition with destination routing rules:
Copy apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: demo-app-vs
spec:
hosts:
- "demo-app.ms1.com"
gateways:
- demo-app-gateway
http:
- name: primary
route:
- destination:
host: demo-app.demo-app.svc.cluster.local
subset: stable
weight: 100
- destination:
host: demo-app.demo-app.svc.cluster.local
subset: canary
weight: 0
Create a gateway definition:
Copy apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: demo-app-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http-web
protocol: HTTP
hosts:
- "demo-app.ms1.com"
Create an analysis template
Copy apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: istio-success-rate
spec:
args:
- name: demo-app
- name: demo-app
metrics:
- name: success-rate
initialDelay: 60s
interval: 20s
successCondition: result[0] > 0.90
provider:
prometheus:
address: http://prometheus.istio-system:9090
query: >+
sum(irate(istio_requests_total{
reporter="source",
destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local",
response_code!~"5.*"}[40s])
)
/
sum(irate(istio_requests_total{
reporter="source",
destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local"}[40s])
)
Create a rollout resource with the following configuration:
A rollout configuration encapulates a replicaset definition. No need to write both the rollout and the replicaset.
Copy apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: demo-app-canary-rollout
spec:
strategy:
canary:
trafficRouting:
istio:
virtualService:
name: demo-app-vs
routes:
- primary
destinationRule:
name: demo-app-destination-rule
canarySubsetName: canary
stableSubsetName: stable
steps:
- setWeight: 10
- pause:
duration: 2s
- setWeight: 30
- pause:
duration: 2s
- setWeight: 50
- pause:
duration: 2s
analysis:
templates:
- templateName: istio-success-rate
startingStep: 1
args:
- name: service
value: demo-app.demo-app.svc.cluster.local
- name: namespace
value: demo-app
selector:
matchLabels:
app: demo-app
template:
metadata:
labels:
app: demo-app
spec:
serviceAccountName: demo-app
containers:
- name: demo-app
image: memogarcia10/demo-app:v4
imagePullPolicy: Always
ports:
- containerPort: 80
name: http-web
securityContext:
runAsUser: 1000
resources:
limits:
cpu: 5m
memory: 64Mi