Files
flagger/usage/webhooks.html
T
2020-03-05 15:17:54 +00:00

255 lines
50 KiB
HTML

<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Webhooks | Flagger</title>
<meta name="description" content="Progressive Delivery operator for Kubernetes (Canary, A/B Testing and Blue/Green deployments)">
<link rel="icon" href="/favicon.png">
<link rel="stylesheet" href="/website.css">
<meta name="keywords" content="gitops kubernetes flagger istio linkerd appmesh contour gloo nginx">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Flagger">
<meta name="twitter:description" content="Progressive delivery Kubernetes operator (Canary, A/B Testing and Blue/Green deployments)">
<meta name="twitter:image:src" content="https://flagger.app/flagger-overview.png">
<link rel="preload" href="/assets/css/0.styles.a0ada997.css" as="style"><link rel="preload" href="/assets/js/app.b4b27991.js" as="script"><link rel="preload" href="/assets/js/2.ba5bf77c.js" as="script"><link rel="preload" href="/assets/js/35.fc27c09e.js" as="script"><link rel="prefetch" href="/assets/js/10.bf6f38d4.js"><link rel="prefetch" href="/assets/js/11.3af38cfe.js"><link rel="prefetch" href="/assets/js/12.eca4b89c.js"><link rel="prefetch" href="/assets/js/13.9104349a.js"><link rel="prefetch" href="/assets/js/14.a4f3d810.js"><link rel="prefetch" href="/assets/js/15.aada2caa.js"><link rel="prefetch" href="/assets/js/16.3012a10b.js"><link rel="prefetch" href="/assets/js/17.a98b6aa9.js"><link rel="prefetch" href="/assets/js/18.e5188926.js"><link rel="prefetch" href="/assets/js/19.bb9498f7.js"><link rel="prefetch" href="/assets/js/20.dce5a04e.js"><link rel="prefetch" href="/assets/js/21.df66561d.js"><link rel="prefetch" href="/assets/js/22.1c5d14b9.js"><link rel="prefetch" href="/assets/js/23.b3dcc355.js"><link rel="prefetch" href="/assets/js/24.4f54d289.js"><link rel="prefetch" href="/assets/js/25.914acd1d.js"><link rel="prefetch" href="/assets/js/26.b2d4f402.js"><link rel="prefetch" href="/assets/js/27.ea9f1f9c.js"><link rel="prefetch" href="/assets/js/28.deae273d.js"><link rel="prefetch" href="/assets/js/29.17c547e6.js"><link rel="prefetch" href="/assets/js/3.8b254d5d.js"><link rel="prefetch" href="/assets/js/30.38bd809e.js"><link rel="prefetch" href="/assets/js/31.fbfb336c.js"><link rel="prefetch" href="/assets/js/32.591c3f2b.js"><link rel="prefetch" href="/assets/js/33.c456709f.js"><link rel="prefetch" href="/assets/js/34.5a071e36.js"><link rel="prefetch" href="/assets/js/36.144098aa.js"><link rel="prefetch" href="/assets/js/4.26a3069c.js"><link rel="prefetch" href="/assets/js/5.f92a6aca.js"><link rel="prefetch" href="/assets/js/6.ee5ffca3.js"><link rel="prefetch" href="/assets/js/7.6bf27a87.js"><link rel="prefetch" href="/assets/js/8.8b72a8d3.js"><link rel="prefetch" href="/assets/js/9.7919fc1d.js">
<link rel="stylesheet" href="/assets/css/0.styles.a0ada997.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">Flagger</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="https://docs.flagger.app" target="_blank" rel="noopener noreferrer" class="nav-link external">
Docs
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><a href="https://github.com/weaveworks/flagger/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="nav-link external">
Changelog
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <a href="https://github.com/weaveworks/flagger" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="https://docs.flagger.app" target="_blank" rel="noopener noreferrer" class="nav-link external">
Docs
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><a href="https://github.com/weaveworks/flagger/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="nav-link external">
Changelog
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <a href="https://github.com/weaveworks/flagger" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav> <ul class="sidebar-links"><li><a href="/" class="sidebar-link">Home</a></li><li><section class="sidebar-group depth-0"><a href="/intro/" class="sidebar-heading clickable"><span>Introduction</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/intro/" class="sidebar-link">Get Started</a></li><li><a href="/intro/faq.html" class="sidebar-link">FAQ</a></li></ul></section></li><li><section class="sidebar-group depth-0"><a href="/install/flagger-install-on-kubernetes" class="sidebar-heading clickable"><span>Install</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/install/flagger-install-on-kubernetes.html" class="sidebar-link">On Kubernetes</a></li><li><a href="/install/flagger-install-on-google-cloud.html" class="sidebar-link">On GKE Istio</a></li><li><a href="/install/flagger-install-on-eks-appmesh.html" class="sidebar-link">On EKS App Mesh</a></li></ul></section></li><li><section class="sidebar-group depth-0"><a href="/usage/how-it-works" class="sidebar-heading clickable open"><span>Usage</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/usage/how-it-works.html" class="sidebar-link">How it works</a></li><li><a href="/usage/deployment-strategies.html" class="sidebar-link">Deployment Strategies</a></li><li><a href="/usage/metrics.html" class="sidebar-link">Metrics Analysis</a></li><li><a href="/usage/webhooks.html" class="active sidebar-link">Webhooks</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/usage/webhooks.html#load-testing" class="sidebar-link">Load Testing</a></li><li class="sidebar-sub-header"><a href="/usage/webhooks.html#load-testing-delegation" class="sidebar-link">Load Testing Delegation</a></li><li class="sidebar-sub-header"><a href="/usage/webhooks.html#integration-testing" class="sidebar-link">Integration Testing</a></li><li class="sidebar-sub-header"><a href="/usage/webhooks.html#manual-gating" class="sidebar-link">Manual Gating</a></li></ul></li><li><a href="/usage/alerting.html" class="sidebar-link">Alerting</a></li><li><a href="/usage/monitoring.html" class="sidebar-link">Monitoring</a></li></ul></section></li><li><section class="sidebar-group depth-0"><a href="/tutorials/istio-progressive-delivery" class="sidebar-heading clickable"><span>Tutorials</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/tutorials/istio-progressive-delivery.html" class="sidebar-link">Istio Canaries</a></li><li><a href="/tutorials/istio-ab-testing.html" class="sidebar-link">Istio A/B Testing</a></li><li><a href="/tutorials/linkerd-progressive-delivery.html" class="sidebar-link">Linkerd Canaries</a></li><li><a href="/tutorials/appmesh-progressive-delivery.html" class="sidebar-link">App Mesh Canaries</a></li><li><a href="/tutorials/nginx-progressive-delivery.html" class="sidebar-link">NGINX Ingress Canaries</a></li><li><a href="/tutorials/gloo-progressive-delivery.html" class="sidebar-link">Gloo Canaries</a></li><li><a href="/tutorials/contour-progressive-delivery.html" class="sidebar-link">Contour Canaries</a></li><li><a href="/tutorials/kubernetes-blue-green.html" class="sidebar-link">Kubernetes Blue/Green</a></li><li><a href="/tutorials/canary-helm-gitops.html" class="sidebar-link">Canaries with Helm charts and GitOps</a></li></ul></section></li><li><section class="sidebar-group depth-0"><a href="/dev/dev-guide" class="sidebar-heading clickable"><span>Dev</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/dev/dev-guide.html" class="sidebar-link">Development Guide</a></li><li><a href="/dev/release-guide.html" class="sidebar-link">Release Guide</a></li><li><a href="/dev/upgrade-guide.html" class="sidebar-link">Upgrade Guide</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="webhooks"><a href="#webhooks" aria-hidden="true" class="header-anchor">#</a> Webhooks</h1> <p>The canary analysis can be extended with webhooks. Flagger will call each webhook URL and
determine from the response status code (HTTP 2xx) if the canary is failing or not.</p> <p>There are several types of hooks:</p> <ul><li><strong>confirm-rollout</strong> hooks are executed before scaling up the canary deployment and can be used for manual approval.
The rollout is paused until the hook returns a successful HTTP status code.</li> <li><strong>pre-rollout</strong> hooks are executed before routing traffic to canary.
The canary advancement is paused if a pre-rollout hook fails and if the number of failures reach the
threshold the canary will be rollback.</li> <li><strong>rollout</strong> hooks are executed during the analysis on each iteration before the metric checks.
If a rollout hook call fails the canary advancement is paused and eventfully rolled back.</li> <li><strong>confirm-promotion</strong> hooks are executed before the promotion step.
The canary promotion is paused until the hooks return HTTP 200.
While the promotion is paused, Flagger will continue to run the metrics checks and rollout hooks.</li> <li><strong>post-rollout</strong> hooks are executed after the canary has been promoted or rolled back.
If a post rollout hook fails the error is logged.</li> <li><strong>rollback</strong> hooks are executed while a canary deployment is in either Progressing or Waiting status.
This provides the ability to rollback during analysis or while waiting for a confirmation. If a rollback hook
returns a successful HTTP status code, Flagger will stop the analysis and mark the canary release as failed.</li> <li><strong>event</strong> hooks are executed every time Flagger emits a Kubernetes event. When configured,
every action that Flagger takes during a canary deployment will be sent as JSON via an HTTP POST request.</li></ul> <p>Spec:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;start gate&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> confirm<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/gate/approve
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;helm test&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> pre<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>helmtester.flagger/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 3m
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> <span class="token string">&quot;helmv3&quot;</span>
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;test podinfo -n test&quot;</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;load test&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 15s
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;hey -z 1m -q 5 -c 2 http://podinfo-canary.test:9898/&quot;</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;promotion gate&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> confirm<span class="token punctuation">-</span>promotion
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/gate/approve
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;notify&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> post<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//telegram.bot<span class="token punctuation">:</span>8080/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">some</span><span class="token punctuation">:</span> <span class="token string">&quot;message&quot;</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;rollback gate&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> rollback
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/rollback/check
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;send to Slack&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> event
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//event<span class="token punctuation">-</span>recevier.notifications/slack
</code></pre></div><blockquote><p><strong>Note</strong> that the sum of all rollout webhooks timeouts should be lower than the analysis interval.</p></blockquote> <p>Webhook payload (HTTP POST):</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">&quot;name&quot;</span><span class="token operator">:</span> <span class="token string">&quot;podinfo&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;namespace&quot;</span><span class="token operator">:</span> <span class="token string">&quot;test&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;phase&quot;</span><span class="token operator">:</span> <span class="token string">&quot;Progressing&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;metadata&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">&quot;test&quot;</span><span class="token operator">:</span> <span class="token string">&quot;all&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;token&quot;</span><span class="token operator">:</span> <span class="token string">&quot;16688eb5e9f289f1991c&quot;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>Response status codes:</p> <ul><li>200-202 - advance canary by increasing the traffic weight</li> <li>timeout or non-2xx - halt advancement and increment failed checks</li></ul> <p>On a non-2xx response Flagger will include the response body (if any) in the failed checks log and Kubernetes events.</p> <p>Event payload (HTTP POST):</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">&quot;name&quot;</span><span class="token operator">:</span> <span class="token string">&quot;string (canary name)&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;namespace&quot;</span><span class="token operator">:</span> <span class="token string">&quot;string (canary namespace)&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;phase&quot;</span><span class="token operator">:</span> <span class="token string">&quot;string (canary phase)&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;metadata&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">&quot;eventMessage&quot;</span><span class="token operator">:</span> <span class="token string">&quot;string (canary event message)&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;eventType&quot;</span><span class="token operator">:</span> <span class="token string">&quot;string (canary event type)&quot;</span><span class="token punctuation">,</span>
<span class="token property">&quot;timestamp&quot;</span><span class="token operator">:</span> <span class="token string">&quot;string (unix timestamp ms)&quot;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>The event receiver can create alerts based on the received phase
(possible values: <code>Initialized</code>, <code>Waiting</code>, <code>Progressing</code>, <code>Promoting</code>, <code>Finalising</code>, <code>Succeeded</code> or <code>Failed</code>).</p> <h2 id="load-testing"><a href="#load-testing" aria-hidden="true" class="header-anchor">#</a> Load Testing</h2> <p>For workloads that are not receiving constant traffic Flagger can be configured with a webhook,
that when called, will start a load test for the target workload.
If the target workload doesn't receive any traffic during the canary analysis,
Flagger metric checks will fail with &quot;no values found for metric request-success-rate&quot;.</p> <p>Flagger comes with a load testing service based on <a href="https://github.com/rakyll/hey" target="_blank" rel="noopener noreferrer">rakyll/hey<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>
that generates traffic during analysis when configured as a webhook.</p> <p><img src="https://raw.githubusercontent.com/weaveworks/flagger/master/docs/diagrams/flagger-load-testing.png" alt="Flagger Load Testing Webhook"></p> <p>First you need to deploy the load test runner in a namespace with sidecar injection enabled:</p> <div class="language-bash extra-class"><pre class="language-bash"><code>kubectl apply -k github.com/weaveworks/flagger//kustomize/tester
</code></pre></div><p>Or by using Helm:</p> <div class="language-bash extra-class"><pre class="language-bash"><code>helm repo <span class="token function">add</span> flagger https://flagger.app
helm upgrade -i flagger-loadtester flagger/loadtester <span class="token punctuation">\</span>
--namespace<span class="token operator">=</span>test <span class="token punctuation">\</span>
--set cmd.timeout<span class="token operator">=</span>1h
</code></pre></div><p>When deployed the load tester API will be available at <code>http://flagger-loadtester.test/</code>.</p> <p>Now you can add webhooks to the canary analysis spec:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code><span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> load<span class="token punctuation">-</span>test<span class="token punctuation">-</span>get
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> cmd
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/&quot;</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> load<span class="token punctuation">-</span>test<span class="token punctuation">-</span>post
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> cmd
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;hey -z 1m -q 10 -c 2 -m POST -d '{test: 2}' http://podinfo-canary.test:9898/echo&quot;</span>
</code></pre></div><p>When the canary analysis starts, Flagger will call the webhooks and the load tester will run the <code>hey</code> commands
in the background, if they are not already running. This will ensure that during the
analysis, the <code>podinfo-canary.test</code> service will receive a steady stream of GET and POST requests.</p> <p>If your workload is exposed outside the mesh you can point <code>hey</code> to the
public URL and use HTTP2.</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code><span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> load<span class="token punctuation">-</span>test<span class="token punctuation">-</span>get
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> cmd
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;hey -z 1m -q 10 -c 2 -h2 https://podinfo.example.com/&quot;</span>
</code></pre></div><p>For gRPC services you can use <a href="https://github.com/bojand/ghz" target="_blank" rel="noopener noreferrer">bojand/ghz<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> which is a similar tool to Hey but for gPRC:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code><span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> grpc<span class="token punctuation">-</span>load<span class="token punctuation">-</span>test
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> cmd
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;ghz -z 1m -q 10 -c 2 --insecure podinfo.test:9898&quot;</span>
</code></pre></div><p><code>ghz</code> uses reflection to identify which gRPC method to call. If you do not wish to enable reflection for your gRPC service you can implement a standardized health check from the <a href="https://github.com/grpc/grpc-proto" target="_blank" rel="noopener noreferrer">grpc-proto<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> library. To use this <a href="https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto" target="_blank" rel="noopener noreferrer">health check schema<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> without reflection you can pass a parameter to <code>ghz</code> like this</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code><span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> grpc<span class="token punctuation">-</span>load<span class="token punctuation">-</span>test<span class="token punctuation">-</span>no<span class="token punctuation">-</span>reflection
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> cmd
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;ghz --insecure --proto=/tmp/ghz/health.proto --call=grpc.health.v1.Health/Check podinfo.test:9898&quot;</span>
</code></pre></div><p>The load tester can run arbitrary commands as long as the binary is present in the container image.
For example if you you want to replace <code>hey</code> with another CLI, you can create your own Docker image:</p> <div class="language-dockerfile extra-class"><pre class="language-text"><code>FROM weaveworks/flagger-loadtester:&lt;VER&gt;
RUN curl -Lo /usr/local/bin/my-cli https://github.com/user/repo/releases/download/ver/my-cli \
&amp;&amp; chmod +x /usr/local/bin/my-cli
</code></pre></div><h2 id="load-testing-delegation"><a href="#load-testing-delegation" aria-hidden="true" class="header-anchor">#</a> Load Testing Delegation</h2> <p>The load tester can also forward testing tasks to external tools, by now <a href="https://github.com/naver/ngrinder" target="_blank" rel="noopener noreferrer">nGrinder<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>
is supported.</p> <p>To use this feature, add a load test task of type 'ngrinder' to the canary analysis spec:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code><span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> load<span class="token punctuation">-</span>test<span class="token punctuation">-</span>post
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token comment"># type of this load test task, cmd or ngrinder</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> ngrinder
<span class="token comment"># base url of your nGrinder controller server</span>
<span class="token key atrule">server</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//ngrinder<span class="token punctuation">-</span>server<span class="token punctuation">:</span>port
<span class="token comment"># id of the test to clone from, the test must have been defined.</span>
<span class="token key atrule">clone</span><span class="token punctuation">:</span> <span class="token number">100</span>
<span class="token comment"># user name and base64 encoded password to authenticate against the nGrinder server</span>
<span class="token key atrule">username</span><span class="token punctuation">:</span> admin
<span class="token key atrule">passwd</span><span class="token punctuation">:</span> YWRtaW4=
<span class="token comment"># the interval between between nGrinder test status polling, default to 1s</span>
<span class="token key atrule">pollInterval</span><span class="token punctuation">:</span> 5s
</code></pre></div><p>When the canary analysis starts, the load tester will initiate a <a href="https://github.com/naver/ngrinder/wiki/REST-API-PerfTest" target="_blank" rel="noopener noreferrer">clone_and_start request<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>
to the nGrinder server and start a new performance test. the load tester will periodically poll the nGrinder server
for the status of the test, and prevent duplicate requests from being sent in subsequent analysis loops.</p> <h2 id="integration-testing"><a href="#integration-testing" aria-hidden="true" class="header-anchor">#</a> Integration Testing</h2> <p>Flagger comes with a testing service that can run Helm tests or Bats tests when configured as a webhook.</p> <p>Deploy the Helm test runner in the <code>kube-system</code> namespace using the <code>tiller</code> service account:</p> <div class="language-bash extra-class"><pre class="language-bash"><code>helm repo <span class="token function">add</span> flagger https://flagger.app
helm upgrade -i flagger-helmtester flagger/loadtester <span class="token punctuation">\</span>
--namespace<span class="token operator">=</span>kube-system <span class="token punctuation">\</span>
--set <span class="token assign-left variable">serviceAccountName</span><span class="token operator">=</span>tiller
</code></pre></div><p>When deployed the Helm tester API will be available at <code>http://flagger-helmtester.kube-system/</code>.</p> <p>Now you can add pre-rollout webhooks to the canary analysis spec:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;smoke test&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> pre<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>helmtester.kube<span class="token punctuation">-</span>system/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 3m
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> <span class="token string">&quot;helm&quot;</span>
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;test {{ .Release.Name }} --cleanup&quot;</span>
</code></pre></div><p>When the canary analysis starts, Flagger will call the pre-rollout webhooks before routing traffic to the canary.
If the helm test fails, Flagger will retry until the analysis threshold is reached and the canary is rolled back.</p> <p>If you are using Helm v3, you'll have to create a dedicated service account and add the release namespace to the test command:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;smoke test&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> pre<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>helmtester.kube<span class="token punctuation">-</span>system/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 3m
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> <span class="token string">&quot;helmv3&quot;</span>
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;test {{ .Release.Name }} --timeout 3m -n {{ .Release.Namespace }}&quot;</span>
</code></pre></div><p>As an alternative to Helm you can use the <a href="https://github.com/bats-core/bats-core" target="_blank" rel="noopener noreferrer">Bash Automated Testing System<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> to run your tests.</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;acceptance tests&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> pre<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>batstester.default/
<span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5m
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> <span class="token string">&quot;bash&quot;</span>
<span class="token key atrule">cmd</span><span class="token punctuation">:</span> <span class="token string">&quot;bats /tests/acceptance.bats&quot;</span>
</code></pre></div><p>Note that you should create a ConfigMap with your Bats tests and mount it inside the tester container.</p> <h2 id="manual-gating"><a href="#manual-gating" aria-hidden="true" class="header-anchor">#</a> Manual Gating</h2> <p>For manual approval of a canary deployment you can use the <code>confirm-rollout</code> and <code>confirm-promotion</code> webhooks.
The confirmation rollout hooks are executed before the pre-rollout hooks.
Flagger will halt the canary traffic shifting and analysis until the confirm webhook returns HTTP status 200.</p> <p>For manual rollback of a canary deployment you can use the <code>rollback</code> webhook. The rollback hook will be called
during the analysis and confirmation states. If a rollback webhook returns a successful HTTP status code, Flagger
will shift all traffic back to the primary instance and fail the canary.</p> <p>Manual gating with Flagger's tester:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;gate&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> confirm<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/gate/halt
</code></pre></div><p>The <code>/gate/halt</code> returns HTTP 403 thus blocking the rollout.</p> <p>If you have notifications enabled, Flagger will post a message to Slack or MS Teams if a canary rollout is waiting for approval.</p> <p>Change the URL to <code>/gate/approve</code> to start the canary analysis:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;gate&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> confirm<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/gate/approve
</code></pre></div><p>Manual gating can be driven with Flagger's tester API. Set the confirmation URL to <code>/gate/check</code>:</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;ask for confirmation&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> confirm<span class="token punctuation">-</span>rollout
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/gate/check
</code></pre></div><p>By default the gate is closed, you can start or resume the canary rollout with:</p> <div class="language-bash extra-class"><pre class="language-bash"><code>kubectl -n <span class="token builtin class-name">test</span> <span class="token builtin class-name">exec</span> -it flagger-loadtester-xxxx-xxxx <span class="token function">sh</span>
<span class="token function">curl</span> -d <span class="token string">'{&quot;name&quot;: &quot;podinfo&quot;,&quot;namespace&quot;:&quot;test&quot;}'</span> http://localhost:8080/gate/open
</code></pre></div><p>You can pause the rollout at any time with:</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token function">curl</span> -d <span class="token string">'{&quot;name&quot;: &quot;podinfo&quot;,&quot;namespace&quot;:&quot;test&quot;}'</span> http://localhost:8080/gate/close
</code></pre></div><p>If a canary analysis is paused the status will change to waiting:</p> <div class="language-bash extra-class"><pre class="language-bash"><code>kubectl get canary/podinfo
NAME STATUS WEIGHT
podinfo Waiting <span class="token number">0</span>
</code></pre></div><p>The <code>confirm-promotion</code> hook type can be used to manually approve the canary promotion.
While the promotion is paused, Flagger will continue to run the metrics checks and load tests.</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;promotion gate&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> confirm<span class="token punctuation">-</span>promotion
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/gate/halt
</code></pre></div><p>The <code>rollback</code> hook type can be used to manually rollback the canary promotion. As with gating, rollbacks can be driven
with Flagger's tester API by setting the rollback URL to <code>/rollback/check</code></p> <div class="language-yaml extra-class"><pre class="language-yaml"><code> <span class="token key atrule">analysis</span><span class="token punctuation">:</span>
<span class="token key atrule">webhooks</span><span class="token punctuation">:</span>
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">&quot;rollback&quot;</span>
<span class="token key atrule">type</span><span class="token punctuation">:</span> rollback
<span class="token key atrule">url</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//flagger<span class="token punctuation">-</span>loadtester.test/rollback/check
</code></pre></div><p>By default rollback is closed, you can rollback a canary rollout with:</p> <div class="language-bash extra-class"><pre class="language-bash"><code>kubectl -n <span class="token builtin class-name">test</span> <span class="token builtin class-name">exec</span> -it flagger-loadtester-xxxx-xxxx <span class="token function">sh</span>
<span class="token function">curl</span> -d <span class="token string">'{&quot;name&quot;: &quot;podinfo&quot;,&quot;namespace&quot;:&quot;test&quot;}'</span> http://localhost:8080/rollback/open
</code></pre></div><p>You can close the rollback with:</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token function">curl</span> -d <span class="token string">'{&quot;name&quot;: &quot;podinfo&quot;,&quot;namespace&quot;:&quot;test&quot;}'</span> http://localhost:8080/rollback/close
</code></pre></div><p>If you have notifications enabled, Flagger will post a message to Slack or MS Teams if a canary has been rolled back.</p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/usage/metrics.html" class="prev">
Metrics Analysis
</a></span> <span class="next"><a href="/usage/alerting.html">
Alerting
</a>
</span></p></div> </main></div><div class="global-ui"></div></div>
<script src="/assets/js/app.b4b27991.js" defer></script><script src="/assets/js/2.ba5bf77c.js" defer></script><script src="/assets/js/35.fc27c09e.js" defer></script>
</body>
</html>