This is the second post in a Progressive Delivery series, see the first one, Progressive Delivery in Kubernetes: Blue-Green and Canary Deployments.
I have evaluated three Progressive Delivery options for Canary and Blue-Green deployments with Jenkins X, using my Croc Hunter example project.
- Shipper enables blue-green and multi cluster deployments for the Helm charts built by Jenkins X, but has limitations on what are the contents of the chart. You could do blue-green between staging and production environments.
- Istio allows to send a percentage of the traffic to staging or preview environments by just creating a VirtualService.
- Flagger builds on top of Istio and adds canary deployment, with automated roll out and roll back based on metrics. Jenkins X promotions to the production environment can automatically be canary-enabled for a graceful roll out by creating a Canary object.
Find the example code for Shipper, Istio and Flagger.
Shipper
Because Shipper has multiple limitations on the Helm charts created I had to make some changes to the app. Also Jenkins X only builds the Helm package from master so we can’t do rollouts of PRs, only the master branch.
The app label can’t include the release name, ie. app: {{ template “fullname” . }} won’t work, need something like app: {{ .Values.appLabel }}
App rollout failed with the Jenkins X generated charts due to a generated templates/release.yaml, probably a conflict with jenkins.io/releases CRD.
Chart croc-hunter-jenkinsx-0.0.58 failed to render: could not decode manifest: no kind "Release" is registered for version "jenkins.io/v1"
We just need to change jx step changelog to jx step changelog –generate-yaml=false so the file is not generated.
In multi cluster, it needs to use public urls for both chartmuseum and docker registry in the shipper application yaml so the other clusters can find the management cluster services to download the charts.
Istio
We can create this Virtual Service to send 1% of the traffic to a Jenkins X preview environment (for PR number 35), for all requests coming to the Ingress Gateway for host croc-hunter.istio.example.org
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: croc-hunter-jenkinsx namespace: jx-production spec: gateways: - public-gateway.istio-system.svc.cluster.local - mesh hosts: - croc-hunter.istio.example.com http: - route: - destination: host: croc-hunter-jenkinsx.jx-production.svc.cluster.local port: number: 80 weight: 99 - destination: host: croc-hunter-jenkinsx.jx-carlossg-croc-hunter-jenkinsx-serverless-pr-35.svc.cluster.local port: number: 80 weight: 1
Flagger
We can create a Canary object for the chart deployed by Jenkins X in the jx-production namespace, and all new Jenkins X promotions to jx-production will automatically be rolled out 10% at a time and automatically rolled back if anything fails.
apiVersion: flagger.app/v1alpha2 kind: Canary metadata: # canary name must match deployment name name: jx-production-croc-hunter-jenkinsx namespace: jx-production spec: # deployment reference targetRef: apiVersion: apps/v1 kind: Deployment name: jx-production-croc-hunter-jenkinsx # HPA reference (optional) # autoscalerRef: # apiVersion: autoscaling/v2beta1 # kind: HorizontalPodAutoscaler # name: jx-production-croc-hunter-jenkinsx # the maximum time in seconds for the canary deployment # to make progress before it is rollback (default 600s) progressDeadlineSeconds: 60 service: # container port port: 8080 # Istio gateways (optional) gateways: - public-gateway.istio-system.svc.cluster.local # Istio virtual service host names (optional) hosts: - croc-hunter.istio.example.com canaryAnalysis: # schedule interval (default 60s) interval: 15s # max number of failed metric checks before rollback threshold: 5 # max traffic percentage routed to canary # percentage (0-100) maxWeight: 50 # canary increment step # percentage (0-100) stepWeight: 10 metrics: - name: istio_requests_total # minimum req success rate (non 5xx responses) # percentage (0-100) threshold: 99 interval: 1m - name: istio_request_duration_seconds_bucket # maximum req duration P99 # milliseconds threshold: 500 interval: 30s
Pingback: Progressive Delivery with Jenkins X: Automatic Canary Deployments | Carlos Sanchez's Weblog