mirror of
https://github.com/fluxcd/flagger.git
synced 2026-02-16 02:49:51 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71137ba3bb | ||
|
|
6372c7dfcc | ||
|
|
4584733f6f | ||
|
|
03408683c0 | ||
|
|
29137ae75b | ||
|
|
6bf85526d0 | ||
|
|
9f6a30f43e |
@@ -3,6 +3,6 @@ coverage:
|
||||
project:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 0.50
|
||||
threshold: 50
|
||||
base: auto
|
||||
patch: off
|
||||
patch: off
|
||||
|
||||
3
Makefile
3
Makefile
@@ -13,7 +13,8 @@ build:
|
||||
docker build -t stefanprodan/flagger:$(TAG) . -f Dockerfile
|
||||
|
||||
push:
|
||||
docker push stefanprodan/flagger:$(TAG)
|
||||
docker tag stefanprodan/flagger:$(TAG) quay.io/stefanprodan/flagger:$(VERSION)
|
||||
docker push quay.io/stefanprodan/flagger:$(VERSION)
|
||||
|
||||
fmt:
|
||||
gofmt -l -s -w $(SOURCE_DIRS)
|
||||
|
||||
20
README.md
20
README.md
@@ -367,7 +367,25 @@ helm upgrade -i flagger flagger/flagger \
|
||||
Once configured with a Slack incoming webhook, Flagger will post messages when a canary deployment has been initialized,
|
||||
when a new revision has been detected and if the canary analysis failed or succeeded.
|
||||
|
||||

|
||||

|
||||
|
||||
A canary deployment will be rolled back if the progress deadline exceeded or if the analysis
|
||||
reached the maximum number of failed checks:
|
||||
|
||||

|
||||
|
||||
Besides Slack, you can use Alertmanager to trigger alerts when a canary deployment failed:
|
||||
|
||||
```yaml
|
||||
- alert: canary_rollback
|
||||
expr: flagger_canary_status > 1
|
||||
for: 1m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Canary failed"
|
||||
description: "Workload {{ $labels.name }} namespace {{ $labels.namespace }}"
|
||||
```
|
||||
|
||||
### Roadmap
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ spec:
|
||||
serviceAccountName: flagger
|
||||
containers:
|
||||
- name: flagger
|
||||
image: quay.io/stefanprodan/flagger:0.1.1
|
||||
image: quay.io/stefanprodan/flagger:0.1.2
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v1
|
||||
name: flagger
|
||||
version: 0.1.1
|
||||
appVersion: 0.1.1
|
||||
version: 0.1.2
|
||||
appVersion: 0.1.2
|
||||
description: Flagger is a Kubernetes operator that automates the promotion of canary deployments using Istio routing for traffic shifting and Prometheus metrics for canary analysis.
|
||||
home: https://github.com/stefanprodan/flagger
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
image:
|
||||
repository: quay.io/stefanprodan/flagger
|
||||
tag: 0.1.1
|
||||
tag: 0.1.2
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
controlLoopInterval: "10s"
|
||||
|
||||
@@ -367,7 +367,25 @@ helm upgrade -i flagger flagger/flagger \
|
||||
Once configured with a Slack incoming webhook, Flagger will post messages when a canary deployment has been initialized,
|
||||
when a new revision has been detected and if the canary analysis failed or succeeded.
|
||||
|
||||

|
||||

|
||||
|
||||
A canary deployment will be rolled back if the progress deadline exceeded or if the analysis
|
||||
reached the maximum number of failed checks:
|
||||
|
||||

|
||||
|
||||
Besides Slack, you can use Alertmanager to trigger alerts when a canary deployment failed:
|
||||
|
||||
```yaml
|
||||
- alert: canary_rollback
|
||||
expr: flagger_canary_status > 1
|
||||
for: 1m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Canary failed"
|
||||
description: "Workload {{ $labels.name }} namespace {{ $labels.namespace }}"
|
||||
```
|
||||
|
||||
### Roadmap
|
||||
|
||||
|
||||
BIN
docs/flagger-0.1.2.tgz
Normal file
BIN
docs/flagger-0.1.2.tgz
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,9 +1,21 @@
|
||||
apiVersion: v1
|
||||
entries:
|
||||
flagger:
|
||||
- apiVersion: v1
|
||||
appVersion: 0.1.2
|
||||
created: 2018-12-06T13:57:50.322474+07:00
|
||||
description: Flagger is a Kubernetes operator that automates the promotion of
|
||||
canary deployments using Istio routing for traffic shifting and Prometheus metrics
|
||||
for canary analysis.
|
||||
digest: a52bf1bf797d60d3d92f46f84805edbd1ffb7d87504727266f08543532ff5e08
|
||||
home: https://github.com/stefanprodan/flagger
|
||||
name: flagger
|
||||
urls:
|
||||
- https://stefanprodan.github.io/flagger/flagger-0.1.2.tgz
|
||||
version: 0.1.2
|
||||
- apiVersion: v1
|
||||
appVersion: 0.1.1
|
||||
created: 2018-11-28T14:53:55.671596+02:00
|
||||
created: 2018-12-06T13:57:50.322115+07:00
|
||||
description: Flagger is a Kubernetes operator that automates the promotion of
|
||||
canary deployments using Istio routing for traffic shifting and Prometheus metrics
|
||||
for canary analysis.
|
||||
@@ -15,7 +27,7 @@ entries:
|
||||
version: 0.1.1
|
||||
- apiVersion: v1
|
||||
appVersion: 0.1.0
|
||||
created: 2018-11-28T14:53:55.670949+02:00
|
||||
created: 2018-12-06T13:57:50.321509+07:00
|
||||
description: Flagger is a Kubernetes operator that automates the promotion of
|
||||
canary deployments using Istio routing for traffic shifting and Prometheus metrics
|
||||
for canary analysis.
|
||||
@@ -28,13 +40,13 @@ entries:
|
||||
grafana:
|
||||
- apiVersion: v1
|
||||
appVersion: 5.3.1
|
||||
created: 2018-11-28T14:53:55.67202+02:00
|
||||
created: 2018-12-06T13:57:50.323051+07:00
|
||||
description: A Grafana Helm chart for monitoring progressive deployments powered
|
||||
by Istio and Flagger
|
||||
digest: 1ab2d0297f11def3787294d277180742f8a62dabfe577795d1867d5b001cbcd1
|
||||
digest: 692b7c545214b652374249cc814d37decd8df4f915530e82dff4d9dfa25e8762
|
||||
home: https://github.com/stefanprodan/flagger
|
||||
name: grafana
|
||||
urls:
|
||||
- https://stefanprodan.github.io/flagger/grafana-0.1.0.tgz
|
||||
version: 0.1.0
|
||||
generated: 2018-11-28T14:53:55.670112+02:00
|
||||
generated: 2018-12-06T13:57:50.320726+07:00
|
||||
|
||||
BIN
docs/screens/slack-canary-failed.png
Normal file
BIN
docs/screens/slack-canary-failed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/screens/slack-canary-success.png
Normal file
BIN
docs/screens/slack-canary-success.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 114 KiB |
@@ -260,12 +260,36 @@ func (c *Controller) recordEventWarningf(r *flaggerv1.Canary, template string, a
|
||||
c.eventRecorder.Event(r, corev1.EventTypeWarning, "Synced", fmt.Sprintf(template, args...))
|
||||
}
|
||||
|
||||
func (c *Controller) sendNotification(workload string, namespace string, message string, warn bool) {
|
||||
func (c *Controller) sendNotification(cd *flaggerv1.Canary, message string, metadata bool, warn bool) {
|
||||
if c.notifier == nil {
|
||||
return
|
||||
}
|
||||
|
||||
err := c.notifier.Post(workload, namespace, message, warn)
|
||||
var fields []notifier.SlackField
|
||||
|
||||
if metadata {
|
||||
fields = append(fields,
|
||||
notifier.SlackField{
|
||||
Title: "Target",
|
||||
Value: fmt.Sprintf("%s/%s.%s", cd.Spec.TargetRef.Kind, cd.Spec.TargetRef.Name, cd.Namespace),
|
||||
},
|
||||
notifier.SlackField{
|
||||
Title: "Traffic routing",
|
||||
Value: fmt.Sprintf("Weight step: %v max: %v",
|
||||
cd.Spec.CanaryAnalysis.StepWeight,
|
||||
cd.Spec.CanaryAnalysis.MaxWeight),
|
||||
},
|
||||
notifier.SlackField{
|
||||
Title: "Failed checks threshold",
|
||||
Value: fmt.Sprintf("%v", cd.Spec.CanaryAnalysis.Threshold),
|
||||
},
|
||||
notifier.SlackField{
|
||||
Title: "Progress deadline",
|
||||
Value: fmt.Sprintf("%vs", cd.GetProgressDeadlineSeconds()),
|
||||
},
|
||||
)
|
||||
}
|
||||
err := c.notifier.Post(cd.Name, cd.Namespace, message, fields, warn)
|
||||
if err != nil {
|
||||
c.logger.Error(err)
|
||||
}
|
||||
|
||||
@@ -95,11 +95,15 @@ func (c *Controller) advanceCanary(name string, namespace string) {
|
||||
if cd.Status.FailedChecks >= cd.Spec.CanaryAnalysis.Threshold {
|
||||
c.recordEventWarningf(cd, "Rolling back %s.%s failed checks threshold reached %v",
|
||||
cd.Name, cd.Namespace, cd.Status.FailedChecks)
|
||||
c.sendNotification(cd, fmt.Sprintf("Failed checks threshold reached %v", cd.Status.FailedChecks),
|
||||
false, true)
|
||||
}
|
||||
|
||||
if !retriable {
|
||||
c.recordEventWarningf(cd, "Rolling back %s.%s progress deadline exceeded %v",
|
||||
cd.Name, cd.Namespace, err)
|
||||
c.sendNotification(cd, fmt.Sprintf("Progress deadline exceeded %v", err),
|
||||
false, true)
|
||||
}
|
||||
|
||||
// route all traffic back to primary
|
||||
@@ -112,7 +116,7 @@ func (c *Controller) advanceCanary(name string, namespace string) {
|
||||
|
||||
c.recorder.SetWeight(cd, primaryRoute.Weight, canaryRoute.Weight)
|
||||
c.recordEventWarningf(cd, "Canary failed! Scaling down %s.%s",
|
||||
cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
cd.Name, cd.Namespace)
|
||||
|
||||
// shutdown canary
|
||||
if err := c.deployer.Scale(cd, 0); err != nil {
|
||||
@@ -127,8 +131,6 @@ func (c *Controller) advanceCanary(name string, namespace string) {
|
||||
}
|
||||
|
||||
c.recorder.SetStatus(cd)
|
||||
c.sendNotification(cd.Spec.TargetRef.Name, cd.Namespace,
|
||||
"Canary analysis failed, rollback finished.", true)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -199,8 +201,8 @@ func (c *Controller) advanceCanary(name string, namespace string) {
|
||||
return
|
||||
}
|
||||
c.recorder.SetStatus(cd)
|
||||
c.sendNotification(cd.Spec.TargetRef.Name, cd.Namespace,
|
||||
"Canary analysis completed successfully, promotion finished.", false)
|
||||
c.sendNotification(cd, "Canary analysis completed successfully, promotion finished.",
|
||||
false, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,15 +219,15 @@ func (c *Controller) checkCanaryStatus(cd *flaggerv1.Canary, deployer CanaryDepl
|
||||
}
|
||||
c.recorder.SetStatus(cd)
|
||||
c.recordEventInfof(cd, "Initialization done! %s.%s", cd.Name, cd.Namespace)
|
||||
c.sendNotification(cd.Spec.TargetRef.Name, cd.Namespace,
|
||||
"New deployment detected, initialization completed.", false)
|
||||
c.sendNotification(cd, "New deployment detected, initialization completed.",
|
||||
true, false)
|
||||
return false
|
||||
}
|
||||
|
||||
if diff, err := deployer.IsNewSpec(cd); diff {
|
||||
c.recordEventInfof(cd, "New revision detected! Scaling up %s.%s", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
c.sendNotification(cd.Spec.TargetRef.Name, cd.Namespace,
|
||||
"New revision detected, starting canary analysis.", false)
|
||||
c.sendNotification(cd, "New revision detected, starting canary analysis.",
|
||||
true, false)
|
||||
if err = deployer.Scale(cd, 1); err != nil {
|
||||
c.recordEventErrorf(cd, "%v", err)
|
||||
return false
|
||||
|
||||
@@ -30,10 +30,17 @@ type SlackPayload struct {
|
||||
|
||||
// SlackAttachment holds the markdown message body
|
||||
type SlackAttachment struct {
|
||||
Color string `json:"color"`
|
||||
AuthorName string `json:"author_name"`
|
||||
Text string `json:"text"`
|
||||
MrkdwnIn []string `json:"mrkdwn_in"`
|
||||
Color string `json:"color"`
|
||||
AuthorName string `json:"author_name"`
|
||||
Text string `json:"text"`
|
||||
MrkdwnIn []string `json:"mrkdwn_in"`
|
||||
Fields []SlackField `json:"fields"`
|
||||
}
|
||||
|
||||
type SlackField struct {
|
||||
Title string `json:"title"`
|
||||
Value string `json:"value"`
|
||||
Short bool `json:"short"`
|
||||
}
|
||||
|
||||
// NewSlack validates the Slack URL and returns a Slack object
|
||||
@@ -60,7 +67,7 @@ func NewSlack(hookURL string, username string, channel string) (*Slack, error) {
|
||||
}
|
||||
|
||||
// Post Slack message
|
||||
func (s *Slack) Post(workload string, namespace string, message string, warn bool) error {
|
||||
func (s *Slack) Post(workload string, namespace string, message string, fields []SlackField, warn bool) error {
|
||||
payload := SlackPayload{
|
||||
Channel: s.Channel,
|
||||
Username: s.Username,
|
||||
@@ -76,6 +83,7 @@ func (s *Slack) Post(workload string, namespace string, message string, warn boo
|
||||
AuthorName: fmt.Sprintf("%s.%s", workload, namespace),
|
||||
Text: message,
|
||||
MrkdwnIn: []string{"text"},
|
||||
Fields: fields,
|
||||
}
|
||||
|
||||
payload.Attachments = []SlackAttachment{a}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package version
|
||||
|
||||
var VERSION = "0.1.1"
|
||||
var VERSION = "0.1.2"
|
||||
var REVISION = "unknown"
|
||||
|
||||
Reference in New Issue
Block a user