Flux v2 Progressive Delivery Patterns: Advanced GitOps Deployment Strategies
Flux v2 brings GitOps to the next level with native support for progressive delivery patterns through Flagger integration. This comprehensive guide explores advanced deployment strategies including canary analysis, blue-green deployments, A/B testing, and automated rollbacks for enterprise Kubernetes environments.
Flux v2 Progressive Delivery Patterns: Advanced GitOps Deployment Strategies
Executive Summary
Progressive delivery extends continuous delivery with fine-grained control over the release process, reducing deployment risk through gradual rollouts and automated analysis. This guide covers Flux v2’s integration with Flagger for implementing canary deployments, blue-green strategies, A/B testing, and automated rollback mechanisms in production environments.
Flux v2 Architecture Overview
Core Components
Flux v2 consists of specialized controllers working together:
# Install Flux v2 with all controllers
apiVersion: v1
kind: Namespace
metadata:
name: flux-system
---
# Source Controller - manages Git repositories and Helm repositories
apiVersion: apps/v1
kind: Deployment
metadata:
name: source-controller
namespace: flux-system
spec:
replicas: 1
selector:
matchLabels:
app: source-controller
template:
metadata:
labels:
app: source-controller
spec:
containers:
- name: manager
image: ghcr.io/fluxcd/source-controller:v1.2.0
args:
- --events-addr=http://notification-controller.flux-system.svc.cluster.local./
- --watch-all-namespaces=true
- --log-level=info
- --log-encoding=json
- --enable-leader-election
# Storage configuration
- --storage-path=/data
- --storage-adv-addr=source-controller.$(RUNTIME_NAMESPACE).svc.cluster.local.
# Performance tuning
- --concurrent=10
- --requeue-dependency=5s
env:
- name: RUNTIME_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 1000m
memory: 1Gi
volumeMounts:
- name: data
mountPath: /data
- name: tmp
mountPath: /tmp
volumes:
- name: data
emptyDir:
sizeLimit: 10Gi
- name: tmp
emptyDir: {}
---
# Kustomize Controller - applies Kustomize manifests
apiVersion: apps/v1
kind: Deployment
metadata:
name: kustomize-controller
namespace: flux-system
spec:
replicas: 1
selector:
matchLabels:
app: kustomize-controller
template:
metadata:
labels:
app: kustomize-controller
spec:
containers:
- name: manager
image: ghcr.io/fluxcd/kustomize-controller:v1.2.0
args:
- --events-addr=http://notification-controller.flux-system.svc.cluster.local./
- --watch-all-namespaces=true
- --log-level=info
- --log-encoding=json
- --enable-leader-election
# Performance tuning
- --concurrent=10
- --requeue-dependency=5s
# Feature flags
- --feature-gates=CacheSecretsAndConfigMaps=true
- --kube-api-qps=500
- --kube-api-burst=1000
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 1000m
memory: 1Gi
---
# Helm Controller - manages Helm releases
apiVersion: apps/v1
kind: Deployment
metadata:
name: helm-controller
namespace: flux-system
spec:
replicas: 1
selector:
matchLabels:
app: helm-controller
template:
metadata:
labels:
app: helm-controller
spec:
containers:
- name: manager
image: ghcr.io/fluxcd/helm-controller:v0.37.0
args:
- --events-addr=http://notification-controller.flux-system.svc.cluster.local./
- --watch-all-namespaces=true
- --log-level=info
- --log-encoding=json
- --enable-leader-election
# Performance tuning
- --concurrent=10
- --requeue-dependency=5s
# Helm-specific settings
- --http-retry-max=10
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 1000m
memory: 1Gi
---
# Notification Controller - handles events and alerts
apiVersion: apps/v1
kind: Deployment
metadata:
name: notification-controller
namespace: flux-system
spec:
replicas: 1
selector:
matchLabels:
app: notification-controller
template:
metadata:
labels:
app: notification-controller
spec:
containers:
- name: manager
image: ghcr.io/fluxcd/notification-controller:v1.2.0
args:
- --watch-all-namespaces=true
- --log-level=info
- --log-encoding=json
- --enable-leader-election
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 1000m
memory: 1Gi
ports:
- containerPort: 9090
name: http
- containerPort: 9292
name: http-webhook
- containerPort: 9440
name: healthz
Git Source Configuration
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: production-apps
namespace: flux-system
spec:
interval: 1m
url: https://github.com/example/production-apps
ref:
branch: main
secretRef:
name: git-credentials
# Performance optimization
timeout: 60s
# Verify commits
verify:
mode: head
secretRef:
name: git-pgp-key
---
apiVersion: v1
kind: Secret
metadata:
name: git-credentials
namespace: flux-system
type: Opaque
stringData:
username: git
password: <github-token>
---
apiVersion: v1
kind: Secret
metadata:
name: git-pgp-key
namespace: flux-system
type: Opaque
stringData:
identity: |
-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----
identity.pub: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----
Flagger Integration
Installing Flagger
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: flagger
namespace: flux-system
spec:
interval: 1h
url: https://flagger.app
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: flagger
namespace: flux-system
spec:
interval: 10m
chart:
spec:
chart: flagger
version: '1.35.x'
sourceRef:
kind: HelmRepository
name: flagger
namespace: flux-system
values:
# Mesh provider configuration
meshProvider: istio
metricsServer: http://prometheus.monitoring:9090
# Controller configuration
podMonitor:
enabled: true
namespace: flux-system
# Slack notifications
slack:
url: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
channel: deployments
user: flagger
# Resource limits
resources:
limits:
cpu: 1000m
memory: 512Mi
requests:
cpu: 100m
memory: 32Mi
---
# Install Flagger's Prometheus integration
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: flagger-grafana
namespace: flux-system
spec:
interval: 10m
chart:
spec:
chart: grafana
version: '7.0.x'
sourceRef:
kind: HelmRepository
name: flagger
values:
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus.monitoring:9090
isDefault: true
dashboardProviders:
dashboardproviders.yaml:
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: false
editable: true
options:
path: /var/lib/grafana/dashboards/default
Canary Deployment Patterns
Basic Canary with Traffic Shifting
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp
namespace: production
spec:
# Target deployment
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
# Progressive delivery service configuration
service:
port: 9898
targetPort: 9898
portDiscovery: true
# Load balancer configuration
apex:
annotations:
external-dns.alpha.kubernetes.io/hostname: myapp.example.com
# Canary service annotations
canary:
annotations:
external-dns.alpha.kubernetes.io/hostname: canary.myapp.example.com
# Primary service annotations
primary:
annotations:
external-dns.alpha.kubernetes.io/hostname: primary.myapp.example.com
# Autoscaling configuration
autoscalerRef:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
name: myapp
primaryScalerReplicas:
minReplicas: 2
maxReplicas: 10
canaryScalerReplicas:
minReplicas: 1
maxReplicas: 5
# Canary analysis configuration
analysis:
# Schedule interval for canary analysis
interval: 1m
# Max number of failed checks before rollback
threshold: 5
# Max traffic percentage routed to canary
maxWeight: 50
# Traffic increment step
stepWeight: 10
# Duration to wait before scaling down canary
stepWeightPromotion: 30
# Metrics for canary analysis
metrics:
# Request success rate
- name: request-success-rate
templateRef:
name: request-success-rate
namespace: flux-system
thresholdRange:
min: 99
interval: 1m
# Request duration P99
- name: request-duration
templateRef:
name: request-duration
namespace: flux-system
thresholdRange:
max: 500
interval: 1m
# Custom business metric
- name: error-rate
templateRef:
name: error-rate
namespace: flux-system
thresholdRange:
max: 1
interval: 1m
# Webhooks for external validation
webhooks:
# Load testing
- name: load-test
type: pre-rollout
url: http://flagger-loadtester.flux-system/
timeout: 5s
metadata:
type: bash
cmd: "curl -sd 'test' http://myapp-canary.production:9898/token | grep token"
# Smoke tests
- name: smoke-test
type: pre-rollout
url: http://flagger-loadtester.flux-system/
timeout: 30s
metadata:
type: bash
cmd: "./test/smoke-test.sh"
# Integration tests
- name: integration-test
url: http://flagger-loadtester.flux-system/
timeout: 60s
metadata:
type: cmd
cmd: "hey -z 1m -q 10 -c 2 http://myapp-canary.production:9898/"
# Approval gate
- name: approval-gate
type: confirm-rollout
url: http://flagger-loadtester.flux-system/gate/approve
# Rollback hook
- name: rollback-notification
type: rollback
url: http://notification-service.flux-system/
metadata:
message: "Canary rollback for myapp"
---
# Metric templates
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: request-success-rate
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
sum(
rate(
http_requests_total{
namespace="{{ namespace }}",
deployment=~"{{ target }}",
status!~"5.."
}[{{ interval }}]
)
)
/
sum(
rate(
http_requests_total{
namespace="{{ namespace }}",
deployment=~"{{ target }}"
}[{{ interval }}]
)
)
* 100
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: request-duration
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
histogram_quantile(0.99,
sum(
rate(
http_request_duration_seconds_bucket{
namespace="{{ namespace }}",
deployment=~"{{ target }}"
}[{{ interval }}]
)
) by (le)
)
* 1000
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: error-rate
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
sum(
rate(
app_errors_total{
namespace="{{ namespace }}",
deployment=~"{{ target }}"
}[{{ interval }}]
)
)
Advanced Canary with Session Affinity
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp-sticky
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
service:
port: 9898
# Session affinity configuration
sessionAffinity:
cookieName: myapp-session
maxAge: 86400
# Gateway references for Istio
gateways:
- public-gateway.istio-system
- private-gateway.istio-system
hosts:
- myapp.example.com
- myapp.internal.example.com
# Traffic policy
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
connectionPool:
http:
http1MaxPendingRequests: 1024
http2MaxRequests: 1024
maxRequestsPerConnection: 100
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
analysis:
interval: 1m
threshold: 10
maxWeight: 50
stepWeight: 5
# Canary match conditions
match:
# Header-based routing
- headers:
x-canary:
exact: "true"
# Cookie-based routing
- headers:
cookie:
regex: "^(.*?;)?(canary=true)(;.*)?$"
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
- name: request-duration
thresholdRange:
max: 500
interval: 1m
# Session-aware analysis
sessionAffinity:
cookieName: myapp-session
maxAge: 86400
A/B Testing Pattern
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp-ab-test
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
service:
port: 9898
gateways:
- public-gateway.istio-system
hosts:
- myapp.example.com
analysis:
# A/B testing configuration
interval: 1m
threshold: 10
iterations: 100
match:
# Route users with specific header to version B
- headers:
x-version:
exact: "b"
# Route 50% of matching traffic
percentage: 50
metrics:
# Business metrics for A/B testing
- name: conversion-rate
templateRef:
name: conversion-rate
thresholdRange:
min: 5.0
interval: 1m
- name: average-order-value
templateRef:
name: average-order-value
thresholdRange:
min: 100.0
interval: 5m
- name: user-engagement
templateRef:
name: user-engagement
thresholdRange:
min: 0.8
interval: 1m
webhooks:
# Statistical significance test
- name: ab-test-analysis
url: http://ab-test-service.flux-system/analyze
timeout: 30s
metadata:
minSampleSize: "1000"
confidenceLevel: "0.95"
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: conversion-rate
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
sum(
rate(
app_conversions_total{
namespace="{{ namespace }}",
deployment=~"{{ target }}"
}[{{ interval }}]
)
)
/
sum(
rate(
app_sessions_total{
namespace="{{ namespace }}",
deployment=~"{{ target }}"
}[{{ interval }}]
)
)
* 100
Blue-Green Deployment Pattern
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp-bluegreen
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
service:
port: 9898
gateways:
- public-gateway.istio-system
hosts:
- myapp.example.com
analysis:
# Blue-green uses iterations instead of progressive traffic shifting
interval: 1m
threshold: 5
# Number of iterations with green version before promotion
iterations: 10
# Mirror traffic to green for analysis
mirror: true
mirrorWeight: 100
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
- name: request-duration
thresholdRange:
max: 500
interval: 1m
webhooks:
# Pre-rollout validation
- name: pre-rollout-tests
type: pre-rollout
url: http://flagger-loadtester.flux-system/
metadata:
type: bash
cmd: "./test/validate-green.sh"
# Load testing during mirroring
- name: load-test
url: http://flagger-loadtester.flux-system/
timeout: 5s
metadata:
cmd: "hey -z 2m -q 10 -c 2 http://myapp-canary.production:9898/"
# Manual approval before cutover
- name: manual-approval
type: confirm-promotion
url: http://approval-service.flux-system/approve
metadata:
deployment: "myapp"
environment: "production"
Automated Rollback Strategies
Health Check-Based Rollback
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp-healthcheck
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
service:
port: 9898
analysis:
interval: 30s
threshold: 3
maxWeight: 50
stepWeight: 10
metrics:
# Built-in Kubernetes health checks
- name: kubernetes-health
templateRef:
name: kubernetes-health
thresholdRange:
min: 100
interval: 30s
# Custom health endpoint
- name: app-health
templateRef:
name: app-health
thresholdRange:
min: 100
interval: 30s
# Database connectivity
- name: database-health
templateRef:
name: database-health
thresholdRange:
min: 100
interval: 30s
webhooks:
# Immediate rollback on critical errors
- name: critical-error-check
url: http://flagger-loadtester.flux-system/
timeout: 5s
metadata:
type: bash
cmd: |
#!/bin/bash
ERRORS=$(curl -s http://myapp-canary.production:9898/metrics | \
grep critical_errors_total | \
awk '{print $2}')
if [ "$ERRORS" -gt "0" ]; then
exit 1
fi
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: kubernetes-health
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
sum(
up{
namespace="{{ namespace }}",
pod=~"{{ target }}-[a-z0-9]+-[a-z0-9]+"
}
)
/
count(
up{
namespace="{{ namespace }}",
pod=~"{{ target }}-[a-z0-9]+-[a-z0-9]+"
}
)
* 100
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: app-health
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
sum(
probe_success{
namespace="{{ namespace }}",
deployment="{{ target }}"
}
)
/
count(
probe_success{
namespace="{{ namespace }}",
deployment="{{ target }}"
}
)
* 100
Automatic Rollback on SLO Violation
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp-slo
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
service:
port: 9898
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
# SLO-based metrics
metrics:
# Availability SLO (99.9%)
- name: availability
templateRef:
name: availability-slo
thresholdRange:
min: 99.9
interval: 1m
# Latency SLO (P95 < 200ms)
- name: latency-p95
templateRef:
name: latency-p95-slo
thresholdRange:
max: 200
interval: 1m
# Error budget depletion rate
- name: error-budget
templateRef:
name: error-budget
thresholdRange:
min: 0.1
interval: 5m
webhooks:
# SLO violation alert
- name: slo-violation-alert
type: rollback
url: http://notification-service.flux-system/alert
metadata:
severity: "critical"
message: "SLO violation detected during canary deployment"
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: availability-slo
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
(
sum(rate(http_requests_total{namespace="{{ namespace }}",deployment=~"{{ target }}",status!~"5.."}[{{ interval }}]))
/
sum(rate(http_requests_total{namespace="{{ namespace }}",deployment=~"{{ target }}"}[{{ interval }}]))
) * 100
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: latency-p95-slo
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket{
namespace="{{ namespace }}",
deployment=~"{{ target }}"
}[{{ interval }}])) by (le)
) * 1000
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: error-budget
namespace: flux-system
spec:
provider:
type: prometheus
address: http://prometheus.monitoring:9090
query: |
(
1 - (
sum(rate(http_requests_total{namespace="{{ namespace }}",deployment=~"{{ target }}",status=~"5.."}[30d]))
/
sum(rate(http_requests_total{namespace="{{ namespace }}",deployment=~"{{ target }}"}[30d]))
)
) * 100
Multi-Cluster Progressive Delivery
Cluster Sequencing Strategy
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: app-dev
namespace: flux-system
spec:
interval: 5m
path: ./apps/myapp/overlays/dev
prune: true
sourceRef:
kind: GitRepository
name: production-apps
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: myapp
namespace: myapp-dev
timeout: 5m
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: app-staging
namespace: flux-system
spec:
# Deploy to staging only after dev succeeds
dependsOn:
- name: app-dev
interval: 10m
path: ./apps/myapp/overlays/staging
prune: true
sourceRef:
kind: GitRepository
name: production-apps
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: myapp
namespace: myapp-staging
# Additional validation for staging
postBuild:
substitute:
CLUSTER_NAME: "staging"
substituteFrom:
- kind: ConfigMap
name: staging-config
timeout: 10m
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: app-prod-canary
namespace: flux-system
spec:
# Deploy to production only after staging succeeds
dependsOn:
- name: app-staging
interval: 15m
path: ./apps/myapp/overlays/production
prune: true
sourceRef:
kind: GitRepository
name: production-apps
# Use canary deployment in production
patches:
- patch: |
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp
spec:
analysis:
interval: 1m
threshold: 10
maxWeight: 50
stepWeight: 5
target:
kind: Canary
name: myapp
healthChecks:
- apiVersion: flagger.app/v1beta1
kind: Canary
name: myapp
namespace: production
timeout: 30m
Multi-Region Rollout
apiVersion: v1
kind: ConfigMap
metadata:
name: rollout-regions
namespace: flux-system
data:
regions.yaml: |
regions:
- name: us-east-1
priority: 1
canary:
maxWeight: 25
stepWeight: 5
- name: us-west-2
priority: 2
canary:
maxWeight: 50
stepWeight: 10
- name: eu-west-1
priority: 3
canary:
maxWeight: 50
stepWeight: 10
- name: ap-southeast-1
priority: 4
canary:
maxWeight: 100
stepWeight: 20
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: app-us-east-1
namespace: flux-system
spec:
interval: 10m
path: ./apps/myapp/overlays/us-east-1
sourceRef:
kind: GitRepository
name: production-apps
kubeConfig:
secretRef:
name: us-east-1-kubeconfig
healthChecks:
- apiVersion: flagger.app/v1beta1
kind: Canary
name: myapp
namespace: production
timeout: 30m
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: app-us-west-2
namespace: flux-system
spec:
# Deploy to us-west-2 after us-east-1
dependsOn:
- name: app-us-east-1
interval: 10m
path: ./apps/myapp/overlays/us-west-2
sourceRef:
kind: GitRepository
name: production-apps
kubeConfig:
secretRef:
name: us-west-2-kubeconfig
timeout: 30m
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: app-eu-west-1
namespace: flux-system
spec:
# Deploy to eu-west-1 after us-west-2
dependsOn:
- name: app-us-west-2
interval: 10m
path: ./apps/myapp/overlays/eu-west-1
sourceRef:
kind: GitRepository
name: production-apps
kubeConfig:
secretRef:
name: eu-west-1-kubeconfig
timeout: 30m
Notification and Alerting
Comprehensive Alert Configuration
apiVersion: notification.toolkit.fluxcd.io/v1beta2
kind: Provider
metadata:
name: slack
namespace: flux-system
spec:
type: slack
channel: deployments
username: Flux
secretRef:
name: slack-webhook
---
apiVersion: notification.toolkit.fluxcd.io/v1beta2
kind: Provider
metadata:
name: pagerduty
namespace: flux-system
spec:
type: generic
address: https://events.pagerduty.com/v2/enqueue
secretRef:
name: pagerduty-token
---
apiVersion: notification.toolkit.fluxcd.io/v1beta2
kind: Alert
metadata:
name: canary-alerts
namespace: flux-system
spec:
providerRef:
name: slack
eventSeverity: info
eventSources:
- kind: Canary
name: '*'
namespace: production
exclusionList:
- ".*health check passed.*"
---
apiVersion: notification.toolkit.fluxcd.io/v1beta2
kind: Alert
metadata:
name: critical-alerts
namespace: flux-system
spec:
providerRef:
name: pagerduty
eventSeverity: error
eventSources:
- kind: Canary
name: '*'
namespace: production
inclusionList:
- ".*rollback.*"
- ".*failed.*"
---
apiVersion: v1
kind: Secret
metadata:
name: slack-webhook
namespace: flux-system
type: Opaque
stringData:
address: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
---
apiVersion: v1
kind: Secret
metadata:
name: pagerduty-token
namespace: flux-system
type: Opaque
stringData:
token: <pagerduty-integration-key>
Monitoring and Observability
Flagger Metrics Dashboard
apiVersion: v1
kind: ConfigMap
metadata:
name: flagger-dashboard
namespace: flux-system
data:
dashboard.json: |
{
"dashboard": {
"title": "Flagger Progressive Delivery",
"panels": [
{
"title": "Canary Status",
"targets": [
{
"expr": "flagger_canary_status"
}
]
},
{
"title": "Canary Weight",
"targets": [
{
"expr": "flagger_canary_weight"
}
]
},
{
"title": "Canary Duration",
"targets": [
{
"expr": "flagger_canary_duration_seconds"
}
]
},
{
"title": "Success Rate Comparison",
"targets": [
{
"expr": "sum(rate(http_requests_total{deployment=\"myapp-primary\",status!~\"5..\"}[1m])) / sum(rate(http_requests_total{deployment=\"myapp-primary\"}[1m])) * 100",
"legendFormat": "Primary"
},
{
"expr": "sum(rate(http_requests_total{deployment=\"myapp-canary\",status!~\"5..\"}[1m])) / sum(rate(http_requests_total{deployment=\"myapp-canary\"}[1m])) * 100",
"legendFormat": "Canary"
}
]
},
{
"title": "Latency Comparison (P95)",
"targets": [
{
"expr": "histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{deployment=\"myapp-primary\"}[1m])) by (le)) * 1000",
"legendFormat": "Primary"
},
{
"expr": "histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{deployment=\"myapp-canary\"}[1m])) by (le)) * 1000",
"legendFormat": "Canary"
}
]
}
]
}
}
Best Practices
Deployment Strategy Selection
- Canary Deployments: Gradual traffic shifting for most production workloads
- Blue-Green: Instant cutover for services requiring all-or-nothing deployment
- A/B Testing: Feature validation with specific user segments
- Progressive Rollout: Multi-cluster deployment with staged regional rollout
Performance Optimization
- Metric Queries: Optimize Prometheus queries for fast analysis
- Analysis Intervals: Balance safety with deployment speed
- Webhook Timeouts: Set appropriate timeouts for validation webhooks
- Resource Limits: Right-size Flux and Flagger controller resources
Operational Excellence
- Monitoring: Comprehensive dashboards for canary progress
- Alerting: Multi-channel notifications for deployment events
- Testing: Automated smoke and integration tests
- Documentation: Document rollout strategies and rollback procedures
- Disaster Recovery: Plan for GitOps infrastructure failure
Conclusion
Flux v2 with Flagger provides enterprise-grade progressive delivery capabilities that significantly reduce deployment risk while maintaining deployment velocity. By implementing canary deployments, blue-green strategies, automated rollbacks, and multi-cluster orchestration, organizations can achieve safe, automated production deployments.
Key takeaways:
- Use canary deployments with automated analysis for gradual rollouts
- Implement comprehensive metrics and health checks for early issue detection
- Leverage blue-green deployments for instant cutover requirements
- Configure automated rollbacks based on SLO violations
- Orchestrate multi-cluster deployments with dependency management
- Monitor deployment progress with detailed metrics and alerts
With proper implementation of these patterns, teams can deploy confidently to production multiple times per day while maintaining high availability and reliability standards.