<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Stefan Prodan</title>
    <description>The latest articles on Forem by Stefan Prodan (@stefanprodan).</description>
    <link>https://forem.com/stefanprodan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F176765%2Fa8197862-550d-4804-8146-e145255a8c31.jpeg</url>
      <title>Forem: Stefan Prodan</title>
      <link>https://forem.com/stefanprodan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stefanprodan"/>
    <language>en</language>
    <item>
      <title>A GitOps recipe for Progressive Delivery with Istio</title>
      <dc:creator>Stefan Prodan</dc:creator>
      <pubDate>Tue, 27 Apr 2021 16:25:30 +0000</pubDate>
      <link>https://forem.com/stefanprodan/a-gitops-recipe-for-progressive-delivery-2pa3</link>
      <guid>https://forem.com/stefanprodan/a-gitops-recipe-for-progressive-delivery-2pa3</guid>
      <description>&lt;p&gt;This is a guide where you will get hands-on experience with GitOps and Progressive Delivery using Kubernetes and Istio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is GitOps?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GitOps is a way to do Continuous Delivery, it works by using Git as a source of truth for declarative infrastructure and workloads. For Kubernetes this means using &lt;code&gt;git push&lt;/code&gt; instead of &lt;code&gt;kubectl apply/delete&lt;/code&gt; or &lt;code&gt;helm install/upgrade&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this workshop you'll be using GitHub to host the config repository and &lt;a href="https://fluxcd.io" rel="noopener noreferrer"&gt;Flux&lt;/a&gt; as the GitOps delivery solution.&lt;/p&gt;

&lt;p&gt;Flux is a multi-tenant Continuous Delivery solution for Kubernetes. Flux is constructed with the &lt;a href="https://fluxcd.io/docs/components/" rel="noopener noreferrer"&gt;GitOps Toolkit&lt;/a&gt;, a set of composable APIs and specialized tools for keeping Kubernetes clusters in sync with sources of configuration (like Git &amp;amp; Helm repositories), and automating updates to configuration when there is new code to deploy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who is Flux for?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Flux is made for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;cluster operators&lt;/em&gt; who automate provision and configuration of clusters&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;platform engineers&lt;/em&gt; who build continuous delivery for developer teams&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;app developers&lt;/em&gt; who rely on continuous delivery to get their code live&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What is Progressive Delivery?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Progressive Delivery is an umbrella term for advanced deployment patterns like canaries, feature flags and A/B testing. Progressive delivery techniques are used to reduce the risk of introducing a new software version in production&lt;br&gt;
by giving app developers and SRE teams a fine-grained control over the blast radius.&lt;/p&gt;

&lt;p&gt;In this workshop you'll be using &lt;a href="https://flagger.app" rel="noopener noreferrer"&gt;Flagger&lt;/a&gt; to drive Canary Releases and A/B Testing for your applications.&lt;/p&gt;

&lt;p&gt;Flagger automates the release process using Istio routing for traffic shifting and Prometheus metrics for canary analysis. It comes with a declarative model for decoupling the deployment of apps from the release process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffluxcd%2Fflagger%2Fmain%2Fdocs%2Fdiagrams%2Fflagger-gitops-istio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffluxcd%2Fflagger%2Fmain%2Fdocs%2Fdiagrams%2Fflagger-gitops-istio.png" alt="Progressive Delivery GitOps Pipeline"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You'll need a Kubernetes cluster &lt;strong&gt;v1.16&lt;/strong&gt; or newer with &lt;code&gt;LoadBalancer&lt;/code&gt; support. &lt;br&gt;
For testing purposes you can use Minikube with 2 CPUs and 4GB of memory. &lt;/p&gt;

&lt;p&gt;Install the &lt;code&gt;flux&lt;/code&gt; CLI with Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;fluxcd/tap/flux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Binaries for macOS AMD64/ARM64, Linux AMD64/ARM and Windows are available to download on the &lt;a href="https://github.com/fluxcd/flux2/releases" rel="noopener noreferrer"&gt;flux2 release page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Verify that your cluster satisfies the prerequisites with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flux check &lt;span class="nt"&gt;--pre&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;code&gt;jq&lt;/code&gt; and &lt;code&gt;yq&lt;/code&gt; with Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;jq yq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fork the &lt;a href="https://github.com/stefanprodan/gitops-istio" rel="noopener noreferrer"&gt;gitops-istio&lt;/a&gt; repository and clone it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/&amp;lt;YOUR-USERNAME&amp;gt;/gitops-istio
&lt;span class="nb"&gt;cd &lt;/span&gt;gitops-istio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cluster bootstrap
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;flux bootstrap&lt;/code&gt; command you can install Flux on a Kubernetes cluster and configure it to manage itself from a Git repository. If the Flux components are present on the cluster, the bootstrap command will perform an upgrade if needed.&lt;/p&gt;

&lt;p&gt;Bootstrap Flux by specifying your GitHub repository fork URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flux bootstrap git &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--author-email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;YOUR-EMAIL&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ssh://git@github.com/&amp;lt;YOUR-USERNAME&amp;gt;/gitops-istio &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;clusters/my-cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command requires ssh-agent, if you're using Windows see &lt;a href="https://fluxcd.io/docs/guides/installation/#github-and-github-enterprise" rel="noopener noreferrer"&gt;flux boostrap github&lt;/a&gt; documentation.&lt;/p&gt;

&lt;p&gt;At bootstrap, Flux generates an SSH key and prints the public key. In order to sync your cluster state with git you need to copy the public key and create a deploy key with write access on your GitHub repository. On GitHub go to &lt;em&gt;Settings &amp;gt; Deploy keys&lt;/em&gt; click on &lt;em&gt;Add deploy key&lt;/em&gt;, check &lt;em&gt;Allow write access&lt;/em&gt;, paste the Flux public key and click &lt;em&gt;Add key&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When Flux has access to your repository it will do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;installs the Istio operator&lt;/li&gt;
&lt;li&gt;waits for Istio control plane to be ready&lt;/li&gt;
&lt;li&gt;installs Flagger, Prometheus and Grafana&lt;/li&gt;
&lt;li&gt;creates the Istio public gateway&lt;/li&gt;
&lt;li&gt;creates the &lt;code&gt;prod&lt;/code&gt; namespace&lt;/li&gt;
&lt;li&gt;installs the demo apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When bootstrapping a cluster with Istio, it's important to define the install order. For the application pods to be injected with Istio sidecar, the Istio control plane must be up and running before the apps.&lt;/p&gt;

&lt;p&gt;With Flux v2 you can specify the execution order by defining dependencies between objects. For example, in &lt;a href="https://github.com/stefanprodan/gitops-istio/blob/main/clusters/my-cluster/apps.yaml" rel="noopener noreferrer"&gt;clusters/my-cluster/apps.yaml&lt;/a&gt; we tell Flux that the &lt;code&gt;apps&lt;/code&gt; reconciliation depends on the &lt;code&gt;istio-system&lt;/code&gt; one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kustomize.toolkit.fluxcd.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Kustomization&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flux-system&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30m0s&lt;/span&gt;
  &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;istio-system&lt;/span&gt;
  &lt;span class="na"&gt;sourceRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GitRepository&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flux-system&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./apps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch Flux installing Istio first, then the demo apps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;watch flux get kustomizations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can tail the Flux reconciliation logs with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flux logs &lt;span class="nt"&gt;--all-namespaces&lt;/span&gt; &lt;span class="nt"&gt;--follow&lt;/span&gt; &lt;span class="nt"&gt;--tail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Istio customizations and upgrades
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffluxcd%2Fhelm-operator-get-started%2Fmaster%2Fdiagrams%2Fflux-istio-operator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffluxcd%2Fhelm-operator-get-started%2Fmaster%2Fdiagrams%2Fflux-istio-operator.png" alt="Flux Istio Operator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can customize the Istio installation with the &lt;code&gt;IstioOperator&lt;/code&gt; resource located at &lt;a href="https://github.com/stefanprodan/gitops-istio/blob/main/istio/system/profile.yaml" rel="noopener noreferrer"&gt;istio/system/profile.yaml&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;install.istio.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;IstioOperator&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;istio-default&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;istio-system&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demo&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;pilot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;k8s&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10m&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100Mi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After modifying the Istio settings, you can push the change to git and Flux will apply it on the cluster. The Istio operator will reconfigure the Istio control plane according to your changes.&lt;/p&gt;

&lt;p&gt;When a new Istio version is available, the &lt;a href="https://github.com/stefanprodan/gitops-istio/blob/main/.github/workflows/update-istio.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;update-istio&lt;/code&gt; GitHub workflow&lt;/a&gt; will open a pull request with the manifest updates needed for upgrading Istio Operator. The new Istio version is tested on Kubernetes Kind by the &lt;a href="https://github.com/stefanprodan/gitops-istio/blob/main/.github/workflows/e2e.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;e2e&lt;/code&gt; workflow&lt;/a&gt; and when the PR is merged into the main branch, Flux will upgrade Istio on your cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application bootstrap
&lt;/h2&gt;

&lt;p&gt;When Flux syncs the Git repository with your cluster, it creates the frontend/backend deployment, HPA and a canary object. Flagger uses the canary definition to create a series of objects: Kubernetes deployments, ClusterIP services, Istio destination rules and virtual services. These objects expose the application on the mesh and drive the canary analysis and promotion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# applied by Flux&lt;/span&gt;
deployment.apps/frontend
horizontalpodautoscaler.autoscaling/frontend
canary.flagger.app/frontend

&lt;span class="c"&gt;# generated by Flagger&lt;/span&gt;
deployment.apps/frontend-primary
horizontalpodautoscaler.autoscaling/frontend-primary
service/frontend
service/frontend-canary
service/frontend-primary
destinationrule.networking.istio.io/frontend-canary
destinationrule.networking.istio.io/frontend-primary
virtualservice.networking.istio.io/frontend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if Flagger has successfully initialized the canaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl -n prod get canaries

NAME       STATUS        WEIGHT
backend    Initialized   0
frontend   Initialized   0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the &lt;code&gt;frontend-primary&lt;/code&gt; deployment comes online, &lt;br&gt;
Flagger will route all traffic to the primary pods and scale to zero the &lt;code&gt;frontend&lt;/code&gt; deployment.&lt;/p&gt;

&lt;p&gt;Find the Istio ingress gateway address with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system get svc istio-ingressgateway &lt;span class="nt"&gt;-ojson&lt;/span&gt; | jq .status.loadBalancer.ingress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open a browser and navigate to the ingress address, you'll see the frontend UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Canary releases
&lt;/h2&gt;

&lt;p&gt;Flagger implements a control loop that gradually shifts traffic to the canary while measuring key performance indicators like HTTP requests success rate, requests average duration and pod health. Based on analysis of the KPIs a canary is promoted or aborted, and the analysis result is published to Slack.&lt;/p&gt;

&lt;p&gt;A canary analysis is triggered by changes in any of the following objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployment PodSpec (container image, command, ports, env, etc)&lt;/li&gt;
&lt;li&gt;ConfigMaps and Secrets mounted as volumes or mapped to environment variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For workloads that are not receiving constant traffic Flagger can be configured with a webhook, that when called, will start a load test for the target workload. The canary configuration can be found at &lt;a href="https://github.com/stefanprodan/gitops-istio/blob/main/apps/backend/canary.yaml" rel="noopener noreferrer"&gt;apps/backend/canary.yaml&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffluxcd%2Fflagger%2Fmain%2Fdocs%2Fdiagrams%2Fflagger-canary-steps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffluxcd%2Fflagger%2Fmain%2Fdocs%2Fdiagrams%2Fflagger-canary-steps.png" alt="Flagger Canary Release"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pull the changes from GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To trigger a canary deployment for the backend app, bump the container image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yq e &lt;span class="s1"&gt;'.images[0].newTag="5.0.1"'&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; ./apps/backend/kustomization.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"backend 5.0.1"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that Flux can update the container image tag in an automated manner, for more details see &lt;a href="https://fluxcd.io/docs/guides/image-update/" rel="noopener noreferrer"&gt;Automate image updates to Git with Flux v2&lt;/a&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tell Flux to pull the changes or wait one minute for Flux to detect the changes on its own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flux reconcile &lt;span class="nb"&gt;source &lt;/span&gt;git flux-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch Flux reconciling your cluster to the latest commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;watch flux get kustomizations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a couple of seconds, Flagger detects that the deployment revision changed and starts a new rollout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; prod describe canary backend

Events:

New revision detected! Scaling up backend.prod
Starting canary analysis &lt;span class="k"&gt;for &lt;/span&gt;backend.prod
Pre-rollout check conformance-test passed
Advance backend.prod canary weight 5
...
Advance backend.prod canary weight 50
Copying backend.prod template spec to backend-primary.prod
Promotion completed! Scaling down backend.prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the analysis the canary’s progress can be monitored with Grafana. You can access the dashboard using port forwarding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system port-forward svc/flagger-grafana 3000:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Istio dashboard URL is &lt;br&gt;
&lt;code&gt;http://localhost:3000/d/flagger-istio/istio-canary?refresh=10s&amp;amp;orgId=1&amp;amp;var-namespace=prod&amp;amp;var-primary=backend-primary&amp;amp;var-canary=backend&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffluxcd%2Fflagger%2Fmain%2Fdocs%2Fscreens%2Fdemo-backend-dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffluxcd%2Fflagger%2Fmain%2Fdocs%2Fscreens%2Fdemo-backend-dashboard.png" alt="Canary Deployment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that if new changes are applied to the deployment during the canary analysis, Flagger will restart the analysis phase.&lt;/p&gt;
&lt;h2&gt;
  
  
  A/B testing
&lt;/h2&gt;

&lt;p&gt;Besides weighted routing, Flagger can be configured to route traffic to the canary based on HTTP match conditions. &lt;br&gt;
In an A/B testing scenario, you'll be using HTTP headers or cookies to target a certain segment of your users. &lt;br&gt;
This is particularly useful for frontend applications that require session affinity.&lt;/p&gt;

&lt;p&gt;You can enable A/B testing by specifying the HTTP match conditions and the number of iterations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;analysis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# schedule interval (default 60s)&lt;/span&gt;
    &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
    &lt;span class="c1"&gt;# max number of failed metric checks before rollback&lt;/span&gt;
    &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="c1"&gt;# total number of iterations&lt;/span&gt;
    &lt;span class="na"&gt;iterations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;
    &lt;span class="c1"&gt;# canary match condition&lt;/span&gt;
    &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;user-agent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.*Firefox.*"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^(.*?;)?(type=insider)(;.*)?$"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above configuration will run an analysis for two minutes targeting Firefox users and those that have an insider cookie. The frontend configuration can be found at &lt;a href="https://github.com/stefanprodan/gitops-istio/blob/main/apps/frontend/canary.yaml" rel="noopener noreferrer"&gt;apps/frontend/canary.yaml&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Trigger a deployment by updating the frontend container image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yq e &lt;span class="s1"&gt;'.images[0].newTag="5.0.1"'&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; ./apps/frontend/kustomization.yaml

git add &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"frontend 5.0.1"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
git push origin main

flux reconcile &lt;span class="nb"&gt;source &lt;/span&gt;git flux-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flagger detects that the deployment revision changed and starts the A/B testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system logs deploy/flagger &lt;span class="nt"&gt;-f&lt;/span&gt; | jq .msg

New revision detected! Scaling up frontend.prod
Waiting &lt;span class="k"&gt;for &lt;/span&gt;frontend.prod rollout to finish: 0 of 1 updated replicas are available
Pre-rollout check conformance-test passed
Advance frontend.prod canary iteration 1/10
...
Advance frontend.prod canary iteration 10/10
Copying frontend.prod template spec to frontend-primary.prod
Waiting &lt;span class="k"&gt;for &lt;/span&gt;frontend-primary.prod rollout to finish: 1 of 2 updated replicas are available
Promotion completed! Scaling down frontend.prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can monitor all canaries with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;watch kubectl get canaries &lt;span class="nt"&gt;--all-namespaces&lt;/span&gt;

NAMESPACE   NAME      STATUS        WEIGHT
prod        frontend  Progressing   100
prod        backend   Succeeded     0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rollback based on Istio metrics
&lt;/h2&gt;

&lt;p&gt;Flagger makes use of the metrics provided by Istio telemetry to validate the canary workload. The frontend app &lt;a href="https://github.com/stefanprodan/gitops-istio/blob/main/apps/frontend/canary.yaml" rel="noopener noreferrer"&gt;analysis&lt;/a&gt; defines two metric checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;error-rate&lt;/span&gt;
        &lt;span class="na"&gt;templateRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;error-rate&lt;/span&gt;
          &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;istio-system&lt;/span&gt;
        &lt;span class="na"&gt;thresholdRange&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latency&lt;/span&gt;
        &lt;span class="na"&gt;templateRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latency&lt;/span&gt;
          &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;istio-system&lt;/span&gt;
        &lt;span class="na"&gt;thresholdRange&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;
        &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Prometheus queries used for checking the error rate and latency are located at &lt;a href="https://github.com/stefanprodan/gitops-istio/blob/main/istio/gateway/flagger-metrics.yaml" rel="noopener noreferrer"&gt;flagger-metrics.yaml&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;During the canary analysis you can generate HTTP 500 errors and high latency to test Flagger's rollback.&lt;/p&gt;

&lt;p&gt;Generate HTTP 500 errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;watch curl &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s1"&gt;'type=insider'&lt;/span&gt; http://&amp;lt;INGRESS-IP&amp;gt;/status/500
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate latency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;watch curl &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s1"&gt;'type=insider'&lt;/span&gt; http://&amp;lt;INGRESS-IP&amp;gt;/delay/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the number of failed checks reaches the canary analysis threshold, the traffic is routed back to the primary, the canary is scaled to zero and the rollout is marked as failed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl -n istio-system logs deploy/flagger -f | jq .msg

New revision detected! Scaling up frontend.prod
Pre-rollout check conformance-test passed
Advance frontend.prod canary iteration 1/10
Halt frontend.prod advancement error-rate 31 &amp;gt; 1
Halt frontend.prod advancement latency 2000 &amp;gt; 500
...
Rolling back frontend.prod failed checks threshold reached 10
Canary failed! Scaling down frontend.prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can extend the analysis with custom metric checks targeting &lt;a href="https://docs.flagger.app/usage/metrics#prometheus" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt;, &lt;a href="https://docs.flagger.app/usage/metrics#datadog" rel="noopener noreferrer"&gt;Datadog&lt;/a&gt; and &lt;a href="https://docs.flagger.app/usage/metrics#amazon-cloudwatch" rel="noopener noreferrer"&gt;Amazon CloudWatch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For configuring alerting of the canary analysis for Slack, MS Teams, Discord or Rocket see the &lt;a href="https://docs.flagger.app/usage/alerting#canary-configuration" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Help
&lt;/h2&gt;

&lt;p&gt;If you have any questions about progressive delivery:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invite yourself to the &lt;a href="https://slack.cncf.io/" rel="noopener noreferrer"&gt;CNCF community slack&lt;/a&gt;
and join the &lt;a href="https://cloud-native.slack.com/messages/flux/" rel="noopener noreferrer"&gt;#flux&lt;/a&gt; and &lt;a href="https://cloud-native.slack.com/messages/flagger/" rel="noopener noreferrer"&gt;#flagger&lt;/a&gt; channels.&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href="https://fluxcd.io/community/#talks" rel="noopener noreferrer"&gt;Flux talks section&lt;/a&gt; and to see a list of online talks, hands-on training and meetups.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your feedback is always welcome!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>testing</category>
      <category>kubernetes</category>
      <category>istio</category>
    </item>
  </channel>
</rss>
