From c9c97c379ddcb7be537aec9c8e609c133ab8aec7 Mon Sep 17 00:00:00 2001 From: weaveworksbot Date: Thu, 20 Aug 2020 06:16:09 +0000 Subject: [PATCH] Publish website --- 404.html | 6 +++--- assets/js/{10.d04c7ada.js => 10.bf6f38d4.js} | 2 +- assets/js/{11.ab251275.js => 11.3af38cfe.js} | 2 +- assets/js/{13.6b55cb59.js => 13.9104349a.js} | 2 +- assets/js/{14.affa49a6.js => 14.a4f3d810.js} | 2 +- assets/js/{23.ec1dec63.js => 23.b3dcc355.js} | 2 +- assets/js/{24.721d8c4e.js => 24.4f54d289.js} | 2 +- assets/js/{29.17c547e6.js => 29.ce4011f4.js} | 2 +- assets/js/{30.38bd809e.js => 30.edda19d9.js} | 2 +- assets/js/5.0c32bdf9.js | 1 + assets/js/5.f0e04ff6.js | 1 - assets/js/{app.67d16e10.js => app.9b46ae46.js} | 4 ++-- dev/dev-guide.html | 4 ++-- dev/index.html | 4 ++-- dev/release-guide.html | 4 ++-- dev/upgrade-guide.html | 4 ++-- index.html | 9 +++++---- install/flagger-install-on-eks-appmesh.html | 4 ++-- install/flagger-install-on-google-cloud.html | 4 ++-- install/flagger-install-on-kubernetes.html | 4 ++-- install/index.html | 4 ++-- intro/faq.html | 4 ++-- intro/index.html | 4 ++-- tutorials/appmesh-progressive-delivery.html | 4 ++-- tutorials/canary-helm-gitops.html | 4 ++-- tutorials/contour-progressive-delivery.html | 4 ++-- tutorials/crossover-progressive-delivery.html | 4 ++-- tutorials/flagger-smi-istio.html | 4 ++-- tutorials/gloo-progressive-delivery.html | 4 ++-- tutorials/index.html | 4 ++-- tutorials/istio-ab-testing.html | 4 ++-- tutorials/istio-progressive-delivery.html | 4 ++-- tutorials/kubernetes-blue-green.html | 4 ++-- tutorials/linkerd-progressive-delivery.html | 4 ++-- tutorials/nginx-progressive-delivery.html | 4 ++-- tutorials/zero-downtime-deployments.html | 4 ++-- usage/alerting.html | 4 ++-- usage/deployment-strategies.html | 4 ++-- usage/how-it-works.html | 4 ++-- usage/index.html | 4 ++-- usage/metrics.html | 4 ++-- usage/monitoring.html | 4 ++-- usage/webhooks.html | 4 ++-- 43 files changed, 79 insertions(+), 78 deletions(-) rename assets/js/{10.d04c7ada.js => 10.bf6f38d4.js} (79%) rename assets/js/{11.ab251275.js => 11.3af38cfe.js} (99%) rename assets/js/{13.6b55cb59.js => 13.9104349a.js} (99%) rename assets/js/{14.affa49a6.js => 14.a4f3d810.js} (98%) rename assets/js/{23.ec1dec63.js => 23.b3dcc355.js} (99%) rename assets/js/{24.721d8c4e.js => 24.4f54d289.js} (99%) rename assets/js/{29.17c547e6.js => 29.ce4011f4.js} (79%) rename assets/js/{30.38bd809e.js => 30.edda19d9.js} (99%) create mode 100644 assets/js/5.0c32bdf9.js delete mode 100644 assets/js/5.f0e04ff6.js rename assets/js/{app.67d16e10.js => app.9b46ae46.js} (86%) diff --git a/404.html b/404.html index e730f266..4fbd0a98 100644 --- a/404.html +++ b/404.html @@ -13,11 +13,11 @@ - + -

404

There's nothing here.
Take me home.
- +

404

Looks like we've got some broken links.
Take me home.
+ diff --git a/assets/js/10.d04c7ada.js b/assets/js/10.bf6f38d4.js similarity index 79% rename from assets/js/10.d04c7ada.js rename to assets/js/10.bf6f38d4.js index 1e49516c..336f8d72 100644 --- a/assets/js/10.d04c7ada.js +++ b/assets/js/10.bf6f38d4.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{271:function(t,e,n){"use strict";n.r(e);var s=n(37),l=Object(s.a)({},function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})},[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{270:function(t,e,n){"use strict";n.r(e);var s=n(37),l=Object(s.a)({},function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})},[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/11.ab251275.js b/assets/js/11.3af38cfe.js similarity index 99% rename from assets/js/11.ab251275.js rename to assets/js/11.3af38cfe.js index 86643c3d..d5503238 100644 --- a/assets/js/11.ab251275.js +++ b/assets/js/11.3af38cfe.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{270:function(a,e,s){"use strict";s.r(e);var t=s(37),r=Object(t.a)({},function(){var a=this,e=a.$createElement,s=a._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[s("h1",{attrs:{id:"flagger-install-on-eks-app-mesh"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#flagger-install-on-eks-app-mesh","aria-hidden":"true"}},[a._v("#")]),a._v(" Flagger Install on EKS App Mesh")]),a._v(" "),s("p",[a._v("This guide walks you through setting up Flagger and AWS App Mesh on EKS.")]),a._v(" "),s("h2",{attrs:{id:"app-mesh"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#app-mesh","aria-hidden":"true"}},[a._v("#")]),a._v(" App Mesh")]),a._v(" "),s("p",[a._v("The App Mesh integration with EKS is made out of the following components:")]),a._v(" "),s("ul",[s("li",[a._v("Kubernetes custom resources\n"),s("ul",[s("li",[s("code",[a._v("mesh.appmesh.k8s.aws")]),a._v(" defines a logical boundary for network traffic between the services")]),a._v(" "),s("li",[s("code",[a._v("virtualnode.appmesh.k8s.aws")]),a._v(" defines a logical pointer to a Kubernetes workload")]),a._v(" "),s("li",[s("code",[a._v("virtualservice.appmesh.k8s.aws")]),a._v(" defines the routing rules for a workload inside the mesh")])])]),a._v(" "),s("li",[a._v("CRD controller - keeps the custom resources in sync with the App Mesh control plane")]),a._v(" "),s("li",[a._v("Admission controller - injects the Envoy sidecar and assigns Kubernetes pods to App Mesh virtual nodes")]),a._v(" "),s("li",[a._v("Telemetry service - Prometheus instance that collects and stores Envoy's metrics")])]),a._v(" "),s("h2",{attrs:{id:"create-a-kubernetes-cluster"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#create-a-kubernetes-cluster","aria-hidden":"true"}},[a._v("#")]),a._v(" Create a Kubernetes cluster")]),a._v(" "),s("p",[a._v("In order to create an EKS cluster you can use "),s("a",{attrs:{href:"https://eksctl.io",target:"_blank",rel:"noopener noreferrer"}},[a._v("eksctl"),s("OutboundLink")],1),a._v(". Eksctl is an open source command-line utility made by Weaveworks in collaboration with Amazon.")]),a._v(" "),s("p",[a._v("On MacOS you can install eksctl with Homebrew:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("brew tap weaveworks/tap\nbrew "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("install")]),a._v(" weaveworks/tap/eksctl\n")])])]),s("p",[a._v("Create an EKS cluster:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("eksctl create cluster --name"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--region"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("us-west-2 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--nodes "),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("3")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--node-volume-size"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("120")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--appmesh-access\n")])])]),s("p",[a._v("The above command will create a two nodes cluster with App Mesh "),s("a",{attrs:{href:"https://docs.aws.amazon.com/app-mesh/latest/userguide/MESH_IAM_user_policies.html",target:"_blank",rel:"noopener noreferrer"}},[a._v("IAM policy"),s("OutboundLink")],1),a._v(" attached to the EKS node instance role.")]),a._v(" "),s("p",[a._v("Verify the install with:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl get nodes\n")])])]),s("h2",{attrs:{id:"install-helm"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#install-helm","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Helm")]),a._v(" "),s("p",[a._v("Install the "),s("a",{attrs:{href:"https://docs.helm.sh/using_helm/#installing-helm",target:"_blank",rel:"noopener noreferrer"}},[a._v("Helm"),s("OutboundLink")],1),a._v(" command-line tool:")]),a._v(" "),s("div",{staticClass:"language-text extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("brew install kubernetes-helm\n")])])]),s("p",[a._v("Create a service account and a cluster role binding for Tiller:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl -n kube-system create sa tiller\n\nkubectl create clusterrolebinding tiller-cluster-rule "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--clusterrole"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("cluster-admin "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--serviceaccount"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("kube-system:tiller\n")])])]),s("p",[a._v("Deploy Tiller in the "),s("code",[a._v("kube-system")]),a._v(" namespace:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm init --service-account tiller\n")])])]),s("p",[a._v("You should consider using SSL between Helm and Tiller, for more information on securing your Helm installation see "),s("a",{attrs:{href:"https://docs.helm.sh/using_helm/#securing-your-helm-installation",target:"_blank",rel:"noopener noreferrer"}},[a._v("docs.helm.sh"),s("OutboundLink")],1),a._v(".")]),a._v(" "),s("h2",{attrs:{id:"enable-horizontal-pod-auto-scaling"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#enable-horizontal-pod-auto-scaling","aria-hidden":"true"}},[a._v("#")]),a._v(" Enable horizontal pod auto-scaling")]),a._v(" "),s("p",[a._v("Install the Horizontal Pod Autoscaler (HPA) metrics provider:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i metrics-server stable/metrics-server "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace kube-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("--kubelet-preferred-address-types"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("InternalIP\n")])])]),s("p",[a._v("After a minute, the metrics API should report CPU and memory usage for pods. You can very the metrics API with:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl -n kube-system "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("top")]),a._v(" pods\n")])])]),s("h2",{attrs:{id:"install-the-app-mesh-components"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#install-the-app-mesh-components","aria-hidden":"true"}},[a._v("#")]),a._v(" Install the App Mesh components")]),a._v(" "),s("p",[a._v("Create the "),s("code",[a._v("appmesh-system")]),a._v(" namespace:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl create ns appmesh-system\n")])])]),s("p",[a._v("Apply the App Mesh CRDs:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl apply -k github.com/aws/eks-charts/stable/appmesh-controller//crds\n")])])]),s("p",[a._v("Add the EKS repository to Helm:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm repo "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("add")]),a._v(" eks https://aws.github.io/eks-charts\n")])])]),s("p",[a._v("Install the App Mesh CRD controller:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i appmesh-controller eks/appmesh-controller "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--wait --namespace appmesh-system\n")])])]),s("p",[a._v("Install the App Mesh admission controller and create a mesh called "),s("code",[a._v("global")]),a._v(":")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i appmesh-inject eks/appmesh-inject "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--wait --namespace appmesh-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set mesh.create"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("true "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set mesh.name"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("global\n")])])]),s("p",[a._v("Verify that the global mesh is active:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl describe mesh\n\nStatus:\n Mesh Condition:\n Status: True\n Type: MeshActive\n")])])]),s("p",[a._v("In order to collect the App Mesh metrics that Flagger needs to run the canary analysis, you'll need to setup a Prometheus instance to scrape the Envoy sidecars.")]),a._v(" "),s("p",[a._v("Install the App Mesh Prometheus:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i appmesh-prometheus eks/appmesh-prometheus "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--wait --namespace appmesh-system\n")])])]),s("h2",{attrs:{id:"install-flagger-and-grafana"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#install-flagger-and-grafana","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Flagger and Grafana")]),a._v(" "),s("p",[a._v("Add Flagger Helm repository:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm repo "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("add")]),a._v(" flagger https://flagger.app\n")])])]),s("p",[a._v("Install Flagger's Canary CRD:")]),a._v(" "),s("div",{staticClass:"language-yaml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-yaml"}},[s("code",[a._v("kubectl apply "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("f https"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("//raw.githubusercontent.com/weaveworks/flagger/master/artifacts/flagger/crd.yaml\n")])])]),s("p",[a._v("Deploy Flagger in the "),s("em",[s("strong",[a._v("appmesh-system")])]),a._v(" namespace:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i flagger flagger/flagger "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),s("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),s("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://appmesh-prometheus:9090\n")])])]),s("p",[a._v("You can enable Slack or MS Teams notifications with:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i flagger flagger/flagger "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--reuse-values "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.url"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.channel"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("general "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.user"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("flagger\n")])])]),s("p",[a._v("Flagger comes with a Grafana dashboard made for monitoring the canary analysis. Deploy Grafana in the "),s("em",[s("strong",[a._v("appmesh-system")])]),a._v(" namespace:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i flagger-grafana flagger/grafana "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),s("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("url")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://appmesh-prometheus:9090\n")])])]),s("p",[a._v("You can access Grafana using port forwarding:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl -n appmesh-system port-forward svc/flagger-grafana "),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("3000")]),a._v(":80\n")])])]),s("p",[a._v("Now that you have Flagger running you can try the "),s("a",{attrs:{href:"https://docs.flagger.app/usage/appmesh-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[a._v("App Mesh canary deployments tutorial"),s("OutboundLink")],1),a._v(".")])])},[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{271:function(a,e,s){"use strict";s.r(e);var t=s(37),r=Object(t.a)({},function(){var a=this,e=a.$createElement,s=a._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[s("h1",{attrs:{id:"flagger-install-on-eks-app-mesh"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#flagger-install-on-eks-app-mesh","aria-hidden":"true"}},[a._v("#")]),a._v(" Flagger Install on EKS App Mesh")]),a._v(" "),s("p",[a._v("This guide walks you through setting up Flagger and AWS App Mesh on EKS.")]),a._v(" "),s("h2",{attrs:{id:"app-mesh"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#app-mesh","aria-hidden":"true"}},[a._v("#")]),a._v(" App Mesh")]),a._v(" "),s("p",[a._v("The App Mesh integration with EKS is made out of the following components:")]),a._v(" "),s("ul",[s("li",[a._v("Kubernetes custom resources\n"),s("ul",[s("li",[s("code",[a._v("mesh.appmesh.k8s.aws")]),a._v(" defines a logical boundary for network traffic between the services")]),a._v(" "),s("li",[s("code",[a._v("virtualnode.appmesh.k8s.aws")]),a._v(" defines a logical pointer to a Kubernetes workload")]),a._v(" "),s("li",[s("code",[a._v("virtualservice.appmesh.k8s.aws")]),a._v(" defines the routing rules for a workload inside the mesh")])])]),a._v(" "),s("li",[a._v("CRD controller - keeps the custom resources in sync with the App Mesh control plane")]),a._v(" "),s("li",[a._v("Admission controller - injects the Envoy sidecar and assigns Kubernetes pods to App Mesh virtual nodes")]),a._v(" "),s("li",[a._v("Telemetry service - Prometheus instance that collects and stores Envoy's metrics")])]),a._v(" "),s("h2",{attrs:{id:"create-a-kubernetes-cluster"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#create-a-kubernetes-cluster","aria-hidden":"true"}},[a._v("#")]),a._v(" Create a Kubernetes cluster")]),a._v(" "),s("p",[a._v("In order to create an EKS cluster you can use "),s("a",{attrs:{href:"https://eksctl.io",target:"_blank",rel:"noopener noreferrer"}},[a._v("eksctl"),s("OutboundLink")],1),a._v(". Eksctl is an open source command-line utility made by Weaveworks in collaboration with Amazon.")]),a._v(" "),s("p",[a._v("On MacOS you can install eksctl with Homebrew:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("brew tap weaveworks/tap\nbrew "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("install")]),a._v(" weaveworks/tap/eksctl\n")])])]),s("p",[a._v("Create an EKS cluster:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("eksctl create cluster --name"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--region"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("us-west-2 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--nodes "),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("3")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--node-volume-size"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("120")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--appmesh-access\n")])])]),s("p",[a._v("The above command will create a two nodes cluster with App Mesh "),s("a",{attrs:{href:"https://docs.aws.amazon.com/app-mesh/latest/userguide/MESH_IAM_user_policies.html",target:"_blank",rel:"noopener noreferrer"}},[a._v("IAM policy"),s("OutboundLink")],1),a._v(" attached to the EKS node instance role.")]),a._v(" "),s("p",[a._v("Verify the install with:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl get nodes\n")])])]),s("h2",{attrs:{id:"install-helm"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#install-helm","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Helm")]),a._v(" "),s("p",[a._v("Install the "),s("a",{attrs:{href:"https://docs.helm.sh/using_helm/#installing-helm",target:"_blank",rel:"noopener noreferrer"}},[a._v("Helm"),s("OutboundLink")],1),a._v(" command-line tool:")]),a._v(" "),s("div",{staticClass:"language-text extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("brew install kubernetes-helm\n")])])]),s("p",[a._v("Create a service account and a cluster role binding for Tiller:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl -n kube-system create sa tiller\n\nkubectl create clusterrolebinding tiller-cluster-rule "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--clusterrole"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("cluster-admin "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--serviceaccount"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("kube-system:tiller\n")])])]),s("p",[a._v("Deploy Tiller in the "),s("code",[a._v("kube-system")]),a._v(" namespace:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm init --service-account tiller\n")])])]),s("p",[a._v("You should consider using SSL between Helm and Tiller, for more information on securing your Helm installation see "),s("a",{attrs:{href:"https://docs.helm.sh/using_helm/#securing-your-helm-installation",target:"_blank",rel:"noopener noreferrer"}},[a._v("docs.helm.sh"),s("OutboundLink")],1),a._v(".")]),a._v(" "),s("h2",{attrs:{id:"enable-horizontal-pod-auto-scaling"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#enable-horizontal-pod-auto-scaling","aria-hidden":"true"}},[a._v("#")]),a._v(" Enable horizontal pod auto-scaling")]),a._v(" "),s("p",[a._v("Install the Horizontal Pod Autoscaler (HPA) metrics provider:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i metrics-server stable/metrics-server "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace kube-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("--kubelet-preferred-address-types"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("InternalIP\n")])])]),s("p",[a._v("After a minute, the metrics API should report CPU and memory usage for pods. You can very the metrics API with:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl -n kube-system "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("top")]),a._v(" pods\n")])])]),s("h2",{attrs:{id:"install-the-app-mesh-components"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#install-the-app-mesh-components","aria-hidden":"true"}},[a._v("#")]),a._v(" Install the App Mesh components")]),a._v(" "),s("p",[a._v("Create the "),s("code",[a._v("appmesh-system")]),a._v(" namespace:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl create ns appmesh-system\n")])])]),s("p",[a._v("Apply the App Mesh CRDs:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl apply -k github.com/aws/eks-charts/stable/appmesh-controller//crds\n")])])]),s("p",[a._v("Add the EKS repository to Helm:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm repo "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("add")]),a._v(" eks https://aws.github.io/eks-charts\n")])])]),s("p",[a._v("Install the App Mesh CRD controller:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i appmesh-controller eks/appmesh-controller "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--wait --namespace appmesh-system\n")])])]),s("p",[a._v("Install the App Mesh admission controller and create a mesh called "),s("code",[a._v("global")]),a._v(":")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i appmesh-inject eks/appmesh-inject "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--wait --namespace appmesh-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set mesh.create"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("true "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set mesh.name"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("global\n")])])]),s("p",[a._v("Verify that the global mesh is active:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl describe mesh\n\nStatus:\n Mesh Condition:\n Status: True\n Type: MeshActive\n")])])]),s("p",[a._v("In order to collect the App Mesh metrics that Flagger needs to run the canary analysis, you'll need to setup a Prometheus instance to scrape the Envoy sidecars.")]),a._v(" "),s("p",[a._v("Install the App Mesh Prometheus:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i appmesh-prometheus eks/appmesh-prometheus "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--wait --namespace appmesh-system\n")])])]),s("h2",{attrs:{id:"install-flagger-and-grafana"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#install-flagger-and-grafana","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Flagger and Grafana")]),a._v(" "),s("p",[a._v("Add Flagger Helm repository:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm repo "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("add")]),a._v(" flagger https://flagger.app\n")])])]),s("p",[a._v("Install Flagger's Canary CRD:")]),a._v(" "),s("div",{staticClass:"language-yaml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-yaml"}},[s("code",[a._v("kubectl apply "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("f https"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("//raw.githubusercontent.com/weaveworks/flagger/master/artifacts/flagger/crd.yaml\n")])])]),s("p",[a._v("Deploy Flagger in the "),s("em",[s("strong",[a._v("appmesh-system")])]),a._v(" namespace:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i flagger flagger/flagger "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),s("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),s("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://appmesh-prometheus:9090\n")])])]),s("p",[a._v("You can enable Slack or MS Teams notifications with:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i flagger flagger/flagger "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--reuse-values "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.url"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.channel"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("general "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.user"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("flagger\n")])])]),s("p",[a._v("Flagger comes with a Grafana dashboard made for monitoring the canary analysis. Deploy Grafana in the "),s("em",[s("strong",[a._v("appmesh-system")])]),a._v(" namespace:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("helm upgrade -i flagger-grafana flagger/grafana "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh-system "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),s("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("url")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://appmesh-prometheus:9090\n")])])]),s("p",[a._v("You can access Grafana using port forwarding:")]),a._v(" "),s("div",{staticClass:"language-bash extra-class"},[s("pre",{pre:!0,attrs:{class:"language-bash"}},[s("code",[a._v("kubectl -n appmesh-system port-forward svc/flagger-grafana "),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("3000")]),a._v(":80\n")])])]),s("p",[a._v("Now that you have Flagger running you can try the "),s("a",{attrs:{href:"https://docs.flagger.app/usage/appmesh-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[a._v("App Mesh canary deployments tutorial"),s("OutboundLink")],1),a._v(".")])])},[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/13.6b55cb59.js b/assets/js/13.9104349a.js similarity index 99% rename from assets/js/13.6b55cb59.js rename to assets/js/13.9104349a.js index 553f44ec..e3f22559 100644 --- a/assets/js/13.6b55cb59.js +++ b/assets/js/13.9104349a.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{274:function(a,e,t){"use strict";t.r(e);var s=t(37),r=Object(s.a)({},function(){var a=this,e=a.$createElement,t=a._self._c||e;return t("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[t("h1",{attrs:{id:"flagger-install-on-kubernetes"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#flagger-install-on-kubernetes","aria-hidden":"true"}},[a._v("#")]),a._v(" Flagger Install on Kubernetes")]),a._v(" "),t("p",[a._v("This guide walks you through setting up Flagger on a Kubernetes cluster with Helm v3 or Kustomize.")]),a._v(" "),t("h2",{attrs:{id:"prerequisites"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites","aria-hidden":"true"}},[a._v("#")]),a._v(" Prerequisites")]),a._v(" "),t("p",[a._v("Flagger requires a Kubernetes cluster "),t("strong",[a._v("v1.11")]),a._v(" or newer.")]),a._v(" "),t("h2",{attrs:{id:"install-flagger-with-helm"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#install-flagger-with-helm","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Flagger with Helm")]),a._v(" "),t("p",[a._v("Add Flagger Helm repository:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm repo "),t("span",{pre:!0,attrs:{class:"token function"}},[a._v("add")]),a._v(" flagger https://flagger.app\n")])])]),t("p",[a._v("Install Flagger's Canary CRD:")]),a._v(" "),t("div",{staticClass:"language-yaml extra-class"},[t("pre",{pre:!0,attrs:{class:"language-yaml"}},[t("code",[a._v("kubectl apply "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("f https"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("//raw.githubusercontent.com/weaveworks/flagger/master/artifacts/flagger/crd.yaml\n")])])]),t("p",[a._v("Deploy Flagger for Istio:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://prometheus:9090\n")])])]),t("p",[a._v("Note that Flagger depends on Istio telemetry and Prometheus, if you're installing Istio with istioctl\nthen you should be using the "),t("a",{attrs:{href:"https://istio.io/docs/setup/additional-setup/config-profiles/",target:"_blank",rel:"noopener noreferrer"}},[a._v("default profile"),t("OutboundLink")],1),a._v(".")]),a._v(" "),t("p",[a._v("For Istio multi-cluster shared control plane you can install Flagger\non each remote cluster and set the Istio control plane host cluster kubeconfig:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://istio-cluster-prometheus:9090 "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set istio.kubeconfig.secretName"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-kubeconfig "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set istio.kubeconfig.key"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("kubeconfig\n")])])]),t("p",[a._v("Note that the Istio kubeconfig must be stored in a Kubernetes secret with a data key named "),t("code",[a._v("kubeconfig")]),a._v(".\nFor more details on how to configure Istio multi-cluster credentials\nread the "),t("a",{attrs:{href:"https://istio.io/docs/setup/install/multicluster/shared-vpn/#credentials",target:"_blank",rel:"noopener noreferrer"}},[a._v("Istio docs"),t("OutboundLink")],1),a._v(".")]),a._v(" "),t("p",[a._v("Deploy Flagger for Linkerd:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("linkerd "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("linkerd "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://linkerd-prometheus:9090\n")])])]),t("p",[a._v("Deploy Flagger for App Mesh:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://appmesh-prometheus:9090\n")])])]),t("p",[a._v("You can install Flagger in any namespace as long as it can talk to the Prometheus service on port 9090.")]),a._v(" "),t("p",[a._v("For ingress controllers, the install instructions are:")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/contour-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[a._v("Contour"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/gloo-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[a._v("Gloo"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/nginx-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[a._v("NGINX"),t("OutboundLink")],1)])]),a._v(" "),t("p",[a._v("Enable "),t("strong",[a._v("Slack")]),a._v(" notifications:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.url"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.channel"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("general "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.user"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("flagger\n")])])]),t("p",[a._v("Enable "),t("strong",[a._v("Microsoft Teams")]),a._v(" notifications:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set msteams.url"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK\n")])])]),t("p",[a._v("You can use the helm template command and apply the generated yaml with kubectl:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# generate")]),a._v("\nhelm fetch --untar --untardir "),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v(".")]),a._v(" flagger/flagger "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("&&")]),a._v("\nhelm template flagger ./flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://prometheus.istio-system:9090 "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" flagger.yaml\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# apply")]),a._v("\nkubectl apply -f flagger.yaml\n")])])]),t("p",[a._v("To uninstall the Flagger release with Helm run:")]),a._v(" "),t("div",{staticClass:"language-text extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[a._v("helm delete flagger\n")])])]),t("p",[a._v("The command removes all the Kubernetes components associated with the chart and deletes the release.")]),a._v(" "),t("blockquote",[t("p",[t("strong",[a._v("Note")]),a._v(" that on uninstall the Canary CRD will not be removed. Deleting the CRD will make Kubernetes\nremove all the objects owned by Flagger like Istio virtual services, Kubernetes deployments and ClusterIP services.")])]),a._v(" "),t("p",[a._v("If you want to remove all the objects created by Flagger you have delete the Canary CRD with kubectl:")]),a._v(" "),t("div",{staticClass:"language-text extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[a._v("kubectl delete crd canaries.flagger.app\n")])])]),t("h2",{attrs:{id:"install-grafana-with-helm"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#install-grafana-with-helm","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Grafana with Helm")]),a._v(" "),t("p",[a._v("Flagger comes with a Grafana dashboard made for monitoring the canary analysis.")]),a._v(" "),t("p",[a._v("Deploy Grafana in the "),t("em",[t("strong",[a._v("istio-system")])]),a._v(" namespace:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger-grafana flagger/grafana "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("url")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://prometheus.istio-system:9090 "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("user")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("admin "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("password")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("change-me\n")])])]),t("p",[a._v("Or use helm template command and apply the generated yaml with kubectl:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# generate")]),a._v("\nhelm fetch --untar --untardir "),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v(".")]),a._v(" flagger/grafana "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("&&")]),a._v("\nhelm template flagger-grafana ./grafana "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" flagger-grafana.yaml\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# apply")]),a._v("\nkubectl apply -f flagger-grafana.yaml\n")])])]),t("p",[a._v("You can access Grafana using port forwarding:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl -n istio-system port-forward svc/flagger-grafana "),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("3000")]),a._v(":80\n")])])]),t("h2",{attrs:{id:"install-flagger-with-kustomize"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#install-flagger-with-kustomize","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Flagger with Kustomize")]),a._v(" "),t("p",[a._v("As an alternative to Helm, Flagger can be installed with Kustomize.")]),a._v(" "),t("p",[t("strong",[a._v("Service mesh specific installers")])]),a._v(" "),t("p",[a._v("Install Flagger for Istio:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/istio\n")])])]),t("p",[a._v("This deploys Flagger in the "),t("code",[a._v("istio-system")]),a._v(" namespace and sets the metrics server URL to Istio's Prometheus instance.")]),a._v(" "),t("p",[a._v("Note that you'll need kubectl 1.14 to run the above the command or you can download\nthe "),t("a",{attrs:{href:"https://github.com/kubernetes-sigs/kustomize/releases",target:"_blank",rel:"noopener noreferrer"}},[a._v("kustomize binary"),t("OutboundLink")],1),a._v(" and run:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kustomize build github.com/weaveworks/flagger//kustomize/istio "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("|")]),a._v(" kubectl apply -f -\n")])])]),t("p",[a._v("Install Flagger for AWS App Mesh:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/appmesh\n")])])]),t("p",[a._v("This deploys Flagger and sets the metrics server URL to App Mesh's Prometheus instance.")]),a._v(" "),t("p",[a._v("Install Flagger for Linkerd:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/linkerd\n")])])]),t("p",[a._v("This deploys Flagger in the "),t("code",[a._v("linkerd")]),a._v(" namespace and sets the metrics server URL to Linkerd's Prometheus instance.")]),a._v(" "),t("p",[a._v("If you want to install a specific Flagger release, add the version number to the URL:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/linkerd?ref"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("0.18")]),a._v(".0\n")])])]),t("p",[t("strong",[a._v("Generic installer")])]),a._v(" "),t("p",[a._v("Install Flagger and Prometheus:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/kubernetes\n")])])]),t("p",[a._v("This deploys Flagger and Prometheus in the "),t("code",[a._v("flagger-system")]),a._v(" namespace, sets the metrics server URL\nto "),t("code",[a._v("http://flagger-prometheus.flagger-system:9090")]),a._v(" and the mesh provider to "),t("code",[a._v("kubernetes")]),a._v(".")]),a._v(" "),t("p",[a._v("The Prometheus instance has a two hours data retention and is configured to scrape all pods in your cluster\nthat have the "),t("code",[a._v('prometheus.io/scrape: "true"')]),a._v(" annotation.")]),a._v(" "),t("p",[a._v("To target a different provider you can specify it in the canary custom resource:")]),a._v(" "),t("div",{staticClass:"language-yaml extra-class"},[t("pre",{pre:!0,attrs:{class:"language-yaml"}},[t("code",[t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger.app/v1beta1\n"),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Canary\n"),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" app\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" test\n"),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("spec")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# can be: kubernetes, istio, linkerd, appmesh, nginx, gloo")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# use the kubernetes provider for Blue/Green style deployments")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("provider")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" nginx\n")])])]),t("p",[t("strong",[a._v("Customized installer")])]),a._v(" "),t("p",[a._v("Create a kustomization file using flagger as base:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[a._v("cat")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" kustomization.yaml "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("<<")]),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("EOF\nnamespace: istio-system\nbases:\n - github.com/weaveworks/flagger/kustomize/base/flagger\npatchesStrategicMerge:\n - patch.yaml\nEOF")]),a._v("\n")])])]),t("p",[a._v("Create a patch and enable Slack notifications by setting the slack channel and hook URL:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[a._v("cat")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" patch.yaml "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("<<")]),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("EOF\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: flagger\nspec:\n template:\n spec:\n containers:\n - name: flagger\n args:\n - -mesh-provider=istio\n - -metrics-server=http://prometheus.istio-system:9090\n - -slack-user=flagger\n - -slack-channel=alerts\n - -slack-url=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK\nEOF")]),a._v("\n")])])]),t("p",[a._v("Install Flagger with Slack:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k "),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v(".")]),a._v("\n")])])]),t("p",[a._v("If you want to use MS Teams instead of Slack, replace "),t("code",[a._v("-slack-url")]),a._v(" with "),t("code",[a._v("-msteams-url")]),a._v(" and set the webhook address\nto "),t("code",[a._v("https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK")]),a._v(".")])])},[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{273:function(a,e,t){"use strict";t.r(e);var s=t(37),r=Object(s.a)({},function(){var a=this,e=a.$createElement,t=a._self._c||e;return t("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[t("h1",{attrs:{id:"flagger-install-on-kubernetes"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#flagger-install-on-kubernetes","aria-hidden":"true"}},[a._v("#")]),a._v(" Flagger Install on Kubernetes")]),a._v(" "),t("p",[a._v("This guide walks you through setting up Flagger on a Kubernetes cluster with Helm v3 or Kustomize.")]),a._v(" "),t("h2",{attrs:{id:"prerequisites"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites","aria-hidden":"true"}},[a._v("#")]),a._v(" Prerequisites")]),a._v(" "),t("p",[a._v("Flagger requires a Kubernetes cluster "),t("strong",[a._v("v1.11")]),a._v(" or newer.")]),a._v(" "),t("h2",{attrs:{id:"install-flagger-with-helm"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#install-flagger-with-helm","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Flagger with Helm")]),a._v(" "),t("p",[a._v("Add Flagger Helm repository:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm repo "),t("span",{pre:!0,attrs:{class:"token function"}},[a._v("add")]),a._v(" flagger https://flagger.app\n")])])]),t("p",[a._v("Install Flagger's Canary CRD:")]),a._v(" "),t("div",{staticClass:"language-yaml extra-class"},[t("pre",{pre:!0,attrs:{class:"language-yaml"}},[t("code",[a._v("kubectl apply "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("f https"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("//raw.githubusercontent.com/weaveworks/flagger/master/artifacts/flagger/crd.yaml\n")])])]),t("p",[a._v("Deploy Flagger for Istio:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://prometheus:9090\n")])])]),t("p",[a._v("Note that Flagger depends on Istio telemetry and Prometheus, if you're installing Istio with istioctl\nthen you should be using the "),t("a",{attrs:{href:"https://istio.io/docs/setup/additional-setup/config-profiles/",target:"_blank",rel:"noopener noreferrer"}},[a._v("default profile"),t("OutboundLink")],1),a._v(".")]),a._v(" "),t("p",[a._v("For Istio multi-cluster shared control plane you can install Flagger\non each remote cluster and set the Istio control plane host cluster kubeconfig:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://istio-cluster-prometheus:9090 "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set istio.kubeconfig.secretName"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-kubeconfig "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set istio.kubeconfig.key"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("kubeconfig\n")])])]),t("p",[a._v("Note that the Istio kubeconfig must be stored in a Kubernetes secret with a data key named "),t("code",[a._v("kubeconfig")]),a._v(".\nFor more details on how to configure Istio multi-cluster credentials\nread the "),t("a",{attrs:{href:"https://istio.io/docs/setup/install/multicluster/shared-vpn/#credentials",target:"_blank",rel:"noopener noreferrer"}},[a._v("Istio docs"),t("OutboundLink")],1),a._v(".")]),a._v(" "),t("p",[a._v("Deploy Flagger for Linkerd:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("linkerd "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("linkerd "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://linkerd-prometheus:9090\n")])])]),t("p",[a._v("Deploy Flagger for App Mesh:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("meshProvider")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("appmesh "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://appmesh-prometheus:9090\n")])])]),t("p",[a._v("You can install Flagger in any namespace as long as it can talk to the Prometheus service on port 9090.")]),a._v(" "),t("p",[a._v("For ingress controllers, the install instructions are:")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/contour-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[a._v("Contour"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/gloo-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[a._v("Gloo"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/nginx-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[a._v("NGINX"),t("OutboundLink")],1)])]),a._v(" "),t("p",[a._v("Enable "),t("strong",[a._v("Slack")]),a._v(" notifications:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.url"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.channel"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("general "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.user"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("flagger\n")])])]),t("p",[a._v("Enable "),t("strong",[a._v("Microsoft Teams")]),a._v(" notifications:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger flagger/flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set crd.create"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("false "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set msteams.url"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK\n")])])]),t("p",[a._v("You can use the helm template command and apply the generated yaml with kubectl:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# generate")]),a._v("\nhelm fetch --untar --untardir "),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v(".")]),a._v(" flagger/flagger "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("&&")]),a._v("\nhelm template flagger ./flagger "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("metricsServer")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://prometheus.istio-system:9090 "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" flagger.yaml\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# apply")]),a._v("\nkubectl apply -f flagger.yaml\n")])])]),t("p",[a._v("To uninstall the Flagger release with Helm run:")]),a._v(" "),t("div",{staticClass:"language-text extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[a._v("helm delete flagger\n")])])]),t("p",[a._v("The command removes all the Kubernetes components associated with the chart and deletes the release.")]),a._v(" "),t("blockquote",[t("p",[t("strong",[a._v("Note")]),a._v(" that on uninstall the Canary CRD will not be removed. Deleting the CRD will make Kubernetes\nremove all the objects owned by Flagger like Istio virtual services, Kubernetes deployments and ClusterIP services.")])]),a._v(" "),t("p",[a._v("If you want to remove all the objects created by Flagger you have delete the Canary CRD with kubectl:")]),a._v(" "),t("div",{staticClass:"language-text extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[a._v("kubectl delete crd canaries.flagger.app\n")])])]),t("h2",{attrs:{id:"install-grafana-with-helm"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#install-grafana-with-helm","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Grafana with Helm")]),a._v(" "),t("p",[a._v("Flagger comes with a Grafana dashboard made for monitoring the canary analysis.")]),a._v(" "),t("p",[a._v("Deploy Grafana in the "),t("em",[t("strong",[a._v("istio-system")])]),a._v(" namespace:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("helm upgrade -i flagger-grafana flagger/grafana "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("url")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("http://prometheus.istio-system:9090 "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("user")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("admin "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("password")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("change-me\n")])])]),t("p",[a._v("Or use helm template command and apply the generated yaml with kubectl:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# generate")]),a._v("\nhelm fetch --untar --untardir "),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v(".")]),a._v(" flagger/grafana "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("&&")]),a._v("\nhelm template flagger-grafana ./grafana "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--namespace"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("istio-system "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" flagger-grafana.yaml\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# apply")]),a._v("\nkubectl apply -f flagger-grafana.yaml\n")])])]),t("p",[a._v("You can access Grafana using port forwarding:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl -n istio-system port-forward svc/flagger-grafana "),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("3000")]),a._v(":80\n")])])]),t("h2",{attrs:{id:"install-flagger-with-kustomize"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#install-flagger-with-kustomize","aria-hidden":"true"}},[a._v("#")]),a._v(" Install Flagger with Kustomize")]),a._v(" "),t("p",[a._v("As an alternative to Helm, Flagger can be installed with Kustomize.")]),a._v(" "),t("p",[t("strong",[a._v("Service mesh specific installers")])]),a._v(" "),t("p",[a._v("Install Flagger for Istio:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/istio\n")])])]),t("p",[a._v("This deploys Flagger in the "),t("code",[a._v("istio-system")]),a._v(" namespace and sets the metrics server URL to Istio's Prometheus instance.")]),a._v(" "),t("p",[a._v("Note that you'll need kubectl 1.14 to run the above the command or you can download\nthe "),t("a",{attrs:{href:"https://github.com/kubernetes-sigs/kustomize/releases",target:"_blank",rel:"noopener noreferrer"}},[a._v("kustomize binary"),t("OutboundLink")],1),a._v(" and run:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kustomize build github.com/weaveworks/flagger//kustomize/istio "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("|")]),a._v(" kubectl apply -f -\n")])])]),t("p",[a._v("Install Flagger for AWS App Mesh:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/appmesh\n")])])]),t("p",[a._v("This deploys Flagger and sets the metrics server URL to App Mesh's Prometheus instance.")]),a._v(" "),t("p",[a._v("Install Flagger for Linkerd:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/linkerd\n")])])]),t("p",[a._v("This deploys Flagger in the "),t("code",[a._v("linkerd")]),a._v(" namespace and sets the metrics server URL to Linkerd's Prometheus instance.")]),a._v(" "),t("p",[a._v("If you want to install a specific Flagger release, add the version number to the URL:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/linkerd?ref"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("0.18")]),a._v(".0\n")])])]),t("p",[t("strong",[a._v("Generic installer")])]),a._v(" "),t("p",[a._v("Install Flagger and Prometheus:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/kubernetes\n")])])]),t("p",[a._v("This deploys Flagger and Prometheus in the "),t("code",[a._v("flagger-system")]),a._v(" namespace, sets the metrics server URL\nto "),t("code",[a._v("http://flagger-prometheus.flagger-system:9090")]),a._v(" and the mesh provider to "),t("code",[a._v("kubernetes")]),a._v(".")]),a._v(" "),t("p",[a._v("The Prometheus instance has a two hours data retention and is configured to scrape all pods in your cluster\nthat have the "),t("code",[a._v('prometheus.io/scrape: "true"')]),a._v(" annotation.")]),a._v(" "),t("p",[a._v("To target a different provider you can specify it in the canary custom resource:")]),a._v(" "),t("div",{staticClass:"language-yaml extra-class"},[t("pre",{pre:!0,attrs:{class:"language-yaml"}},[t("code",[t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger.app/v1beta1\n"),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Canary\n"),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" app\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" test\n"),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("spec")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# can be: kubernetes, istio, linkerd, appmesh, nginx, gloo")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# use the kubernetes provider for Blue/Green style deployments")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("provider")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" nginx\n")])])]),t("p",[t("strong",[a._v("Customized installer")])]),a._v(" "),t("p",[a._v("Create a kustomization file using flagger as base:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[a._v("cat")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" kustomization.yaml "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("<<")]),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("EOF\nnamespace: istio-system\nbases:\n - github.com/weaveworks/flagger/kustomize/base/flagger\npatchesStrategicMerge:\n - patch.yaml\nEOF")]),a._v("\n")])])]),t("p",[a._v("Create a patch and enable Slack notifications by setting the slack channel and hook URL:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[a._v("cat")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" patch.yaml "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("<<")]),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("EOF\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: flagger\nspec:\n template:\n spec:\n containers:\n - name: flagger\n args:\n - -mesh-provider=istio\n - -metrics-server=http://prometheus.istio-system:9090\n - -slack-user=flagger\n - -slack-channel=alerts\n - -slack-url=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK\nEOF")]),a._v("\n")])])]),t("p",[a._v("Install Flagger with Slack:")]),a._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[a._v("kubectl apply -k "),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v(".")]),a._v("\n")])])]),t("p",[a._v("If you want to use MS Teams instead of Slack, replace "),t("code",[a._v("-slack-url")]),a._v(" with "),t("code",[a._v("-msteams-url")]),a._v(" and set the webhook address\nto "),t("code",[a._v("https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK")]),a._v(".")])])},[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/14.affa49a6.js b/assets/js/14.a4f3d810.js similarity index 98% rename from assets/js/14.affa49a6.js rename to assets/js/14.a4f3d810.js index fa8f2088..1ba97bcb 100644 --- a/assets/js/14.affa49a6.js +++ b/assets/js/14.a4f3d810.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{273:function(e,r,t){"use strict";t.r(r);var s=t(37),o=Object(s.a)({},function(){var e=this,r=e.$createElement,t=e._self._c||r;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"introduction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#introduction","aria-hidden":"true"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://github.com/weaveworks/flagger",target:"_blank",rel:"noopener noreferrer"}},[e._v("Flagger"),t("OutboundLink")],1),e._v(" is a "),t("strong",[e._v("Kubernetes")]),e._v(" operator that automates the promotion of\ncanary deployments using "),t("strong",[e._v("Istio")]),e._v(", "),t("strong",[e._v("Linkerd")]),e._v(", "),t("strong",[e._v("App Mesh")]),e._v(", "),t("strong",[e._v("NGINX")]),e._v(", "),t("strong",[e._v("Contour")]),e._v(" or "),t("strong",[e._v("Gloo")]),e._v(" routing for\ntraffic shifting and "),t("strong",[e._v("Prometheus")]),e._v(" metrics for canary analysis. The canary analysis can be extended with webhooks for\nrunning system integration/acceptance tests, load tests, or any other custom validation.")]),e._v(" "),t("p",[e._v("Flagger implements a control loop that gradually shifts traffic to the canary while measuring key performance indicators\nlike HTTP requests success rate, requests average duration and pods health.\nBased on analysis of the "),t("strong",[e._v("KPIs")]),e._v(" a canary is promoted or aborted, and the analysis result is published to "),t("strong",[e._v("Slack")]),e._v(" or "),t("strong",[e._v("MS Teams")]),e._v(".")]),e._v(" "),t("p",[t("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-canary-overview.png",alt:"Flagger overview diagram"}})]),e._v(" "),t("p",[e._v("Flagger can be configured with Kubernetes custom resources and is compatible with any CI/CD solutions made for Kubernetes.\nSince Flagger is declarative and reacts to Kubernetes events,\nit can be used in "),t("strong",[e._v("GitOps")]),e._v(" pipelines together with Flux CD or JenkinsX.")]),e._v(" "),t("p",[e._v("To get started with Flagger, chose one of the supported routing providers\nand "),t("a",{attrs:{href:"../install/flagger-install-on-kubernetes"}},[e._v("install")]),e._v(" Flagger with Helm or Kustomize.")]),e._v(" "),t("p",[e._v("After install Flagger, you can follow one of the tutorials:")]),e._v(" "),t("p",[t("strong",[e._v("Service mesh tutorials")])]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"../tutorials/istio-progressive-delivery"}},[e._v("Istio")])]),e._v(" "),t("li",[t("a",{attrs:{href:"../tutorials/linkerd-progressive-delivery"}},[e._v("Linkerd")])]),e._v(" "),t("li",[t("a",{attrs:{href:"../tutorials/appmesh-progressive-delivery"}},[e._v("AWS App Mesh")])])]),e._v(" "),t("p",[t("strong",[e._v("Ingress controller tutorials")])]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"../tutorials/contour-progressive-delivery"}},[e._v("Contour")])]),e._v(" "),t("li",[t("a",{attrs:{href:"../tutorials/gloo-progressive-delivery"}},[e._v("Gloo")])]),e._v(" "),t("li",[t("a",{attrs:{href:"../tutorials/nginx-progressive-delivery"}},[e._v("NGINX Ingress")])])]),e._v(" "),t("p",[t("strong",[e._v("Hands-on GitOps workshops")])]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/stefanprodan/gitops-istio",target:"_blank",rel:"noopener noreferrer"}},[e._v("Istio"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://helm.workshop.flagger.dev",target:"_blank",rel:"noopener noreferrer"}},[e._v("Linkerd"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://eks.hands-on.flagger.dev",target:"_blank",rel:"noopener noreferrer"}},[e._v("AWS App Mesh"),t("OutboundLink")],1)])])])},[],!1,null,null,null);r.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{274:function(e,r,t){"use strict";t.r(r);var s=t(37),o=Object(s.a)({},function(){var e=this,r=e.$createElement,t=e._self._c||r;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"introduction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#introduction","aria-hidden":"true"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://github.com/weaveworks/flagger",target:"_blank",rel:"noopener noreferrer"}},[e._v("Flagger"),t("OutboundLink")],1),e._v(" is a "),t("strong",[e._v("Kubernetes")]),e._v(" operator that automates the promotion of\ncanary deployments using "),t("strong",[e._v("Istio")]),e._v(", "),t("strong",[e._v("Linkerd")]),e._v(", "),t("strong",[e._v("App Mesh")]),e._v(", "),t("strong",[e._v("NGINX")]),e._v(", "),t("strong",[e._v("Contour")]),e._v(" or "),t("strong",[e._v("Gloo")]),e._v(" routing for\ntraffic shifting and "),t("strong",[e._v("Prometheus")]),e._v(" metrics for canary analysis. The canary analysis can be extended with webhooks for\nrunning system integration/acceptance tests, load tests, or any other custom validation.")]),e._v(" "),t("p",[e._v("Flagger implements a control loop that gradually shifts traffic to the canary while measuring key performance indicators\nlike HTTP requests success rate, requests average duration and pods health.\nBased on analysis of the "),t("strong",[e._v("KPIs")]),e._v(" a canary is promoted or aborted, and the analysis result is published to "),t("strong",[e._v("Slack")]),e._v(" or "),t("strong",[e._v("MS Teams")]),e._v(".")]),e._v(" "),t("p",[t("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-canary-overview.png",alt:"Flagger overview diagram"}})]),e._v(" "),t("p",[e._v("Flagger can be configured with Kubernetes custom resources and is compatible with any CI/CD solutions made for Kubernetes.\nSince Flagger is declarative and reacts to Kubernetes events,\nit can be used in "),t("strong",[e._v("GitOps")]),e._v(" pipelines together with Flux CD or JenkinsX.")]),e._v(" "),t("p",[e._v("To get started with Flagger, chose one of the supported routing providers\nand "),t("a",{attrs:{href:"../install/flagger-install-on-kubernetes"}},[e._v("install")]),e._v(" Flagger with Helm or Kustomize.")]),e._v(" "),t("p",[e._v("After install Flagger, you can follow one of the tutorials:")]),e._v(" "),t("p",[t("strong",[e._v("Service mesh tutorials")])]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"../tutorials/istio-progressive-delivery"}},[e._v("Istio")])]),e._v(" "),t("li",[t("a",{attrs:{href:"../tutorials/linkerd-progressive-delivery"}},[e._v("Linkerd")])]),e._v(" "),t("li",[t("a",{attrs:{href:"../tutorials/appmesh-progressive-delivery"}},[e._v("AWS App Mesh")])])]),e._v(" "),t("p",[t("strong",[e._v("Ingress controller tutorials")])]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"../tutorials/contour-progressive-delivery"}},[e._v("Contour")])]),e._v(" "),t("li",[t("a",{attrs:{href:"../tutorials/gloo-progressive-delivery"}},[e._v("Gloo")])]),e._v(" "),t("li",[t("a",{attrs:{href:"../tutorials/nginx-progressive-delivery"}},[e._v("NGINX Ingress")])])]),e._v(" "),t("p",[t("strong",[e._v("Hands-on GitOps workshops")])]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/stefanprodan/gitops-istio",target:"_blank",rel:"noopener noreferrer"}},[e._v("Istio"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://helm.workshop.flagger.dev",target:"_blank",rel:"noopener noreferrer"}},[e._v("Linkerd"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://eks.hands-on.flagger.dev",target:"_blank",rel:"noopener noreferrer"}},[e._v("AWS App Mesh"),t("OutboundLink")],1)])])])},[],!1,null,null,null);r.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/23.ec1dec63.js b/assets/js/23.b3dcc355.js similarity index 99% rename from assets/js/23.ec1dec63.js rename to assets/js/23.b3dcc355.js index 36281afc..ea5f9616 100644 --- a/assets/js/23.ec1dec63.js +++ b/assets/js/23.b3dcc355.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{284:function(a,t,e){"use strict";e.r(t);var s=e(37),n=Object(s.a)({},function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"istio-a-b-testing"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#istio-a-b-testing","aria-hidden":"true"}},[a._v("#")]),a._v(" Istio A/B Testing")]),a._v(" "),e("p",[a._v("This guide shows you how to automate A/B testing with Istio and Flagger.")]),a._v(" "),e("p",[a._v("Besides weighted routing, Flagger can be configured to route traffic to the canary based on HTTP match conditions.\nIn an A/B testing scenario, you'll be using HTTP headers or cookies to target a certain segment of your users.\nThis is particularly useful for frontend applications that require session affinity.")]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-abtest-steps.png",alt:"Flagger A/B Testing Stages"}})]),a._v(" "),e("h2",{attrs:{id:"prerequisites"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites","aria-hidden":"true"}},[a._v("#")]),a._v(" Prerequisites")]),a._v(" "),e("p",[a._v("Flagger requires a Kubernetes cluster "),e("strong",[a._v("v1.11")]),a._v(" or newer and Istio "),e("strong",[a._v("v1.0")]),a._v(" or newer.")]),a._v(" "),e("p",[a._v("Install Istio with telemetry support and Prometheus:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("istioctl manifest apply --set "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("profile")]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("default\n")])])]),e("p",[a._v("Install Flagger using Kustomize (kubectl 1.14) in the "),e("code",[a._v("istio-system")]),a._v(" namespace:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/istio\n")])])]),e("p",[a._v("Create an ingress gateway to expose the demo app outside of the mesh:")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" networking.istio.io/v1alpha3\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Gateway\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" public"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("gateway\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" istio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("system\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("selector")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("istio")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" ingressgateway\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("servers")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("port")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("number")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("80")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" http\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("protocol")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" HTTP\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("hosts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"*"')]),a._v("\n")])])]),e("h2",{attrs:{id:"bootstrap"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#bootstrap","aria-hidden":"true"}},[a._v("#")]),a._v(" Bootstrap")]),a._v(" "),e("p",[a._v("Create a test namespace with Istio sidecar injection enabled:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl create ns "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("test")]),a._v("\nkubectl label namespace "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("test")]),a._v(" istio-injection"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("enabled\n")])])]),e("p",[a._v("Create a deployment and a horizontal pod autoscaler:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/podinfo\n")])])]),e("p",[a._v("Deploy the load testing service to generate traffic during the canary analysis:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/tester\n")])])]),e("p",[a._v("Create a canary custom resource (replace example.com with your own domain):")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger.app/v1beta1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Canary\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" test\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# deployment reference")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("targetRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" apps/v1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Deployment\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# the maximum time in seconds for the canary deployment")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# to make progress before it is rollback (default 600s)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("progressDeadlineSeconds")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("60")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# HPA reference (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("autoscalerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" autoscaling/v2beta1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" HorizontalPodAutoscaler\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("service")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# container port")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("port")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("9898")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# Istio gateways (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("gateways")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" public"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("gateway.istio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("system.svc.cluster.local\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# Istio virtual service host names (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("hosts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" app.example.com\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# Istio traffic policy (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("trafficPolicy")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("tls")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# use ISTIO_MUTUAL when mTLS is enabled")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("mode")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" DISABLE\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("analysis")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# schedule interval (default 60s)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# total number of iterations")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("iterations")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("10")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# max number of failed iterations before rollback")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("threshold")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("2")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# canary match condition")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("match")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("headers")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("user-agent")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("regex")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"^(?!.*Chrome).*Safari.*"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("headers")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("cookie")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("regex")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"^(.*?;)?(type=insider)(;.*)?$"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metrics")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("success"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("rate\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# minimum req success rate (non 5xx responses)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# percentage (0-100)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("min")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("99")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("duration\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# maximum req duration P99")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# milliseconds")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("max")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("500")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 30s\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# generate traffic during analysis")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("webhooks")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" load"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 5s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v("\"hey -z 1m -q 10 -c 2 -H 'Cookie: type=insider' http://podinfo.test:9898/\"")]),a._v("\n")])])]),e("p",[a._v("The above configuration will run an analysis for ten minutes targeting Safari users and those that have an insider cookie.")]),a._v(" "),e("p",[a._v("Save the above resource as podinfo-abtest.yaml and then apply it:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl apply -f ./podinfo-abtest.yaml\n")])])]),e("p",[a._v("After a couple of seconds Flagger will create the canary objects:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# applied ")]),a._v("\ndeployment.apps/podinfo\nhorizontalpodautoscaler.autoscaling/podinfo\ncanary.flagger.app/podinfo\n\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# generated ")]),a._v("\ndeployment.apps/podinfo-primary\nhorizontalpodautoscaler.autoscaling/podinfo-primary\nservice/podinfo\nservice/podinfo-canary\nservice/podinfo-primary\ndestinationrule.networking.istio.io/podinfo-canary\ndestinationrule.networking.istio.io/podinfo-primary\nvirtualservice.networking.istio.io/podinfo\n")])])]),e("h2",{attrs:{id:"automated-canary-promotion"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-canary-promotion","aria-hidden":"true"}},[a._v("#")]),a._v(" Automated canary promotion")]),a._v(" "),e("p",[a._v("Trigger a canary deployment by updating the container image:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl -n "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("test")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("set")]),a._v(" image deployment/podinfo "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("podinfod")]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("stefanprodan/podinfo:3.1.1\n")])])]),e("p",[a._v("Flagger detects that the deployment revision changed and starts a new rollout:")]),a._v(" "),e("div",{staticClass:"language-text extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("kubectl -n test describe canary/abtest\n\nStatus:\n Failed Checks: 0\n Phase: Succeeded\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Synced 3m flagger New revision detected podinfo.test\n Normal Synced 3m flagger Scaling up podinfo.test\n Warning Synced 3m flagger Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available\n Normal Synced 3m flagger Advance podinfo.test canary iteration 1/10\n Normal Synced 3m flagger Advance podinfo.test canary iteration 2/10\n Normal Synced 3m flagger Advance podinfo.test canary iteration 3/10\n Normal Synced 2m flagger Advance podinfo.test canary iteration 4/10\n Normal Synced 2m flagger Advance podinfo.test canary iteration 5/10\n Normal Synced 1m flagger Advance podinfo.test canary iteration 6/10\n Normal Synced 1m flagger Advance podinfo.test canary iteration 7/10\n Normal Synced 55s flagger Advance podinfo.test canary iteration 8/10\n Normal Synced 45s flagger Advance podinfo.test canary iteration 9/10\n Normal Synced 35s flagger Advance podinfo.test canary iteration 10/10\n Normal Synced 25s flagger Copying podinfo.test template spec to podinfo-primary.test\n Warning Synced 15s flagger Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available\n Normal Synced 5s flagger Promotion completed! Scaling down podinfo.test\n")])])]),e("p",[e("strong",[a._v("Note")]),a._v(" that if you apply new changes to the deployment during the canary analysis, Flagger will restart the analysis.")]),a._v(" "),e("p",[a._v("You can monitor all canaries with:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[a._v("watch")]),a._v(" kubectl get canaries --all-namespaces\n\nNAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME\n"),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("test")]),a._v(" podinfo Progressing "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("100")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("2019")]),a._v("-03-16T14:05:07Z\nprod frontend Succeeded "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("0")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("2019")]),a._v("-03-15T16:15:07Z\nprod backend Failed "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("0")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("2019")]),a._v("-03-14T17:05:07Z\n")])])]),e("h2",{attrs:{id:"automated-rollback"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-rollback","aria-hidden":"true"}},[a._v("#")]),a._v(" Automated rollback")]),a._v(" "),e("p",[a._v("During the canary analysis you can generate HTTP 500 errors and high latency to test Flagger's rollback.")]),a._v(" "),e("p",[a._v("Generate HTTP 500 errors:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[a._v("watch")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("curl")]),a._v(" -b "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v("'type=insider'")]),a._v(" http://app.example.com/status/500\n")])])]),e("p",[a._v("Generate latency:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[a._v("watch")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("curl")]),a._v(" -b "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v("'type=insider'")]),a._v(" http://app.example.com/delay/1\n")])])]),e("p",[a._v("When the number of failed checks reaches the canary analysis threshold, the traffic is routed back to the primary,\nthe canary is scaled to zero and the rollout is marked as failed.")]),a._v(" "),e("div",{staticClass:"language-text extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("kubectl -n test describe canary/podinfo\n\nStatus:\n Failed Checks: 2\n Phase: Failed\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Synced 3m flagger Starting canary deployment for podinfo.test\n Normal Synced 3m flagger Advance podinfo.test canary iteration 1/10\n Normal Synced 3m flagger Advance podinfo.test canary iteration 2/10\n Normal Synced 3m flagger Advance podinfo.test canary iteration 3/10\n Normal Synced 3m flagger Halt podinfo.test advancement success rate 69.17% < 99%\n Normal Synced 2m flagger Halt podinfo.test advancement success rate 61.39% < 99%\n Warning Synced 2m flagger Rolling back podinfo.test failed checks threshold reached 2\n Warning Synced 1m flagger Canary failed! Scaling down podinfo.test\n")])])]),e("p",[a._v("The above procedure can be extended with "),e("router-link",{attrs:{to:"/usage/metrics.html"}},[a._v("custom metrics")]),a._v(" checks,\n"),e("router-link",{attrs:{to:"/usage/webhooks.html"}},[a._v("webhooks")]),a._v(",\n"),e("router-link",{attrs:{to:"/usage/webhooks.html#manual-gating"}},[a._v("manual promotion")]),a._v(" approval and\n"),e("router-link",{attrs:{to:"/usage/alerting.html"}},[a._v("Slack or MS Teams")]),a._v(" notifications.")],1)])},[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{283:function(a,t,e){"use strict";e.r(t);var s=e(37),n=Object(s.a)({},function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"istio-a-b-testing"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#istio-a-b-testing","aria-hidden":"true"}},[a._v("#")]),a._v(" Istio A/B Testing")]),a._v(" "),e("p",[a._v("This guide shows you how to automate A/B testing with Istio and Flagger.")]),a._v(" "),e("p",[a._v("Besides weighted routing, Flagger can be configured to route traffic to the canary based on HTTP match conditions.\nIn an A/B testing scenario, you'll be using HTTP headers or cookies to target a certain segment of your users.\nThis is particularly useful for frontend applications that require session affinity.")]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-abtest-steps.png",alt:"Flagger A/B Testing Stages"}})]),a._v(" "),e("h2",{attrs:{id:"prerequisites"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites","aria-hidden":"true"}},[a._v("#")]),a._v(" Prerequisites")]),a._v(" "),e("p",[a._v("Flagger requires a Kubernetes cluster "),e("strong",[a._v("v1.11")]),a._v(" or newer and Istio "),e("strong",[a._v("v1.0")]),a._v(" or newer.")]),a._v(" "),e("p",[a._v("Install Istio with telemetry support and Prometheus:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("istioctl manifest apply --set "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("profile")]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("default\n")])])]),e("p",[a._v("Install Flagger using Kustomize (kubectl 1.14) in the "),e("code",[a._v("istio-system")]),a._v(" namespace:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/istio\n")])])]),e("p",[a._v("Create an ingress gateway to expose the demo app outside of the mesh:")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" networking.istio.io/v1alpha3\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Gateway\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" public"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("gateway\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" istio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("system\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("selector")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("istio")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" ingressgateway\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("servers")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("port")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("number")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("80")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" http\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("protocol")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" HTTP\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("hosts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"*"')]),a._v("\n")])])]),e("h2",{attrs:{id:"bootstrap"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#bootstrap","aria-hidden":"true"}},[a._v("#")]),a._v(" Bootstrap")]),a._v(" "),e("p",[a._v("Create a test namespace with Istio sidecar injection enabled:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl create ns "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("test")]),a._v("\nkubectl label namespace "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("test")]),a._v(" istio-injection"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("enabled\n")])])]),e("p",[a._v("Create a deployment and a horizontal pod autoscaler:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/podinfo\n")])])]),e("p",[a._v("Deploy the load testing service to generate traffic during the canary analysis:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/tester\n")])])]),e("p",[a._v("Create a canary custom resource (replace example.com with your own domain):")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger.app/v1beta1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Canary\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" test\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# deployment reference")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("targetRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" apps/v1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Deployment\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# the maximum time in seconds for the canary deployment")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# to make progress before it is rollback (default 600s)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("progressDeadlineSeconds")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("60")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# HPA reference (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("autoscalerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" autoscaling/v2beta1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" HorizontalPodAutoscaler\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("service")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# container port")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("port")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("9898")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# Istio gateways (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("gateways")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" public"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("gateway.istio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("system.svc.cluster.local\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# Istio virtual service host names (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("hosts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" app.example.com\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# Istio traffic policy (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("trafficPolicy")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("tls")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# use ISTIO_MUTUAL when mTLS is enabled")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("mode")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" DISABLE\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("analysis")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# schedule interval (default 60s)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# total number of iterations")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("iterations")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("10")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# max number of failed iterations before rollback")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("threshold")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("2")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# canary match condition")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("match")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("headers")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("user-agent")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("regex")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"^(?!.*Chrome).*Safari.*"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("headers")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("cookie")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("regex")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"^(.*?;)?(type=insider)(;.*)?$"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metrics")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("success"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("rate\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# minimum req success rate (non 5xx responses)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# percentage (0-100)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("min")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("99")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("duration\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# maximum req duration P99")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# milliseconds")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("max")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("500")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 30s\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# generate traffic during analysis")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("webhooks")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" load"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 5s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v("\"hey -z 1m -q 10 -c 2 -H 'Cookie: type=insider' http://podinfo.test:9898/\"")]),a._v("\n")])])]),e("p",[a._v("The above configuration will run an analysis for ten minutes targeting Safari users and those that have an insider cookie.")]),a._v(" "),e("p",[a._v("Save the above resource as podinfo-abtest.yaml and then apply it:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl apply -f ./podinfo-abtest.yaml\n")])])]),e("p",[a._v("After a couple of seconds Flagger will create the canary objects:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# applied ")]),a._v("\ndeployment.apps/podinfo\nhorizontalpodautoscaler.autoscaling/podinfo\ncanary.flagger.app/podinfo\n\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# generated ")]),a._v("\ndeployment.apps/podinfo-primary\nhorizontalpodautoscaler.autoscaling/podinfo-primary\nservice/podinfo\nservice/podinfo-canary\nservice/podinfo-primary\ndestinationrule.networking.istio.io/podinfo-canary\ndestinationrule.networking.istio.io/podinfo-primary\nvirtualservice.networking.istio.io/podinfo\n")])])]),e("h2",{attrs:{id:"automated-canary-promotion"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-canary-promotion","aria-hidden":"true"}},[a._v("#")]),a._v(" Automated canary promotion")]),a._v(" "),e("p",[a._v("Trigger a canary deployment by updating the container image:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("kubectl -n "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("test")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("set")]),a._v(" image deployment/podinfo "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[a._v("podinfod")]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("stefanprodan/podinfo:3.1.1\n")])])]),e("p",[a._v("Flagger detects that the deployment revision changed and starts a new rollout:")]),a._v(" "),e("div",{staticClass:"language-text extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("kubectl -n test describe canary/abtest\n\nStatus:\n Failed Checks: 0\n Phase: Succeeded\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Synced 3m flagger New revision detected podinfo.test\n Normal Synced 3m flagger Scaling up podinfo.test\n Warning Synced 3m flagger Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available\n Normal Synced 3m flagger Advance podinfo.test canary iteration 1/10\n Normal Synced 3m flagger Advance podinfo.test canary iteration 2/10\n Normal Synced 3m flagger Advance podinfo.test canary iteration 3/10\n Normal Synced 2m flagger Advance podinfo.test canary iteration 4/10\n Normal Synced 2m flagger Advance podinfo.test canary iteration 5/10\n Normal Synced 1m flagger Advance podinfo.test canary iteration 6/10\n Normal Synced 1m flagger Advance podinfo.test canary iteration 7/10\n Normal Synced 55s flagger Advance podinfo.test canary iteration 8/10\n Normal Synced 45s flagger Advance podinfo.test canary iteration 9/10\n Normal Synced 35s flagger Advance podinfo.test canary iteration 10/10\n Normal Synced 25s flagger Copying podinfo.test template spec to podinfo-primary.test\n Warning Synced 15s flagger Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available\n Normal Synced 5s flagger Promotion completed! Scaling down podinfo.test\n")])])]),e("p",[e("strong",[a._v("Note")]),a._v(" that if you apply new changes to the deployment during the canary analysis, Flagger will restart the analysis.")]),a._v(" "),e("p",[a._v("You can monitor all canaries with:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[a._v("watch")]),a._v(" kubectl get canaries --all-namespaces\n\nNAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME\n"),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[a._v("test")]),a._v(" podinfo Progressing "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("100")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("2019")]),a._v("-03-16T14:05:07Z\nprod frontend Succeeded "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("0")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("2019")]),a._v("-03-15T16:15:07Z\nprod backend Failed "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("0")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[a._v("2019")]),a._v("-03-14T17:05:07Z\n")])])]),e("h2",{attrs:{id:"automated-rollback"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-rollback","aria-hidden":"true"}},[a._v("#")]),a._v(" Automated rollback")]),a._v(" "),e("p",[a._v("During the canary analysis you can generate HTTP 500 errors and high latency to test Flagger's rollback.")]),a._v(" "),e("p",[a._v("Generate HTTP 500 errors:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[a._v("watch")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("curl")]),a._v(" -b "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v("'type=insider'")]),a._v(" http://app.example.com/status/500\n")])])]),e("p",[a._v("Generate latency:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[a._v("watch")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("curl")]),a._v(" -b "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v("'type=insider'")]),a._v(" http://app.example.com/delay/1\n")])])]),e("p",[a._v("When the number of failed checks reaches the canary analysis threshold, the traffic is routed back to the primary,\nthe canary is scaled to zero and the rollout is marked as failed.")]),a._v(" "),e("div",{staticClass:"language-text extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("kubectl -n test describe canary/podinfo\n\nStatus:\n Failed Checks: 2\n Phase: Failed\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Synced 3m flagger Starting canary deployment for podinfo.test\n Normal Synced 3m flagger Advance podinfo.test canary iteration 1/10\n Normal Synced 3m flagger Advance podinfo.test canary iteration 2/10\n Normal Synced 3m flagger Advance podinfo.test canary iteration 3/10\n Normal Synced 3m flagger Halt podinfo.test advancement success rate 69.17% < 99%\n Normal Synced 2m flagger Halt podinfo.test advancement success rate 61.39% < 99%\n Warning Synced 2m flagger Rolling back podinfo.test failed checks threshold reached 2\n Warning Synced 1m flagger Canary failed! Scaling down podinfo.test\n")])])]),e("p",[a._v("The above procedure can be extended with "),e("router-link",{attrs:{to:"/usage/metrics.html"}},[a._v("custom metrics")]),a._v(" checks,\n"),e("router-link",{attrs:{to:"/usage/webhooks.html"}},[a._v("webhooks")]),a._v(",\n"),e("router-link",{attrs:{to:"/usage/webhooks.html#manual-gating"}},[a._v("manual promotion")]),a._v(" approval and\n"),e("router-link",{attrs:{to:"/usage/alerting.html"}},[a._v("Slack or MS Teams")]),a._v(" notifications.")],1)])},[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/24.721d8c4e.js b/assets/js/24.4f54d289.js similarity index 99% rename from assets/js/24.721d8c4e.js rename to assets/js/24.4f54d289.js index 95450031..29b683e8 100644 --- a/assets/js/24.721d8c4e.js +++ b/assets/js/24.4f54d289.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{283:function(t,a,e){"use strict";e.r(a);var s=e(37),n=Object(s.a)({},function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"istio-canary-deployments"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#istio-canary-deployments","aria-hidden":"true"}},[t._v("#")]),t._v(" Istio Canary Deployments")]),t._v(" "),e("p",[t._v("This guide shows you how to use Istio and Flagger to automate canary deployments.")]),t._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-canary-steps.png",alt:"Flagger Canary Stages"}})]),t._v(" "),e("h2",{attrs:{id:"prerequisites"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites","aria-hidden":"true"}},[t._v("#")]),t._v(" Prerequisites")]),t._v(" "),e("p",[t._v("Flagger requires a Kubernetes cluster "),e("strong",[t._v("v1.11")]),t._v(" or newer and Istio "),e("strong",[t._v("v1.0")]),t._v(" or newer.")]),t._v(" "),e("p",[t._v("Install Istio with telemetry support and Prometheus:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("istioctl manifest apply --set "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("profile")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("default\n")])])]),e("p",[t._v("Install Flagger using Kustomize (kubectl 1.14) in the "),e("code",[t._v("istio-system")]),t._v(" namespace:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/istio\n")])])]),e("p",[t._v("Create an ingress gateway to expose the demo app outside of the mesh:")]),t._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" networking.istio.io/v1alpha3\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" Gateway\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" public"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("gateway\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" istio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("system\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("selector")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("istio")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ingressgateway\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("servers")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("port")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("number")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("80")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("protocol")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" HTTP\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("hosts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"*"')]),t._v("\n")])])]),e("h2",{attrs:{id:"bootstrap"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#bootstrap","aria-hidden":"true"}},[t._v("#")]),t._v(" Bootstrap")]),t._v(" "),e("p",[t._v("Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler (HPA),\nthen creates a series of objects (Kubernetes deployments, ClusterIP services,\nIstio destination rules and virtual services).\nThese objects expose the application inside the mesh and drive the canary analysis and promotion.")]),t._v(" "),e("p",[t._v("Create a test namespace with Istio sidecar injection enabled:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl create ns "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v("\nkubectl label namespace "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" istio-injection"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("enabled\n")])])]),e("p",[t._v("Create a deployment and a horizontal pod autoscaler:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/podinfo\n")])])]),e("p",[t._v("Deploy the load testing service to generate traffic during the canary analysis:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/tester\n")])])]),e("p",[t._v("Create a canary custom resource (replace example.com with your own domain):")]),t._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" flagger.app/v1beta1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" Canary\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" test\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# deployment reference")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("targetRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" apps/v1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" Deployment\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# the maximum time in seconds for the canary deployment")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# to make progress before it is rollback (default 600s)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("progressDeadlineSeconds")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("60")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# HPA reference (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("autoscalerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" autoscaling/v2beta1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" HorizontalPodAutoscaler\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("service")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# service port number")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("port")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("9898")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# container port number or name (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("targetPort")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("9898")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Istio gateways (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("gateways")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" public"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("gateway.istio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("system.svc.cluster.local\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Istio virtual service host names (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("hosts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" app.example.com\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Istio traffic policy (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("trafficPolicy")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("tls")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# use ISTIO_MUTUAL when mTLS is enabled")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("mode")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" DISABLE\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Istio retry policy (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("retries")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("attempts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("perTryTimeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("retryOn")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"gateway-error,connect-failure,refused-stream"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("analysis")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# schedule interval (default 60s)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# max number of failed metric checks before rollback")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("threshold")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# max traffic percentage routed to canary")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# percentage (0-100)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("maxWeight")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# canary increment step")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# percentage (0-100)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("stepWeight")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metrics")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("success"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("rate\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# minimum req success rate (non 5xx responses)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# percentage (0-100)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("min")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("99")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("duration\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# maximum req duration P99")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# milliseconds")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("max")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 30s\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# testing (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("webhooks")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" acceptance"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pre"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("rollout\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 30s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bash\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"curl -sd 'test' http://podinfo-canary:9898/token | grep token\"")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" load"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 5s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/"')]),t._v("\n")])])]),e("p",[t._v("Save the above resource as podinfo-canary.yaml and then apply it:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl apply -f ./podinfo-canary.yaml\n")])])]),e("p",[t._v("When the canary analysis starts, Flagger will call the pre-rollout webhooks before routing traffic to the canary.\nThe canary analysis will run for five minutes while validating the HTTP metrics and rollout hooks every minute.")]),t._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-canary-hpa.png",alt:"Flagger Canary Process"}})]),t._v(" "),e("p",[t._v("After a couple of seconds Flagger will create the canary objects:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# applied ")]),t._v("\ndeployment.apps/podinfo\nhorizontalpodautoscaler.autoscaling/podinfo\ncanary.flagger.app/podinfo\n\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# generated ")]),t._v("\ndeployment.apps/podinfo-primary\nhorizontalpodautoscaler.autoscaling/podinfo-primary\nservice/podinfo\nservice/podinfo-canary\nservice/podinfo-primary\ndestinationrule.networking.istio.io/podinfo-canary\ndestinationrule.networking.istio.io/podinfo-primary\nvirtualservice.networking.istio.io/podinfo\n")])])]),e("h2",{attrs:{id:"automated-canary-promotion"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-canary-promotion","aria-hidden":"true"}},[t._v("#")]),t._v(" Automated canary promotion")]),t._v(" "),e("p",[t._v("Trigger a canary deployment by updating the container image:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl -n "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" image deployment/podinfo "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("podinfod")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("stefanprodan/podinfo:3.1.1\n")])])]),e("p",[t._v("Flagger detects that the deployment revision changed and starts a new rollout:")]),t._v(" "),e("div",{staticClass:"language-text extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("kubectl -n test describe canary/podinfo\n\nStatus:\n Canary Weight: 0\n Failed Checks: 0\n Phase: Succeeded\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Synced 3m flagger New revision detected podinfo.test\n Normal Synced 3m flagger Scaling up podinfo.test\n Warning Synced 3m flagger Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available\n Normal Synced 3m flagger Advance podinfo.test canary weight 5\n Normal Synced 3m flagger Advance podinfo.test canary weight 10\n Normal Synced 3m flagger Advance podinfo.test canary weight 15\n Normal Synced 2m flagger Advance podinfo.test canary weight 20\n Normal Synced 2m flagger Advance podinfo.test canary weight 25\n Normal Synced 1m flagger Advance podinfo.test canary weight 30\n Normal Synced 1m flagger Advance podinfo.test canary weight 35\n Normal Synced 55s flagger Advance podinfo.test canary weight 40\n Normal Synced 45s flagger Advance podinfo.test canary weight 45\n Normal Synced 35s flagger Advance podinfo.test canary weight 50\n Normal Synced 25s flagger Copying podinfo.test template spec to podinfo-primary.test\n Warning Synced 15s flagger Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available\n Normal Synced 5s flagger Promotion completed! Scaling down podinfo.test\n")])])]),e("p",[e("strong",[t._v("Note")]),t._v(" that if you apply new changes to the deployment during the canary analysis, Flagger will restart the analysis.")]),t._v(" "),e("p",[t._v("A canary deployment is triggered by changes in any of the following objects:")]),t._v(" "),e("ul",[e("li",[t._v("Deployment PodSpec (container image, command, ports, env, resources, etc)")]),t._v(" "),e("li",[t._v("ConfigMaps mounted as volumes or mapped to environment variables")]),t._v(" "),e("li",[t._v("Secrets mounted as volumes or mapped to environment variables")])]),t._v(" "),e("p",[t._v("You can monitor all canaries with:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("watch")]),t._v(" kubectl get canaries --all-namespaces\n\nNAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME\n"),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" podinfo Progressing "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("15")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2019")]),t._v("-01-16T14:05:07Z\nprod frontend Succeeded "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2019")]),t._v("-01-15T16:15:07Z\nprod backend Failed "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2019")]),t._v("-01-14T17:05:07Z\n")])])]),e("h2",{attrs:{id:"automated-rollback"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-rollback","aria-hidden":"true"}},[t._v("#")]),t._v(" Automated rollback")]),t._v(" "),e("p",[t._v("During the canary analysis you can generate HTTP 500 errors and high latency to test if Flagger pauses the rollout.")]),t._v(" "),e("p",[t._v("Trigger another canary deployment:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl -n "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" image deployment/podinfo "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("podinfod")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("stefanprodan/podinfo:3.1.2\n")])])]),e("p",[t._v("Exec into the load tester pod with:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl -n "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("exec")]),t._v(" -it flagger-loadtester-xx-xx "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("sh")]),t._v("\n")])])]),e("p",[t._v("Generate HTTP 500 errors:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("watch")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("curl")]),t._v(" http://podinfo-canary:9898/status/500\n")])])]),e("p",[t._v("Generate latency:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("watch")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("curl")]),t._v(" http://podinfo-canary:9898/delay/1\n")])])]),e("p",[t._v("When the number of failed checks reaches the canary analysis threshold, the traffic is routed back to the primary,\nthe canary is scaled to zero and the rollout is marked as failed.")]),t._v(" "),e("div",{staticClass:"language-text extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("kubectl -n test describe canary/podinfo\n\nStatus:\n Canary Weight: 0\n Failed Checks: 10\n Phase: Failed\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Synced 3m flagger Starting canary deployment for podinfo.test\n Normal Synced 3m flagger Advance podinfo.test canary weight 5\n Normal Synced 3m flagger Advance podinfo.test canary weight 10\n Normal Synced 3m flagger Advance podinfo.test canary weight 15\n Normal Synced 3m flagger Halt podinfo.test advancement success rate 69.17% < 99%\n Normal Synced 2m flagger Halt podinfo.test advancement success rate 61.39% < 99%\n Normal Synced 2m flagger Halt podinfo.test advancement success rate 55.06% < 99%\n Normal Synced 2m flagger Halt podinfo.test advancement success rate 47.00% < 99%\n Normal Synced 2m flagger (combined from similar events): Halt podinfo.test advancement success rate 38.08% < 99%\n Warning Synced 1m flagger Rolling back podinfo.test failed checks threshold reached 10\n Warning Synced 1m flagger Canary failed! Scaling down podinfo.test\n")])])]),e("h2",{attrs:{id:"traffic-mirroring"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#traffic-mirroring","aria-hidden":"true"}},[t._v("#")]),t._v(" Traffic mirroring")]),t._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-canary-traffic-mirroring.png",alt:"Flagger Canary Traffic Shadowing"}})]),t._v(" "),e("p",[t._v("For applications that perform read operations, Flagger can be configured to drive canary releases with traffic mirroring.\nIstio traffic mirroring will copy each incoming request, sending one request to the primary and one to the canary service.\nThe response from the primary is sent back to the user and the response from the canary is discarded.\nMetrics are collected on both requests so that the deployment will only proceed if the canary metrics are within the threshold values.")]),t._v(" "),e("p",[t._v("Note that mirroring should be used for requests that are "),e("strong",[t._v("idempotent")]),t._v(" or capable of being processed twice (once by the primary and once by the canary).")]),t._v(" "),e("p",[t._v("You can enable mirroring by replacing "),e("code",[t._v("stepWeight/maxWeight")]),t._v(" with "),e("code",[t._v("iterations")]),t._v(" and by setting "),e("code",[t._v("analysis.mirror")]),t._v(" to "),e("code",[t._v("true")]),t._v(":")]),t._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" flagger.app/v1beta1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" Canary\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" test\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("analysis")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# schedule interval")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# max number of failed metric checks before rollback")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("threshold")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# total number of iterations")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("iterations")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# enable traffic shadowing ")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("mirror")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean important"}},[t._v("true")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metrics")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("success"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("rate\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("min")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("99")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("duration\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("max")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("webhooks")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" acceptance"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pre"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("rollout\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 30s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bash\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"curl -sd 'test' http://podinfo-canary:9898/token | grep token\"")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" load"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 5s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"')]),t._v("\n")])])]),e("p",[t._v("With the above configuration, Flagger will run a canary release with the following steps:")]),t._v(" "),e("ul",[e("li",[t._v("detect new revision (deployment spec, secrets or configmaps changes)")]),t._v(" "),e("li",[t._v("scale from zero the canary deployment")]),t._v(" "),e("li",[t._v("wait for the HPA to set the canary minimum replicas")]),t._v(" "),e("li",[t._v("check canary pods health")]),t._v(" "),e("li",[t._v("run the acceptance tests")]),t._v(" "),e("li",[t._v("abort the canary release if tests fail")]),t._v(" "),e("li",[t._v("start the load tests")]),t._v(" "),e("li",[t._v("mirror traffic from primary to canary")]),t._v(" "),e("li",[t._v("check request success rate and request duration every minute")]),t._v(" "),e("li",[t._v("abort the canary release if the metrics check failure threshold is reached")]),t._v(" "),e("li",[t._v("stop traffic mirroring after the number of iterations is reached")]),t._v(" "),e("li",[t._v("route live traffic to the canary pods")]),t._v(" "),e("li",[t._v("promote the canary (update the primary secrets, configmaps and deployment spec)")]),t._v(" "),e("li",[t._v("wait for the primary deployment rollout to finish")]),t._v(" "),e("li",[t._v("wait for the HPA to set the primary minimum replicas")]),t._v(" "),e("li",[t._v("check primary pods health")]),t._v(" "),e("li",[t._v("switch live traffic back to primary")]),t._v(" "),e("li",[t._v("scale to zero the canary")]),t._v(" "),e("li",[t._v("send notification with the canary analysis result")])]),t._v(" "),e("p",[t._v("The above procedure can be extended with "),e("router-link",{attrs:{to:"/usage/metrics.html"}},[t._v("custom metrics")]),t._v(" checks,\n"),e("router-link",{attrs:{to:"/usage/webhooks.html"}},[t._v("webhooks")]),t._v(",\n"),e("router-link",{attrs:{to:"/usage/webhooks.html#manual-gating"}},[t._v("manual promotion")]),t._v(" approval and\n"),e("router-link",{attrs:{to:"/usage/alerting.html"}},[t._v("Slack or MS Teams")]),t._v(" notifications.")],1)])},[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{284:function(t,a,e){"use strict";e.r(a);var s=e(37),n=Object(s.a)({},function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"istio-canary-deployments"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#istio-canary-deployments","aria-hidden":"true"}},[t._v("#")]),t._v(" Istio Canary Deployments")]),t._v(" "),e("p",[t._v("This guide shows you how to use Istio and Flagger to automate canary deployments.")]),t._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-canary-steps.png",alt:"Flagger Canary Stages"}})]),t._v(" "),e("h2",{attrs:{id:"prerequisites"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites","aria-hidden":"true"}},[t._v("#")]),t._v(" Prerequisites")]),t._v(" "),e("p",[t._v("Flagger requires a Kubernetes cluster "),e("strong",[t._v("v1.11")]),t._v(" or newer and Istio "),e("strong",[t._v("v1.0")]),t._v(" or newer.")]),t._v(" "),e("p",[t._v("Install Istio with telemetry support and Prometheus:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("istioctl manifest apply --set "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("profile")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("default\n")])])]),e("p",[t._v("Install Flagger using Kustomize (kubectl 1.14) in the "),e("code",[t._v("istio-system")]),t._v(" namespace:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/istio\n")])])]),e("p",[t._v("Create an ingress gateway to expose the demo app outside of the mesh:")]),t._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" networking.istio.io/v1alpha3\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" Gateway\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" public"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("gateway\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" istio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("system\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("selector")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("istio")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ingressgateway\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("servers")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("port")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("number")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("80")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("protocol")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" HTTP\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("hosts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"*"')]),t._v("\n")])])]),e("h2",{attrs:{id:"bootstrap"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#bootstrap","aria-hidden":"true"}},[t._v("#")]),t._v(" Bootstrap")]),t._v(" "),e("p",[t._v("Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler (HPA),\nthen creates a series of objects (Kubernetes deployments, ClusterIP services,\nIstio destination rules and virtual services).\nThese objects expose the application inside the mesh and drive the canary analysis and promotion.")]),t._v(" "),e("p",[t._v("Create a test namespace with Istio sidecar injection enabled:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl create ns "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v("\nkubectl label namespace "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" istio-injection"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("enabled\n")])])]),e("p",[t._v("Create a deployment and a horizontal pod autoscaler:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/podinfo\n")])])]),e("p",[t._v("Deploy the load testing service to generate traffic during the canary analysis:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl apply -k github.com/weaveworks/flagger//kustomize/tester\n")])])]),e("p",[t._v("Create a canary custom resource (replace example.com with your own domain):")]),t._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" flagger.app/v1beta1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" Canary\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" test\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# deployment reference")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("targetRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" apps/v1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" Deployment\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# the maximum time in seconds for the canary deployment")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# to make progress before it is rollback (default 600s)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("progressDeadlineSeconds")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("60")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# HPA reference (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("autoscalerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" autoscaling/v2beta1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" HorizontalPodAutoscaler\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("service")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# service port number")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("port")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("9898")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# container port number or name (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("targetPort")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("9898")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Istio gateways (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("gateways")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" public"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("gateway.istio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("system.svc.cluster.local\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Istio virtual service host names (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("hosts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" app.example.com\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Istio traffic policy (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("trafficPolicy")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("tls")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# use ISTIO_MUTUAL when mTLS is enabled")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("mode")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" DISABLE\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Istio retry policy (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("retries")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("attempts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("perTryTimeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("retryOn")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"gateway-error,connect-failure,refused-stream"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("analysis")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# schedule interval (default 60s)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# max number of failed metric checks before rollback")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("threshold")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# max traffic percentage routed to canary")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# percentage (0-100)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("maxWeight")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# canary increment step")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# percentage (0-100)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("stepWeight")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metrics")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("success"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("rate\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# minimum req success rate (non 5xx responses)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# percentage (0-100)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("min")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("99")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("duration\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# maximum req duration P99")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# milliseconds")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("max")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 30s\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# testing (optional)")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("webhooks")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" acceptance"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pre"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("rollout\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 30s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bash\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"curl -sd 'test' http://podinfo-canary:9898/token | grep token\"")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" load"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 5s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/"')]),t._v("\n")])])]),e("p",[t._v("Save the above resource as podinfo-canary.yaml and then apply it:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl apply -f ./podinfo-canary.yaml\n")])])]),e("p",[t._v("When the canary analysis starts, Flagger will call the pre-rollout webhooks before routing traffic to the canary.\nThe canary analysis will run for five minutes while validating the HTTP metrics and rollout hooks every minute.")]),t._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-canary-hpa.png",alt:"Flagger Canary Process"}})]),t._v(" "),e("p",[t._v("After a couple of seconds Flagger will create the canary objects:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# applied ")]),t._v("\ndeployment.apps/podinfo\nhorizontalpodautoscaler.autoscaling/podinfo\ncanary.flagger.app/podinfo\n\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# generated ")]),t._v("\ndeployment.apps/podinfo-primary\nhorizontalpodautoscaler.autoscaling/podinfo-primary\nservice/podinfo\nservice/podinfo-canary\nservice/podinfo-primary\ndestinationrule.networking.istio.io/podinfo-canary\ndestinationrule.networking.istio.io/podinfo-primary\nvirtualservice.networking.istio.io/podinfo\n")])])]),e("h2",{attrs:{id:"automated-canary-promotion"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-canary-promotion","aria-hidden":"true"}},[t._v("#")]),t._v(" Automated canary promotion")]),t._v(" "),e("p",[t._v("Trigger a canary deployment by updating the container image:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl -n "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" image deployment/podinfo "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("podinfod")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("stefanprodan/podinfo:3.1.1\n")])])]),e("p",[t._v("Flagger detects that the deployment revision changed and starts a new rollout:")]),t._v(" "),e("div",{staticClass:"language-text extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("kubectl -n test describe canary/podinfo\n\nStatus:\n Canary Weight: 0\n Failed Checks: 0\n Phase: Succeeded\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Synced 3m flagger New revision detected podinfo.test\n Normal Synced 3m flagger Scaling up podinfo.test\n Warning Synced 3m flagger Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available\n Normal Synced 3m flagger Advance podinfo.test canary weight 5\n Normal Synced 3m flagger Advance podinfo.test canary weight 10\n Normal Synced 3m flagger Advance podinfo.test canary weight 15\n Normal Synced 2m flagger Advance podinfo.test canary weight 20\n Normal Synced 2m flagger Advance podinfo.test canary weight 25\n Normal Synced 1m flagger Advance podinfo.test canary weight 30\n Normal Synced 1m flagger Advance podinfo.test canary weight 35\n Normal Synced 55s flagger Advance podinfo.test canary weight 40\n Normal Synced 45s flagger Advance podinfo.test canary weight 45\n Normal Synced 35s flagger Advance podinfo.test canary weight 50\n Normal Synced 25s flagger Copying podinfo.test template spec to podinfo-primary.test\n Warning Synced 15s flagger Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available\n Normal Synced 5s flagger Promotion completed! Scaling down podinfo.test\n")])])]),e("p",[e("strong",[t._v("Note")]),t._v(" that if you apply new changes to the deployment during the canary analysis, Flagger will restart the analysis.")]),t._v(" "),e("p",[t._v("A canary deployment is triggered by changes in any of the following objects:")]),t._v(" "),e("ul",[e("li",[t._v("Deployment PodSpec (container image, command, ports, env, resources, etc)")]),t._v(" "),e("li",[t._v("ConfigMaps mounted as volumes or mapped to environment variables")]),t._v(" "),e("li",[t._v("Secrets mounted as volumes or mapped to environment variables")])]),t._v(" "),e("p",[t._v("You can monitor all canaries with:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("watch")]),t._v(" kubectl get canaries --all-namespaces\n\nNAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME\n"),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" podinfo Progressing "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("15")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2019")]),t._v("-01-16T14:05:07Z\nprod frontend Succeeded "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2019")]),t._v("-01-15T16:15:07Z\nprod backend Failed "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2019")]),t._v("-01-14T17:05:07Z\n")])])]),e("h2",{attrs:{id:"automated-rollback"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-rollback","aria-hidden":"true"}},[t._v("#")]),t._v(" Automated rollback")]),t._v(" "),e("p",[t._v("During the canary analysis you can generate HTTP 500 errors and high latency to test if Flagger pauses the rollout.")]),t._v(" "),e("p",[t._v("Trigger another canary deployment:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl -n "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" image deployment/podinfo "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("podinfod")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("stefanprodan/podinfo:3.1.2\n")])])]),e("p",[t._v("Exec into the load tester pod with:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("kubectl -n "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("test")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("exec")]),t._v(" -it flagger-loadtester-xx-xx "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("sh")]),t._v("\n")])])]),e("p",[t._v("Generate HTTP 500 errors:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("watch")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("curl")]),t._v(" http://podinfo-canary:9898/status/500\n")])])]),e("p",[t._v("Generate latency:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("watch")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("curl")]),t._v(" http://podinfo-canary:9898/delay/1\n")])])]),e("p",[t._v("When the number of failed checks reaches the canary analysis threshold, the traffic is routed back to the primary,\nthe canary is scaled to zero and the rollout is marked as failed.")]),t._v(" "),e("div",{staticClass:"language-text extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("kubectl -n test describe canary/podinfo\n\nStatus:\n Canary Weight: 0\n Failed Checks: 10\n Phase: Failed\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Synced 3m flagger Starting canary deployment for podinfo.test\n Normal Synced 3m flagger Advance podinfo.test canary weight 5\n Normal Synced 3m flagger Advance podinfo.test canary weight 10\n Normal Synced 3m flagger Advance podinfo.test canary weight 15\n Normal Synced 3m flagger Halt podinfo.test advancement success rate 69.17% < 99%\n Normal Synced 2m flagger Halt podinfo.test advancement success rate 61.39% < 99%\n Normal Synced 2m flagger Halt podinfo.test advancement success rate 55.06% < 99%\n Normal Synced 2m flagger Halt podinfo.test advancement success rate 47.00% < 99%\n Normal Synced 2m flagger (combined from similar events): Halt podinfo.test advancement success rate 38.08% < 99%\n Warning Synced 1m flagger Rolling back podinfo.test failed checks threshold reached 10\n Warning Synced 1m flagger Canary failed! Scaling down podinfo.test\n")])])]),e("h2",{attrs:{id:"traffic-mirroring"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#traffic-mirroring","aria-hidden":"true"}},[t._v("#")]),t._v(" Traffic mirroring")]),t._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-canary-traffic-mirroring.png",alt:"Flagger Canary Traffic Shadowing"}})]),t._v(" "),e("p",[t._v("For applications that perform read operations, Flagger can be configured to drive canary releases with traffic mirroring.\nIstio traffic mirroring will copy each incoming request, sending one request to the primary and one to the canary service.\nThe response from the primary is sent back to the user and the response from the canary is discarded.\nMetrics are collected on both requests so that the deployment will only proceed if the canary metrics are within the threshold values.")]),t._v(" "),e("p",[t._v("Note that mirroring should be used for requests that are "),e("strong",[t._v("idempotent")]),t._v(" or capable of being processed twice (once by the primary and once by the canary).")]),t._v(" "),e("p",[t._v("You can enable mirroring by replacing "),e("code",[t._v("stepWeight/maxWeight")]),t._v(" with "),e("code",[t._v("iterations")]),t._v(" and by setting "),e("code",[t._v("analysis.mirror")]),t._v(" to "),e("code",[t._v("true")]),t._v(":")]),t._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" flagger.app/v1beta1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" Canary\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" podinfo\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" test\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("analysis")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# schedule interval")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# max number of failed metric checks before rollback")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("threshold")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# total number of iterations")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("iterations")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# enable traffic shadowing ")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("mirror")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean important"}},[t._v("true")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metrics")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("success"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("rate\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("min")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("99")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("duration\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("thresholdRange")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("max")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("interval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("webhooks")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" acceptance"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pre"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("rollout\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 30s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bash\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"curl -sd 'test' http://podinfo-canary:9898/token | grep token\"")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" load"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("test\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("url")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("//flagger"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("loadtester.test/\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("timeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" 5s\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("cmd")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"')]),t._v("\n")])])]),e("p",[t._v("With the above configuration, Flagger will run a canary release with the following steps:")]),t._v(" "),e("ul",[e("li",[t._v("detect new revision (deployment spec, secrets or configmaps changes)")]),t._v(" "),e("li",[t._v("scale from zero the canary deployment")]),t._v(" "),e("li",[t._v("wait for the HPA to set the canary minimum replicas")]),t._v(" "),e("li",[t._v("check canary pods health")]),t._v(" "),e("li",[t._v("run the acceptance tests")]),t._v(" "),e("li",[t._v("abort the canary release if tests fail")]),t._v(" "),e("li",[t._v("start the load tests")]),t._v(" "),e("li",[t._v("mirror traffic from primary to canary")]),t._v(" "),e("li",[t._v("check request success rate and request duration every minute")]),t._v(" "),e("li",[t._v("abort the canary release if the metrics check failure threshold is reached")]),t._v(" "),e("li",[t._v("stop traffic mirroring after the number of iterations is reached")]),t._v(" "),e("li",[t._v("route live traffic to the canary pods")]),t._v(" "),e("li",[t._v("promote the canary (update the primary secrets, configmaps and deployment spec)")]),t._v(" "),e("li",[t._v("wait for the primary deployment rollout to finish")]),t._v(" "),e("li",[t._v("wait for the HPA to set the primary minimum replicas")]),t._v(" "),e("li",[t._v("check primary pods health")]),t._v(" "),e("li",[t._v("switch live traffic back to primary")]),t._v(" "),e("li",[t._v("scale to zero the canary")]),t._v(" "),e("li",[t._v("send notification with the canary analysis result")])]),t._v(" "),e("p",[t._v("The above procedure can be extended with "),e("router-link",{attrs:{to:"/usage/metrics.html"}},[t._v("custom metrics")]),t._v(" checks,\n"),e("router-link",{attrs:{to:"/usage/webhooks.html"}},[t._v("webhooks")]),t._v(",\n"),e("router-link",{attrs:{to:"/usage/webhooks.html#manual-gating"}},[t._v("manual promotion")]),t._v(" approval and\n"),e("router-link",{attrs:{to:"/usage/alerting.html"}},[t._v("Slack or MS Teams")]),t._v(" notifications.")],1)])},[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/29.17c547e6.js b/assets/js/29.ce4011f4.js similarity index 79% rename from assets/js/29.17c547e6.js rename to assets/js/29.ce4011f4.js index 4755337d..7ef8af3f 100644 --- a/assets/js/29.17c547e6.js +++ b/assets/js/29.ce4011f4.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{289:function(t,e,n){"use strict";n.r(e);var s=n(37),l=Object(s.a)({},function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})},[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{290:function(t,e,n){"use strict";n.r(e);var s=n(37),l=Object(s.a)({},function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})},[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/30.38bd809e.js b/assets/js/30.edda19d9.js similarity index 99% rename from assets/js/30.38bd809e.js rename to assets/js/30.edda19d9.js index 321599ef..ec1e64a3 100644 --- a/assets/js/30.38bd809e.js +++ b/assets/js/30.edda19d9.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{290:function(a,t,e){"use strict";e.r(t);var s=e(37),n=Object(s.a)({},function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"alerting"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#alerting","aria-hidden":"true"}},[a._v("#")]),a._v(" Alerting")]),a._v(" "),e("p",[a._v("Flagger can be configured to send alerts to various chat platforms. You can define a global alert provider at\ninstall time or configure alerts on a per canary basis.")]),a._v(" "),e("h2",{attrs:{id:"global-configuration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#global-configuration","aria-hidden":"true"}},[a._v("#")]),a._v(" Global configuration")]),a._v(" "),e("p",[a._v("Flagger can be configured to send Slack notifications:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("helm upgrade -i flagger flagger/flagger "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.url"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.channel"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("general "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.user"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("flagger\n")])])]),e("p",[a._v("Once configured with a Slack incoming "),e("strong",[a._v("webhook")]),a._v(", Flagger will post messages when a canary deployment\nhas been initialised, when a new revision has been detected and if the canary analysis failed or succeeded.")]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/screens/slack-canary-notifications.png",alt:"Slack Notifications"}})]),a._v(" "),e("p",[a._v("A canary deployment will be rolled back if the progress deadline exceeded or if the analysis reached the\nmaximum number of failed checks:")]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/screens/slack-canary-failed.png",alt:"Slack Notifications"}})]),a._v(" "),e("p",[a._v("Flagger can be configured to send notifications to Microsoft Teams:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("helm upgrade -i flagger flagger/flagger "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set msteams.url"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK\n")])])]),e("p",[a._v("Similar to Slack, Flagger alerts on canary analysis events:")]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/screens/flagger-ms-teams-notifications.png",alt:"MS Teams Notifications"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/screens/flagger-ms-teams-failed.png",alt:"MS Teams Notifications"}})]),a._v(" "),e("h2",{attrs:{id:"canary-configuration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#canary-configuration","aria-hidden":"true"}},[a._v("#")]),a._v(" Canary configuration")]),a._v(" "),e("p",[a._v("Configuring alerting globally has several limitations as it's not possible to specify different channels\nor configure the verbosity on a per canary basis.\nTo make the alerting move flexible, the canary analysis can be extended\nwith a list of alerts that reference an alert provider.\nFor each alert, users can configure the severity level.\nThe alerts section overrides the global setting.")]),a._v(" "),e("p",[a._v("Slack example:")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger.app/v1beta1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" AlertProvider\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" slack\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("channel")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("alerts\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("username")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# webhook address (ignored if secretRef is specified)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("address")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" https"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("//hooks.slack.com/services/YOUR/SLACK/WEBHOOK\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# secret containing the webhook address (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("secretRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("url\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("---")]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" v1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Secret\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("url\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("data")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("address")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" ")]),a._v("\n")])])]),e("p",[a._v("The alert provider "),e("strong",[a._v("type")]),a._v(" can be: "),e("code",[a._v("slack")]),a._v(", "),e("code",[a._v("msteams")]),a._v(", "),e("code",[a._v("rocket")]),a._v(" or "),e("code",[a._v("discord")]),a._v(". When set to "),e("code",[a._v("discord")]),a._v(",\nFlagger will use "),e("a",{attrs:{href:"https://birdie0.github.io/discord-webhooks-guide/other/slack_formatting.html",target:"_blank",rel:"noopener noreferrer"}},[a._v("Slack formatting"),e("OutboundLink")],1),a._v("\nand will append "),e("code",[a._v("/slack")]),a._v(" to the Discord address.")]),a._v(" "),e("p",[a._v("When not specified, "),e("strong",[a._v("channel")]),a._v(" defaults to "),e("code",[a._v("general")]),a._v(" and "),e("strong",[a._v("username")]),a._v(" defaults to "),e("code",[a._v("flagger")]),a._v(".")]),a._v(" "),e("p",[a._v("When "),e("strong",[a._v("secretRef")]),a._v(" is specified, the Kubernetes secret must contain a data field named "),e("code",[a._v("address")]),a._v(",\nthe address in the secret will take precedence over the "),e("strong",[a._v("address")]),a._v(" field in the provider spec.")]),a._v(" "),e("p",[a._v("The canary analysis can have a list of alerts, each alert referencing an alert provider:")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("analysis")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("alerts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"on-call Slack"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("severity")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" error\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("providerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"qa Discord"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("severity")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" warn\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("providerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" qa"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("discord\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"dev MS Teams"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("severity")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" info\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("providerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" dev"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("msteams\n")])])]),e("p",[a._v("Alert fields:")]),a._v(" "),e("ul",[e("li",[e("strong",[a._v("name")]),a._v(" (required)")]),a._v(" "),e("li",[e("strong",[a._v("severity")]),a._v(" levels: "),e("code",[a._v("info")]),a._v(", "),e("code",[a._v("warn")]),a._v(", "),e("code",[a._v("error")]),a._v(" (default info)")]),a._v(" "),e("li",[e("strong",[a._v("providerRef.name")]),a._v(" alert provider name (required)")]),a._v(" "),e("li",[e("strong",[a._v("providerRef.namespace")]),a._v(" alert provider namespace (defaults to the canary namespace)")])]),a._v(" "),e("p",[a._v("When the severity is set to "),e("code",[a._v("warn")]),a._v(", Flagger will alert when waiting on manual confirmation or if the analysis fails.\nWhen the severity is set to "),e("code",[a._v("error")]),a._v(", Flagger will alert only if the canary analysis fails.")]),a._v(" "),e("h2",{attrs:{id:"prometheus-alert-manager"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prometheus-alert-manager","aria-hidden":"true"}},[a._v("#")]),a._v(" Prometheus Alert Manager")]),a._v(" "),e("p",[a._v("You can use Alertmanager to trigger alerts when a canary deployment failed:")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[a._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("alert")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" canary_rollback\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("expr")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger_canary_status "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")]),a._v(" 1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("for")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("labels")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("severity")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" warning\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("annotations")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("summary")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"Canary failed"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("description")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"Workload {{ $labels.name }} namespace {{ $labels.namespace }}"')]),a._v("\n")])])])])},[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{289:function(a,t,e){"use strict";e.r(t);var s=e(37),n=Object(s.a)({},function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"alerting"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#alerting","aria-hidden":"true"}},[a._v("#")]),a._v(" Alerting")]),a._v(" "),e("p",[a._v("Flagger can be configured to send alerts to various chat platforms. You can define a global alert provider at\ninstall time or configure alerts on a per canary basis.")]),a._v(" "),e("h2",{attrs:{id:"global-configuration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#global-configuration","aria-hidden":"true"}},[a._v("#")]),a._v(" Global configuration")]),a._v(" "),e("p",[a._v("Flagger can be configured to send Slack notifications:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("helm upgrade -i flagger flagger/flagger "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.url"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.channel"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("general "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set slack.user"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("flagger\n")])])]),e("p",[a._v("Once configured with a Slack incoming "),e("strong",[a._v("webhook")]),a._v(", Flagger will post messages when a canary deployment\nhas been initialised, when a new revision has been detected and if the canary analysis failed or succeeded.")]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/screens/slack-canary-notifications.png",alt:"Slack Notifications"}})]),a._v(" "),e("p",[a._v("A canary deployment will be rolled back if the progress deadline exceeded or if the analysis reached the\nmaximum number of failed checks:")]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/screens/slack-canary-failed.png",alt:"Slack Notifications"}})]),a._v(" "),e("p",[a._v("Flagger can be configured to send notifications to Microsoft Teams:")]),a._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[a._v("helm upgrade -i flagger flagger/flagger "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("\\")]),a._v("\n--set msteams.url"),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v("https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK\n")])])]),e("p",[a._v("Similar to Slack, Flagger alerts on canary analysis events:")]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/screens/flagger-ms-teams-notifications.png",alt:"MS Teams Notifications"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"https://raw.githubusercontent.com/weaveworks/flagger/master/docs/screens/flagger-ms-teams-failed.png",alt:"MS Teams Notifications"}})]),a._v(" "),e("h2",{attrs:{id:"canary-configuration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#canary-configuration","aria-hidden":"true"}},[a._v("#")]),a._v(" Canary configuration")]),a._v(" "),e("p",[a._v("Configuring alerting globally has several limitations as it's not possible to specify different channels\nor configure the verbosity on a per canary basis.\nTo make the alerting move flexible, the canary analysis can be extended\nwith a list of alerts that reference an alert provider.\nFor each alert, users can configure the severity level.\nThe alerts section overrides the global setting.")]),a._v(" "),e("p",[a._v("Slack example:")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger.app/v1beta1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" AlertProvider\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("spec")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("type")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" slack\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("channel")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("alerts\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("username")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# webhook address (ignored if secretRef is specified)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("address")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" https"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("//hooks.slack.com/services/YOUR/SLACK/WEBHOOK\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("# secret containing the webhook address (optional)")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("secretRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("url\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("---")]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("apiVersion")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" v1\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("kind")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" Secret\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("metadata")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("url\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger\n"),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("data")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("address")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" ")]),a._v("\n")])])]),e("p",[a._v("The alert provider "),e("strong",[a._v("type")]),a._v(" can be: "),e("code",[a._v("slack")]),a._v(", "),e("code",[a._v("msteams")]),a._v(", "),e("code",[a._v("rocket")]),a._v(" or "),e("code",[a._v("discord")]),a._v(". When set to "),e("code",[a._v("discord")]),a._v(",\nFlagger will use "),e("a",{attrs:{href:"https://birdie0.github.io/discord-webhooks-guide/other/slack_formatting.html",target:"_blank",rel:"noopener noreferrer"}},[a._v("Slack formatting"),e("OutboundLink")],1),a._v("\nand will append "),e("code",[a._v("/slack")]),a._v(" to the Discord address.")]),a._v(" "),e("p",[a._v("When not specified, "),e("strong",[a._v("channel")]),a._v(" defaults to "),e("code",[a._v("general")]),a._v(" and "),e("strong",[a._v("username")]),a._v(" defaults to "),e("code",[a._v("flagger")]),a._v(".")]),a._v(" "),e("p",[a._v("When "),e("strong",[a._v("secretRef")]),a._v(" is specified, the Kubernetes secret must contain a data field named "),e("code",[a._v("address")]),a._v(",\nthe address in the secret will take precedence over the "),e("strong",[a._v("address")]),a._v(" field in the provider spec.")]),a._v(" "),e("p",[a._v("The canary analysis can have a list of alerts, each alert referencing an alert provider:")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("analysis")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("alerts")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"on-call Slack"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("severity")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" error\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("providerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" on"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("call\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("namespace")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"qa Discord"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("severity")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" warn\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("providerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" qa"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("discord\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"dev MS Teams"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("severity")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" info\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("providerRef")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" dev"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v("msteams\n")])])]),e("p",[a._v("Alert fields:")]),a._v(" "),e("ul",[e("li",[e("strong",[a._v("name")]),a._v(" (required)")]),a._v(" "),e("li",[e("strong",[a._v("severity")]),a._v(" levels: "),e("code",[a._v("info")]),a._v(", "),e("code",[a._v("warn")]),a._v(", "),e("code",[a._v("error")]),a._v(" (default info)")]),a._v(" "),e("li",[e("strong",[a._v("providerRef.name")]),a._v(" alert provider name (required)")]),a._v(" "),e("li",[e("strong",[a._v("providerRef.namespace")]),a._v(" alert provider namespace (defaults to the canary namespace)")])]),a._v(" "),e("p",[a._v("When the severity is set to "),e("code",[a._v("warn")]),a._v(", Flagger will alert when waiting on manual confirmation or if the analysis fails.\nWhen the severity is set to "),e("code",[a._v("error")]),a._v(", Flagger will alert only if the canary analysis fails.")]),a._v(" "),e("h2",{attrs:{id:"prometheus-alert-manager"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prometheus-alert-manager","aria-hidden":"true"}},[a._v("#")]),a._v(" Prometheus Alert Manager")]),a._v(" "),e("p",[a._v("You can use Alertmanager to trigger alerts when a canary deployment failed:")]),a._v(" "),e("div",{staticClass:"language-yaml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yaml"}},[e("code",[a._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("-")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("alert")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" canary_rollback\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("expr")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" flagger_canary_status "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")]),a._v(" 1\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("for")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" 1m\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("labels")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("severity")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" warning\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("annotations")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("summary")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"Canary failed"')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[a._v("description")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"Workload {{ $labels.name }} namespace {{ $labels.namespace }}"')]),a._v("\n")])])])])},[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/5.0c32bdf9.js b/assets/js/5.0c32bdf9.js new file mode 100644 index 00000000..44e85859 --- /dev/null +++ b/assets/js/5.0c32bdf9.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{265:function(e,r,t){"use strict";t.r(r);var a=t(37),n=Object(a.a)({},function(){var e=this,r=e.$createElement,t=e._self._c||r;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h2",{attrs:{id:"progressive-delivery"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#progressive-delivery","aria-hidden":"true"}},[e._v("#")]),e._v(" Progressive Delivery")]),e._v(" "),t("p",[e._v("Flagger was designed to give developers confidence in automating production releases with progressive delivery techniques.")]),e._v(" "),t("div",{staticClass:"tip custom-block"},[t("p",{staticClass:"custom-block-title"},[e._v("Canary release")]),e._v(" "),t("p",[e._v("A benefit of using canary releases is the ability to do capacity testing of the new version in a production environment\nwith a safe rollback strategy if issues are found. By slowly ramping up the load, you can monitor and capture metrics\nabout how the new version impacts the production environment.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://martinfowler.com/bliki/CanaryRelease.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Martin Fowler"),t("OutboundLink")],1)])]),e._v(" "),t("p",[e._v("Flagger can run automated application analysis, testing, promotion and rollback for the following deployment strategies:")]),e._v(" "),t("ul",[t("li",[t("p",[t("strong",[e._v("Canary")]),e._v(" (progressive traffic shifting)")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/istio-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Istio"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/linkerd-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Linkerd"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/appmesh-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("App Mesh"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/contour-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Contour"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/gloo-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Gloo"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/nginx-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("NGINX"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/skipper-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Skipper"),t("OutboundLink")],1)])])]),e._v(" "),t("li",[t("p",[t("strong",[e._v("A/B Testing")]),e._v(" (HTTP headers and cookies traffic routing)")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/istio-ab-testing",target:"_blank",rel:"noopener noreferrer"}},[e._v("Istio"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/appmesh-progressive-delivery#a-b-testing",target:"_blank",rel:"noopener noreferrer"}},[e._v("App Mesh"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/contour-progressive-delivery#a-b-testing",target:"_blank",rel:"noopener noreferrer"}},[e._v("Contour"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/nginx-progressive-delivery#a-b-testing",target:"_blank",rel:"noopener noreferrer"}},[e._v("NGINX"),t("OutboundLink")],1)])])]),e._v(" "),t("li",[t("p",[t("strong",[e._v("Blue/Green")]),e._v(" (traffic switching and mirroring)")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/kubernetes-blue-green",target:"_blank",rel:"noopener noreferrer"}},[e._v("Kubernetes CNI"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/istio-progressive-delivery#traffic-mirroring",target:"_blank",rel:"noopener noreferrer"}},[e._v("Istio"),t("OutboundLink")],1),e._v(",\nLinkerd, App Mesh, Contour, Gloo, NGINX")])])])]),e._v(" "),t("p",[e._v("Flagger can be configured to "),t("a",{attrs:{href:"https://docs.flagger.app/usage/alerting",target:"_blank",rel:"noopener noreferrer"}},[e._v("send notifications"),t("OutboundLink")],1),e._v(" to\nSlack, Microsoft Teams, Discord or Rocket.\nIt will post messages when a deployment has been initialised,\nwhen a new revision has been detected and if the canary analysis failed or succeeded.")]),e._v(" "),t("h2",{attrs:{id:"gitops"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#gitops","aria-hidden":"true"}},[e._v("#")]),e._v(" GitOps")]),e._v(" "),t("p",[t("img",{attrs:{src:"/flagger-gitops.png",alt:"GtiOps with Flagger and FluxCD"}})]),e._v(" "),t("p",[e._v("You can build fully automated GitOps pipelines for canary deployments with Flagger and\n"),t("a",{attrs:{href:"https://github.com/fluxcd/flux",target:"_blank",rel:"noopener noreferrer"}},[e._v("FluxCD"),t("OutboundLink")],1),e._v(" (CNCF sandbox project).")]),e._v(" "),t("div",{staticClass:"tip custom-block"},[t("p",{staticClass:"custom-block-title"},[e._v("GitOps")]),e._v(" "),t("p",[e._v("GitOps is a way to do Kubernetes cluster management and application delivery.\nIt works by using Git as a single source of truth for declarative infrastructure and applications.\nWith Git at the center of your delivery pipelines, developers can make pull requests\nto accelerate and simplify application deployments and operations tasks to Kubernetes.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://www.weave.works/technologies/gitops/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Weaveworks"),t("OutboundLink")],1)])]),e._v(" "),t("p",[e._v("GitOps tutorials:")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/stefanprodan/gitops-istio",target:"_blank",rel:"noopener noreferrer"}},[e._v("Progressive Delivery for Istio with Flagger and FluxCD"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://eks.handson.flagger.dev",target:"_blank",rel:"noopener noreferrer"}},[e._v("Progressive Delivery for AWS App Mesh with Flagger and FluxCD"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://helm.workshop.flagger.dev",target:"_blank",rel:"noopener noreferrer"}},[e._v("Progressive Delivery for Linkerd with Flagger, FluxCD and Helm v3"),t("OutboundLink")],1)])]),e._v(" "),t("h2",{attrs:{id:"getting-help"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#getting-help","aria-hidden":"true"}},[e._v("#")]),e._v(" Getting Help")]),e._v(" "),t("p",[e._v("If you have any questions about Flagger and progressive delivery:")]),e._v(" "),t("ul",[t("li",[e._v("Read the Flagger "),t("a",{attrs:{href:"https://docs.flagger.app",target:"_blank",rel:"noopener noreferrer"}},[e._v("docs"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("li",[e._v("Invite yourself to the "),t("a",{attrs:{href:"https://slack.weave.works/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Weave community slack"),t("OutboundLink")],1),e._v("\nand join the "),t("a",{attrs:{href:"https://weave-community.slack.com/messages/flagger/",target:"_blank",rel:"noopener noreferrer"}},[e._v("#flagger"),t("OutboundLink")],1),e._v(" channel.")]),e._v(" "),t("li",[e._v("Join the "),t("a",{attrs:{href:"https://www.meetup.com/pro/Weave/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Weave User Group"),t("OutboundLink")],1),e._v(" and get invited to online talks,\nhands-on training and meetups in your area.")]),e._v(" "),t("li",[e._v("File an "),t("a",{attrs:{href:"https://github.com/weaveworks/flagger/issues/new",target:"_blank",rel:"noopener noreferrer"}},[e._v("issue"),t("OutboundLink")],1),e._v(".")])]),e._v(" "),t("p",[e._v("Your feedback is always welcome!")])])},[],!1,null,null,null);r.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/5.f0e04ff6.js b/assets/js/5.f0e04ff6.js deleted file mode 100644 index cba88192..00000000 --- a/assets/js/5.f0e04ff6.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{265:function(e,r,t){"use strict";t.r(r);var a=t(37),n=Object(a.a)({},function(){var e=this,r=e.$createElement,t=e._self._c||r;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h2",{attrs:{id:"progressive-delivery"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#progressive-delivery","aria-hidden":"true"}},[e._v("#")]),e._v(" Progressive Delivery")]),e._v(" "),t("p",[e._v("Flagger was designed to give developers confidence in automating production releases with progressive delivery techniques.")]),e._v(" "),t("div",{staticClass:"tip custom-block"},[t("p",{staticClass:"custom-block-title"},[e._v("Canary release")]),e._v(" "),t("p",[e._v("A benefit of using canary releases is the ability to do capacity testing of the new version in a production environment\nwith a safe rollback strategy if issues are found. By slowly ramping up the load, you can monitor and capture metrics\nabout how the new version impacts the production environment.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://martinfowler.com/bliki/CanaryRelease.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Martin Fowler"),t("OutboundLink")],1)])]),e._v(" "),t("p",[e._v("Flagger can run automated application analysis, testing, promotion and rollback for the following deployment strategies:")]),e._v(" "),t("ul",[t("li",[t("p",[t("strong",[e._v("Canary")]),e._v(" (progressive traffic shifting)")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/istio-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Istio"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/linkerd-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Linkerd"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/appmesh-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("App Mesh"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/contour-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Contour"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/gloo-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("Gloo"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/nginx-progressive-delivery",target:"_blank",rel:"noopener noreferrer"}},[e._v("NGINX"),t("OutboundLink")],1)])])]),e._v(" "),t("li",[t("p",[t("strong",[e._v("A/B Testing")]),e._v(" (HTTP headers and cookies traffic routing)")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/istio-ab-testing",target:"_blank",rel:"noopener noreferrer"}},[e._v("Istio"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/appmesh-progressive-delivery#a-b-testing",target:"_blank",rel:"noopener noreferrer"}},[e._v("App Mesh"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/contour-progressive-delivery#a-b-testing",target:"_blank",rel:"noopener noreferrer"}},[e._v("Contour"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/nginx-progressive-delivery#a-b-testing",target:"_blank",rel:"noopener noreferrer"}},[e._v("NGINX"),t("OutboundLink")],1)])])]),e._v(" "),t("li",[t("p",[t("strong",[e._v("Blue/Green")]),e._v(" (traffic switching and mirroring)")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.flagger.app/tutorials/kubernetes-blue-green",target:"_blank",rel:"noopener noreferrer"}},[e._v("Kubernetes CNI"),t("OutboundLink")],1),e._v(",\n"),t("a",{attrs:{href:"https://docs.flagger.app/tutorials/istio-progressive-delivery#traffic-mirroring",target:"_blank",rel:"noopener noreferrer"}},[e._v("Istio"),t("OutboundLink")],1),e._v(",\nLinkerd, App Mesh, Contour, Gloo, NGINX")])])])]),e._v(" "),t("p",[e._v("Flagger can be configured to "),t("a",{attrs:{href:"https://docs.flagger.app/usage/alerting",target:"_blank",rel:"noopener noreferrer"}},[e._v("send notifications"),t("OutboundLink")],1),e._v(" to\nSlack, Microsoft Teams, Discord or Rocket.\nIt will post messages when a deployment has been initialised,\nwhen a new revision has been detected and if the canary analysis failed or succeeded.")]),e._v(" "),t("h2",{attrs:{id:"gitops"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#gitops","aria-hidden":"true"}},[e._v("#")]),e._v(" GitOps")]),e._v(" "),t("p",[t("img",{attrs:{src:"/flagger-gitops.png",alt:"GtiOps with Flagger and FluxCD"}})]),e._v(" "),t("p",[e._v("You can build fully automated GitOps pipelines for canary deployments with Flagger and\n"),t("a",{attrs:{href:"https://github.com/fluxcd/flux",target:"_blank",rel:"noopener noreferrer"}},[e._v("FluxCD"),t("OutboundLink")],1),e._v(" (CNCF sandbox project).")]),e._v(" "),t("div",{staticClass:"tip custom-block"},[t("p",{staticClass:"custom-block-title"},[e._v("GitOps")]),e._v(" "),t("p",[e._v("GitOps is a way to do Kubernetes cluster management and application delivery.\nIt works by using Git as a single source of truth for declarative infrastructure and applications.\nWith Git at the center of your delivery pipelines, developers can make pull requests\nto accelerate and simplify application deployments and operations tasks to Kubernetes.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://www.weave.works/technologies/gitops/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Weaveworks"),t("OutboundLink")],1)])]),e._v(" "),t("p",[e._v("GitOps tutorials:")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/stefanprodan/gitops-istio",target:"_blank",rel:"noopener noreferrer"}},[e._v("Progressive Delivery for Istio with Flagger and FluxCD"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://eks.handson.flagger.dev",target:"_blank",rel:"noopener noreferrer"}},[e._v("Progressive Delivery for AWS App Mesh with Flagger and FluxCD"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://helm.workshop.flagger.dev",target:"_blank",rel:"noopener noreferrer"}},[e._v("Progressive Delivery for Linkerd with Flagger, FluxCD and Helm v3"),t("OutboundLink")],1)])]),e._v(" "),t("h2",{attrs:{id:"getting-help"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#getting-help","aria-hidden":"true"}},[e._v("#")]),e._v(" Getting Help")]),e._v(" "),t("p",[e._v("If you have any questions about Flagger and progressive delivery:")]),e._v(" "),t("ul",[t("li",[e._v("Read the Flagger "),t("a",{attrs:{href:"https://docs.flagger.app",target:"_blank",rel:"noopener noreferrer"}},[e._v("docs"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("li",[e._v("Invite yourself to the "),t("a",{attrs:{href:"https://slack.weave.works/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Weave community slack"),t("OutboundLink")],1),e._v("\nand join the "),t("a",{attrs:{href:"https://weave-community.slack.com/messages/flagger/",target:"_blank",rel:"noopener noreferrer"}},[e._v("#flagger"),t("OutboundLink")],1),e._v(" channel.")]),e._v(" "),t("li",[e._v("Join the "),t("a",{attrs:{href:"https://www.meetup.com/pro/Weave/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Weave User Group"),t("OutboundLink")],1),e._v(" and get invited to online talks,\nhands-on training and meetups in your area.")]),e._v(" "),t("li",[e._v("File an "),t("a",{attrs:{href:"https://github.com/weaveworks/flagger/issues/new",target:"_blank",rel:"noopener noreferrer"}},[e._v("issue"),t("OutboundLink")],1),e._v(".")])]),e._v(" "),t("p",[e._v("Your feedback is always welcome!")])])},[],!1,null,null,null);r.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/app.67d16e10.js b/assets/js/app.9b46ae46.js similarity index 86% rename from assets/js/app.67d16e10.js rename to assets/js/app.9b46ae46.js index a0e1e10e..dceedae9 100644 --- a/assets/js/app.67d16e10.js +++ b/assets/js/app.9b46ae46.js @@ -1,8 +1,8 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,s=e[0],u=e[1],c=e[2],f=0,p=[];f0?o(r(t),9007199254740991):0}},function(t,e,n){var r=n(7),o=n(17),i=n(22),a=n(41)("src"),s=n(143),u=(""+s).split("toString");n(28).inspectSource=function(t){return s.call(t)},(t.exports=function(t,e,n,s){var c="function"==typeof n;c&&(i(n,"name")||o(n,"name",e)),t[e]!==n&&(c&&(i(n,a)||o(n,a,t[e]?""+t[e]:u.join(String(e)))),t===r?t[e]=n:s?t[e]?t[e]=n:o(t,e,n):(delete t[e],o(t,e,n)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[a]||s.call(this)})},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e,n){var r=n(45);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}}},function(t,e){t.exports={}},function(t,e,n){var r=n(165),o=n(68);t.exports=function(t){return r(o(t))}},function(t,e){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},function(t,e,n){"use strict";var r=n(16);t.exports=function(t,e){return!!t&&r(function(){e?t.call(null,function(){},1):t.call(null)})}},function(t,e){var n=t.exports={version:"2.6.9"};"number"==typeof __e&&(__e=n)},function(t,e,n){var r=n(88);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}}},function(t,e,n){var r=n(26);t.exports=function(t){return Object(r(t))}},function(t,e){t.exports={}},function(t,e,n){var r=n(58),o=n(26);t.exports=function(t){return r(o(t))}},function(t,e){t.exports=!0},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e,n){"use strict";function r(t,e,n,r,o,i,a,s){var u,c="function"==typeof t?t.options:t;if(e&&(c.render=e,c.staticRenderFns=n,c._compiled=!0),r&&(c.functional=!0),i&&(c._scopeId="data-v-"+i),a?(u=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},c._ssrRegister=u):o&&(u=s?function(){o.call(this,this.$root.$options.shadowRoot)}:o),u)if(c.functional){c._injectStyles=u;var l=c.render;c.render=function(t,e){return u.call(e),l(t,e)}}else{var f=c.beforeCreate;c.beforeCreate=f?[].concat(f,u):[u]}return{exports:t,options:c}}n.d(e,"a",function(){return r})},function(t,e,n){for(var r=n(146),o=n(61),i=n(21),a=n(7),s=n(17),u=n(31),c=n(2),l=c("iterator"),f=c("toStringTag"),p=u.Array,h={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},d=o(h),v=0;v0?r:n)(t)}},function(t,e,n){"use strict";var r=n(162)(!0);n(101)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,e=this._t,n=this._i;return n>=e.length?{value:void 0,done:!0}:(t=r(e,n),this._i+=t.length,{value:t,done:!1})})},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+r).toString(36))}},function(t,e,n){var r=n(9).f,o=n(19),i=n(4)("toStringTag");t.exports=function(t,e,n){t&&!o(t=n?t:t.prototype,i)&&r(t,i,{configurable:!0,value:e})}},function(t,e,n){var r=n(68);t.exports=function(t){return Object(r(t))}},function(t,e,n){var r=n(12).f,o=Function.prototype,i=/^\s*function ([^ (]*)/;"name"in o||n(13)&&r(o,"name",{configurable:!0,get:function(){try{return(""+this).match(i)[1]}catch(t){return""}}})},function(t,e,n){},function(t,e,n){"use strict";var r=n(127),o=n.n(r);var i=n(128),a=n.n(i),s=n(129),u=n.n(s);function c(t){return function(t){if(o()(t)){for(var e=0,n=new Array(t.length);e0?o(r(t),9007199254740991):0}},function(t,e,n){var r=n(7),o=n(17),i=n(22),a=n(41)("src"),s=n(143),u=(""+s).split("toString");n(28).inspectSource=function(t){return s.call(t)},(t.exports=function(t,e,n,s){var c="function"==typeof n;c&&(i(n,"name")||o(n,"name",e)),t[e]!==n&&(c&&(i(n,a)||o(n,a,t[e]?""+t[e]:u.join(String(e)))),t===r?t[e]=n:s?t[e]?t[e]=n:o(t,e,n):(delete t[e],o(t,e,n)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[a]||s.call(this)})},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e,n){var r=n(45);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}}},function(t,e){t.exports={}},function(t,e,n){var r=n(165),o=n(68);t.exports=function(t){return r(o(t))}},function(t,e){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},function(t,e,n){"use strict";var r=n(16);t.exports=function(t,e){return!!t&&r(function(){e?t.call(null,function(){},1):t.call(null)})}},function(t,e){var n=t.exports={version:"2.6.9"};"number"==typeof __e&&(__e=n)},function(t,e,n){var r=n(88);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}}},function(t,e,n){var r=n(26);t.exports=function(t){return Object(r(t))}},function(t,e){t.exports={}},function(t,e,n){var r=n(58),o=n(26);t.exports=function(t){return r(o(t))}},function(t,e){t.exports=!0},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e,n){"use strict";function r(t,e,n,r,o,i,a,s){var u,c="function"==typeof t?t.options:t;if(e&&(c.render=e,c.staticRenderFns=n,c._compiled=!0),r&&(c.functional=!0),i&&(c._scopeId="data-v-"+i),a?(u=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},c._ssrRegister=u):o&&(u=s?function(){o.call(this,this.$root.$options.shadowRoot)}:o),u)if(c.functional){c._injectStyles=u;var l=c.render;c.render=function(t,e){return u.call(e),l(t,e)}}else{var f=c.beforeCreate;c.beforeCreate=f?[].concat(f,u):[u]}return{exports:t,options:c}}n.d(e,"a",function(){return r})},function(t,e,n){for(var r=n(146),o=n(61),i=n(21),a=n(7),s=n(17),u=n(31),c=n(2),l=c("iterator"),f=c("toStringTag"),p=u.Array,h={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},d=o(h),v=0;v0?r:n)(t)}},function(t,e,n){"use strict";var r=n(162)(!0);n(101)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,e=this._t,n=this._i;return n>=e.length?{value:void 0,done:!0}:(t=r(e,n),this._i+=t.length,{value:t,done:!1})})},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+r).toString(36))}},function(t,e,n){var r=n(9).f,o=n(19),i=n(4)("toStringTag");t.exports=function(t,e,n){t&&!o(t=n?t:t.prototype,i)&&r(t,i,{configurable:!0,value:e})}},function(t,e,n){var r=n(68);t.exports=function(t){return Object(r(t))}},function(t,e,n){var r=n(12).f,o=Function.prototype,i=/^\s*function ([^ (]*)/;"name"in o||n(13)&&r(o,"name",{configurable:!0,get:function(){try{return(""+this).match(i)[1]}catch(t){return""}}})},function(t,e,n){},function(t,e,n){"use strict";var r=n(127),o=n.n(r);var i=n(128),a=n.n(i),s=n(129),u=n.n(s);function c(t){return function(t){if(o()(t)){for(var e=0,n=new Array(t.length);e
'};function o(t,e,n){return tn?n:t}function i(t){return 100*(-1+t)}n.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(r[e]=n);return this},n.status=null,n.set=function(t){var e=n.isStarted();t=o(t,r.minimum,1),n.status=1===t?null:t;var u=n.render(!e),c=u.querySelector(r.barSelector),l=r.speed,f=r.easing;return u.offsetWidth,a(function(e){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(c,function(t,e,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(t)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(t)+"%,0)"}:{"margin-left":i(t)+"%"}).transition="all "+e+"ms "+n,o}(t,l,f)),1===t?(s(u,{transition:"none",opacity:1}),u.offsetWidth,setTimeout(function(){s(u,{transition:"all "+l+"ms linear",opacity:0}),setTimeout(function(){n.remove(),e()},l)},l)):setTimeout(e,l)}),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var t=function(){setTimeout(function(){n.status&&(n.trickle(),t())},r.trickleSpeed)};return r.trickle&&t(),this},n.done=function(t){return t||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(t){var e=n.status;return e?("number"!=typeof t&&(t=(1-e)*o(Math.random()*e,.1,.95)),e=o(e+t,0,.994),n.set(e)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},t=0,e=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===e&&n.start(),t++,e++,r.always(function(){0==--e?(t=0,n.done()):n.set((t-e)/t)}),this):this},n.render=function(t){if(n.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var e=document.createElement("div");e.id="nprogress",e.innerHTML=r.template;var o,a=e.querySelector(r.barSelector),u=t?"-100":i(n.status||0),l=document.querySelector(r.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+u+"%,0,0)"}),r.showSpinner||(o=e.querySelector(r.spinnerSelector))&&p(o),l!=document.body&&c(l,"nprogress-custom-parent"),l.appendChild(e),e},n.remove=function(){l(document.documentElement,"nprogress-busy"),l(document.querySelector(r.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&p(t)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var a=function(){var t=[];function e(){var n=t.shift();n&&n(e)}return function(n){t.push(n),1==t.length&&e()}}(),s=function(){var t=["Webkit","O","Moz","ms"],e={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(t,e){return e.toUpperCase()}),e[n]||(e[n]=function(e){var n=document.body.style;if(e in n)return e;for(var r,o=t.length,i=e.charAt(0).toUpperCase()+e.slice(1);o--;)if((r=t[o]+i)in n)return r;return e}(n))}function r(t,e,r){e=n(e),t.style[e]=r}return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();function u(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function c(t,e){var n=f(t),r=n+e;u(n,e)||(t.className=r.substring(1))}function l(t,e){var n,r=f(t);u(t,e)&&(n=r.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function p(t){t&&t.parentNode&&t.parentNode.removeChild(t)}return n})?r.call(e,n,e,t):r)||(t.exports=o)},function(t,e,n){"use strict";var r=n(1),o=n(55)(1);r(r.P+r.F*!n(27)([].map,!0),"Array",{map:function(t){return o(this,t,arguments[1])}})},function(t,e,n){var r=n(29),o=n(58),i=n(30),a=n(20),s=n(144);t.exports=function(t,e){var n=1==t,u=2==t,c=3==t,l=4==t,f=6==t,p=5==t||f,h=e||s;return function(e,s,d){for(var v,m,y=i(e),g=o(y),b=r(s,d,3),_=a(g.length),w=0,x=n?h(e,_):u?h(e,0):void 0;_>w;w++)if((p||w in g)&&(m=b(v=g[w],w,y),t))if(n)x[w]=m;else if(m)switch(t){case 3:return!0;case 5:return v;case 6:return w;case 2:x.push(v)}else if(l)return!1;return f?-1:c||l?l:x}}},function(t,e,n){"use strict";var r=n(1),o=n(55)(0),i=n(27)([].forEach,!0);r(r.P+r.F*!i,"Array",{forEach:function(t){return o(this,t,arguments[1])}})},function(t,e,n){var r=n(28),o=n(7),i=o["__core-js_shared__"]||(o["__core-js_shared__"]={});(t.exports=function(t,e){return i[t]||(i[t]=void 0!==e?e:{})})("versions",[]).push({version:r.version,mode:n(94)?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(t,e,n){var r=n(42);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==r(t)?t.split(""):Object(t)}},function(t,e,n){"use strict";var r=n(94),o=n(1),i=n(21),a=n(17),s=n(31),u=n(147),c=n(65),l=n(151),f=n(2)("iterator"),p=!([].keys&&"next"in[].keys()),h=function(){return this};t.exports=function(t,e,n,d,v,m,y){u(n,e,d);var g,b,_,w=function(t){if(!p&&t in S)return S[t];switch(t){case"keys":case"values":return function(){return new n(this,t)}}return function(){return new n(this,t)}},x=e+" Iterator",k="values"==v,O=!1,S=t.prototype,C=S[f]||S["@@iterator"]||v&&S[v],A=C||w(v),E=v?k?w("entries"):A:void 0,$="Array"==e&&S.entries||C;if($&&(_=l($.call(new t)))!==Object.prototype&&_.next&&(c(_,x,!0),r||"function"==typeof _[f]||a(_,f,h)),k&&C&&"values"!==C.name&&(O=!0,A=function(){return C.call(this)}),r&&!y||!p&&!O&&S[f]||a(S,f,A),s[e]=A,s[x]=h,v)if(g={values:k?A:w("values"),keys:m?A:w("keys"),entries:E},y)for(b in g)b in S||i(S,b,g[b]);else o(o.P+o.F*(p||O),e,g);return g}},function(t,e,n){var r=n(8),o=n(148),i=n(64),a=n(63)("IE_PROTO"),s=function(){},u=function(){var t,e=n(92)("iframe"),r=i.length;for(e.style.display="none",n(150).appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write(" + diff --git a/dev/index.html b/dev/index.html index 9d10de91..eac5d6b3 100644 --- a/dev/index.html +++ b/dev/index.html @@ -13,7 +13,7 @@ - + @@ -30,6 +30,6 @@ GitHub
- + diff --git a/dev/release-guide.html b/dev/release-guide.html index 408200d8..c06fe2dc 100644 --- a/dev/release-guide.html +++ b/dev/release-guide.html @@ -13,7 +13,7 @@ - + @@ -38,6 +38,6 @@ →

- + diff --git a/dev/upgrade-guide.html b/dev/upgrade-guide.html index a6178d36..bd521b55 100644 --- a/dev/upgrade-guide.html +++ b/dev/upgrade-guide.html @@ -13,7 +13,7 @@ - + @@ -45,6 +45,6 @@ do the upgrade, wait for Flagger to finish the no-op promotions and finally set

- + diff --git a/index.html b/index.html index aafa1d4a..d9c398a3 100644 --- a/index.html +++ b/index.html @@ -13,7 +13,7 @@ - + @@ -33,14 +33,15 @@ Progressive Delivery Operator for Kubernetes

Get Started → -

Safer Releases

Reduce the risk of introducing a new software version in production by gradually shifting traffic to the new version while measuring metrics like HTTP/gRPC request success rate and latency.

Flexible Traffic Routing

Shift and route traffic between app versions using a service mesh like Istio, Linkerd or AWS App Mesh. Or if a service mesh does not meet your needs, use an Ingress controller like Contour, Gloo or NGINX.

Extensible Validation

Besides the builtin metrics checks, you can extend your application analysis with custom Prometheus, Datadog, CloudWatch metrics and webooks for running acceptance tests, load tests, or any other custom validation.

Progressive Delivery

Flagger was designed to give developers confidence in automating production releases with progressive delivery techniques.

Canary release

A benefit of using canary releases is the ability to do capacity testing of the new version in a production environment +

Safer Releases

Reduce the risk of introducing a new software version in production by gradually shifting traffic to the new version while measuring metrics like HTTP/gRPC request success rate and latency.

Flexible Traffic Routing

Shift and route traffic between app versions using a service mesh like Istio, Linkerd or AWS App Mesh. Or if a service mesh does not meet your needs, use an Ingress controller like Contour, Gloo, NGINX or Skipper.

Extensible Validation

Besides the builtin metrics checks, you can extend your application analysis with custom Prometheus, Datadog, CloudWatch metrics and webooks for running acceptance tests, load tests, or any other custom validation.

Progressive Delivery

Flagger was designed to give developers confidence in automating production releases with progressive delivery techniques.

Canary release

A benefit of using canary releases is the ability to do capacity testing of the new version in a production environment with a safe rollback strategy if issues are found. By slowly ramping up the load, you can monitor and capture metrics about how the new version impacts the production environment.

Martin Fowler

Flagger can run automated application analysis, testing, promotion and rollback for the following deployment strategies:

- + diff --git a/install/flagger-install-on-eks-appmesh.html b/install/flagger-install-on-eks-appmesh.html index 6ae0a932..a1b7ce00 100644 --- a/install/flagger-install-on-eks-appmesh.html +++ b/install/flagger-install-on-eks-appmesh.html @@ -13,7 +13,7 @@ - + @@ -92,6 +92,6 @@ Status: →

- + diff --git a/install/flagger-install-on-google-cloud.html b/install/flagger-install-on-google-cloud.html index 86013398..f02edc6f 100644 --- a/install/flagger-install-on-google-cloud.html +++ b/install/flagger-install-on-google-cloud.html @@ -13,7 +13,7 @@ - + @@ -203,6 +203,6 @@ https://storage.googleapis.com/gke-release/istio/release/1.0.6-gke.3/patches/ins →

- + diff --git a/install/flagger-install-on-kubernetes.html b/install/flagger-install-on-kubernetes.html index 07e01a6d..b399d9e0 100644 --- a/install/flagger-install-on-kubernetes.html +++ b/install/flagger-install-on-kubernetes.html @@ -13,7 +13,7 @@ - + @@ -146,6 +146,6 @@ to https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK.

- + diff --git a/install/index.html b/install/index.html index a3f89ab3..80145c31 100644 --- a/install/index.html +++ b/install/index.html @@ -13,7 +13,7 @@ - + @@ -30,6 +30,6 @@ GitHub
- + diff --git a/intro/faq.html b/intro/faq.html index a270c1c6..a77ed3ae 100644 --- a/intro/faq.html +++ b/intro/faq.html @@ -13,7 +13,7 @@ - + @@ -478,6 +478,6 @@ the two services and the website rule will be moved to the end of the list in th →

- + diff --git a/intro/index.html b/intro/index.html index af551889..ad6d29f4 100644 --- a/intro/index.html +++ b/intro/index.html @@ -13,7 +13,7 @@ - + @@ -46,6 +46,6 @@ and install Flagger with →

- + diff --git a/tutorials/appmesh-progressive-delivery.html b/tutorials/appmesh-progressive-delivery.html index c109a4ac..6510f9b3 100644 --- a/tutorials/appmesh-progressive-delivery.html +++ b/tutorials/appmesh-progressive-delivery.html @@ -13,7 +13,7 @@ - + @@ -263,6 +263,6 @@ Promotion completed! Scaling down podinfo.test →

- + diff --git a/tutorials/canary-helm-gitops.html b/tutorials/canary-helm-gitops.html index 1ed6c278..bea67e63 100644 --- a/tutorials/canary-helm-gitops.html +++ b/tutorials/canary-helm-gitops.html @@ -13,7 +13,7 @@ - + @@ -216,6 +216,6 @@ and - + diff --git a/tutorials/contour-progressive-delivery.html b/tutorials/contour-progressive-delivery.html index cc82a3b0..e11f4767 100644 --- a/tutorials/contour-progressive-delivery.html +++ b/tutorials/contour-progressive-delivery.html @@ -13,7 +13,7 @@ - + @@ -268,6 +268,6 @@ Promotion completed! Scaling down podinfo.test

- + diff --git a/tutorials/crossover-progressive-delivery.html b/tutorials/crossover-progressive-delivery.html index 159ef2ce..bb3cec91 100644 --- a/tutorials/crossover-progressive-delivery.html +++ b/tutorials/crossover-progressive-delivery.html @@ -13,7 +13,7 @@ - + @@ -210,6 +210,6 @@ Rolling back podinfo.test failed checks threshold reached 5 Canary failed! Scaling down podinfo.test

If you’ve enabled the Slack notifications, you’ll receive a message if the progress deadline is exceeded, or if the analysis reached the maximum number of failed checks:

Flagger Slack Notifications

- + diff --git a/tutorials/flagger-smi-istio.html b/tutorials/flagger-smi-istio.html index a8f0eb98..29d89811 100644 --- a/tutorials/flagger-smi-istio.html +++ b/tutorials/flagger-smi-istio.html @@ -13,7 +13,7 @@ - + @@ -187,6 +187,6 @@ Events: Warning Synced 1m flagger Rolling back podinfo.test failed checks threshold reached 10 Warning Synced 1m flagger Canary failed! Scaling down podinfo.test
- + diff --git a/tutorials/gloo-progressive-delivery.html b/tutorials/gloo-progressive-delivery.html index 226df730..4f74d908 100644 --- a/tutorials/gloo-progressive-delivery.html +++ b/tutorials/gloo-progressive-delivery.html @@ -13,7 +13,7 @@ - + @@ -266,6 +266,6 @@ Flagger will send a notification with the reason why the canary failed.

F →

- + diff --git a/tutorials/index.html b/tutorials/index.html index 832d8f65..374ee97d 100644 --- a/tutorials/index.html +++ b/tutorials/index.html @@ -13,7 +13,7 @@ - + @@ -30,6 +30,6 @@ GitHub
- + diff --git a/tutorials/istio-ab-testing.html b/tutorials/istio-ab-testing.html index ce55eacb..cd37a191 100644 --- a/tutorials/istio-ab-testing.html +++ b/tutorials/istio-ab-testing.html @@ -13,7 +13,7 @@ - + @@ -198,6 +198,6 @@ Events: →

- + diff --git a/tutorials/istio-progressive-delivery.html b/tutorials/istio-progressive-delivery.html index ada8d314..44599900 100644 --- a/tutorials/istio-progressive-delivery.html +++ b/tutorials/istio-progressive-delivery.html @@ -13,7 +13,7 @@ - + @@ -258,6 +258,6 @@ Metrics are collected on both requests so that the deployment will only proceed →

- + diff --git a/tutorials/kubernetes-blue-green.html b/tutorials/kubernetes-blue-green.html index 74d333c2..fe9d211c 100644 --- a/tutorials/kubernetes-blue-green.html +++ b/tutorials/kubernetes-blue-green.html @@ -13,7 +13,7 @@ - + @@ -248,6 +248,6 @@ If the helm test fails, Flagger will retry until the analysis threshold is reach →

- + diff --git a/tutorials/linkerd-progressive-delivery.html b/tutorials/linkerd-progressive-delivery.html index 220e7e2a..8df9e8d9 100644 --- a/tutorials/linkerd-progressive-delivery.html +++ b/tutorials/linkerd-progressive-delivery.html @@ -13,7 +13,7 @@ - + @@ -340,6 +340,6 @@ Events: →

- + diff --git a/tutorials/nginx-progressive-delivery.html b/tutorials/nginx-progressive-delivery.html index 5d589d8a..7bfdba2f 100644 --- a/tutorials/nginx-progressive-delivery.html +++ b/tutorials/nginx-progressive-delivery.html @@ -13,7 +13,7 @@ - + @@ -319,6 +319,6 @@ Events: →

- + diff --git a/tutorials/zero-downtime-deployments.html b/tutorials/zero-downtime-deployments.html index d6c94444..19c81913 100644 --- a/tutorials/zero-downtime-deployments.html +++ b/tutorials/zero-downtime-deployments.html @@ -13,7 +13,7 @@ - + @@ -135,6 +135,6 @@ perTryTimeout: 5s retryOn: "gateway-error,connect-failure,refused-stream"

When the HPA scales down your app, your users could run into 503 errors. The above configuration will make Envoy retry the HTTP requests that failed due to gateway errors.

- + diff --git a/usage/alerting.html b/usage/alerting.html index 877a0e12..318436a2 100644 --- a/usage/alerting.html +++ b/usage/alerting.html @@ -13,7 +13,7 @@ - + @@ -101,6 +101,6 @@ When the severity is set to error, Flagger will alert only if the c →

- + diff --git a/usage/deployment-strategies.html b/usage/deployment-strategies.html index b4330a9a..05863e4e 100644 --- a/usage/deployment-strategies.html +++ b/usage/deployment-strategies.html @@ -13,7 +13,7 @@ - + @@ -155,6 +155,6 @@ the Kubernetes deployment rollout.