Services

Flux CD

GitOps toolkit for Kubernetes with modular components and native image automation


Flux is a CNCF graduated project that provides a set of continuous and progressive delivery solutions for Kubernetes. It keeps clusters in sync with sources of configuration and automates updates when new code is deployed.

What you'll learn

Related tools

Why Flux?#

Flux brings a modular, composable GitOps architecture to Kubernetes:

FeatureBenefit
CNCF GraduatedProduction-ready, community-driven
Modular DesignUse only the components you need
Native Image AutomationAutomatic image updates with policies
Multi-tenancyBuilt-in tenant isolation
OCI SupportStore configs in container registries
SOPS IntegrationNative secret decryption

Architecture#

1
┌─────────────────────────────────────────────────────────────────┐
2
│ Flux Components │
3
│ │
4
│ ┌─────────────────────────────────────────────────────────┐ │
5
│ │ Source Controller │ │
6
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │
7
│ │ │GitRepo │ │HelmRepo │ │OCIRepo │ │ │
8
│ │ └───────────┘ └───────────┘ └───────────┘ │ │
9
│ └──────────────────────────┬──────────────────────────────┘ │
10
│ │ │
11
│ ┌──────────────────────────▼──────────────────────────────┐ │
12
│ │ Kustomize / Helm Controller │ │
13
│ │ ┌─────────────────┐ ┌─────────────────┐ │ │
14
│ │ │ Kustomization │ │ HelmRelease │ │ │
15
│ │ └─────────────────┘ └─────────────────┘ │ │
16
│ └──────────────────────────┬──────────────────────────────┘ │
17
│ │ │
18
│ ┌──────────────────────────▼──────────────────────────────┐ │
19
│ │ Notification Controller │ │
20
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │
21
│ │ │ Provider │ │ Alert │ │ Receiver │ │ │
22
│ │ └───────────┘ └───────────┘ └───────────┘ │ │
23
│ └─────────────────────────────────────────────────────────┘ │
24
│ │
25
│ ┌─────────────────────────────────────────────────────────┐ │
26
│ │ Image Automation Controllers │ │
27
│ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │
28
│ │ │ ImageRepository │ │ ImagePolicy │ │ │
29
│ │ └─────────────────────┘ └─────────────────────┘ │ │
30
│ │ ┌─────────────────────┐ │ │
31
│ │ │ ImageUpdateAuto │ │ │
32
│ │ └─────────────────────┘ │ │
33
│ └─────────────────────────────────────────────────────────┘ │
34
└─────────────────────────────────────────────────────────────────┘

Controllers#

Source Controller Fetches artifacts from Git repositories, Helm repositories, S3-compatible buckets, and OCI registries.

Kustomize Controller Builds and applies Kustomize overlays. Supports variable substitution and SOPS decryption.

Helm Controller Manages Helm chart releases with support for values files, dependencies, and drift detection.

Notification Controller Handles inbound webhooks and outbound notifications to Slack, Teams, PagerDuty, and more.

Image Reflector Controller Scans container registries and reflects image metadata.

Image Automation Controller Updates Git repositories with new image versions based on policies.


Installation#

Using Flux CLI#

1
#!/bin/bash
2
# Flux installation script
3
4
# Install Flux CLI
5
curl -s https://fluxcd.io/install.sh | sudo bash
6
7
# Verify installation
8
flux --version
9
10
# Pre-flight checks
11
flux check --pre
12
13
# Bootstrap Flux with GitHub
14
flux bootstrap github \
15
--owner=company \
16
--repository=flux-config \
17
--branch=main \
18
--path=clusters/production \
19
--personal \
20
--components-extra=image-reflector-controller,image-automation-controller
21
22
# Verify Flux is running
23
flux check
24
25
# Get reconciliation status
26
flux get all
27
28
echo "Flux installed and bootstrapped successfully"

Bootstrap with GitLab#

1
flux bootstrap gitlab \
2
--owner=company \
3
--repository=flux-config \
4
--branch=main \
5
--path=clusters/production \
6
--token-auth

Bootstrap with Existing Repository#

1
flux bootstrap git \
2
--url=ssh://[email protected]/company/fleet-infra \
3
--branch=main \
4
--path=clusters/production \
5
--private-key-file=/path/to/private/key

Source Management#

GitRepository#

1
apiVersion: source.toolkit.fluxcd.io/v1
2
kind: GitRepository
3
metadata:
4
name: application-repo
5
namespace: flux-system
6
spec:
7
interval: 1m
8
url: https://github.com/company/application.git
9
ref:
10
branch: main
11
secretRef:
12
name: github-auth
13
ignore: |
14
# Exclude CI/CD files
15
/.github/
16
/.gitlab-ci.yml
17
/Jenkinsfile

HelmRepository#

1
apiVersion: source.toolkit.fluxcd.io/v1
2
kind: HelmRepository
3
metadata:
4
name: bitnami
5
namespace: flux-system
6
spec:
7
interval: 30m
8
url: https://charts.bitnami.com/bitnami
9
10
---
11
apiVersion: source.toolkit.fluxcd.io/v1
12
kind: HelmRepository
13
metadata:
14
name: ingress-nginx
15
namespace: flux-system
16
spec:
17
interval: 30m
18
url: https://kubernetes.github.io/ingress-nginx

OCIRepository#

1
apiVersion: source.toolkit.fluxcd.io/v1beta2
2
kind: OCIRepository
3
metadata:
4
name: company-charts
5
namespace: flux-system
6
spec:
7
interval: 5m
8
url: oci://ghcr.io/company/charts
9
ref:
10
semver: ">=1.0.0"
11
secretRef:
12
name: ghcr-auth

Bucket (S3-compatible)#

1
apiVersion: source.toolkit.fluxcd.io/v1beta2
2
kind: Bucket
3
metadata:
4
name: config-bucket
5
namespace: flux-system
6
spec:
7
interval: 5m
8
provider: aws
9
bucketName: my-config-bucket
10
region: us-east-1
11
secretRef:
12
name: aws-credentials

Kustomization#

Basic Kustomization#

1
apiVersion: kustomize.toolkit.fluxcd.io/v1
2
kind: Kustomization
3
metadata:
4
name: applications
5
namespace: flux-system
6
spec:
7
interval: 10m
8
path: ./apps/production
9
prune: true
10
sourceRef:
11
kind: GitRepository
12
name: application-repo
13
14
# Health checks for deployed resources
15
healthChecks:
16
- apiVersion: apps/v1
17
kind: Deployment
18
name: payment-service
19
namespace: payments
20
- apiVersion: apps/v1
21
kind: Deployment
22
name: user-service
23
namespace: users
24
25
# Timeout for health checks
26
timeout: 5m
27
28
# Retry on failure
29
retryInterval: 2m

Kustomization with Dependencies#

1
apiVersion: kustomize.toolkit.fluxcd.io/v1
2
kind: Kustomization
3
metadata:
4
name: applications
5
namespace: flux-system
6
spec:
7
interval: 10m
8
path: ./apps/production
9
prune: true
10
sourceRef:
11
kind: GitRepository
12
name: application-repo
13
14
# Wait for dependencies
15
dependsOn:
16
- name: infrastructure
17
- name: cert-manager
18
19
# Post-build variable substitution
20
postBuild:
21
substitute:
22
CLUSTER_NAME: production
23
ENVIRONMENT: prod
24
substituteFrom:
25
- kind: ConfigMap
26
name: cluster-config
27
- kind: Secret
28
name: cluster-secrets

Kustomization with SOPS Decryption#

1
apiVersion: kustomize.toolkit.fluxcd.io/v1
2
kind: Kustomization
3
metadata:
4
name: applications
5
namespace: flux-system
6
spec:
7
interval: 10m
8
path: ./apps/production
9
prune: true
10
sourceRef:
11
kind: GitRepository
12
name: application-repo
13
14
# Decryption with SOPS
15
decryption:
16
provider: sops
17
secretRef:
18
name: sops-age

Multi-tenant Kustomization#

1
apiVersion: kustomize.toolkit.fluxcd.io/v1
2
kind: Kustomization
3
metadata:
4
name: tenants
5
namespace: flux-system
6
spec:
7
interval: 5m
8
path: ./tenants
9
prune: true
10
sourceRef:
11
kind: GitRepository
12
name: application-repo
13
14
# Service account impersonation for multi-tenancy
15
serviceAccountName: flux-reconciler
16
17
# Validation and enforcement
18
validation: client
19
force: false

HelmRelease#

Basic HelmRelease#

1
apiVersion: helm.toolkit.fluxcd.io/v2
2
kind: HelmRelease
3
metadata:
4
name: payment-service
5
namespace: payments
6
spec:
7
interval: 30m
8
timeout: 10m
9
10
chart:
11
spec:
12
chart: payment-service
13
version: ">=1.0.0 <2.0.0"
14
sourceRef:
15
kind: HelmRepository
16
name: company-charts
17
namespace: flux-system
18
interval: 5m
19
20
# Installation configuration
21
install:
22
createNamespace: true
23
remediation:
24
retries: 3
25
26
# Upgrade configuration
27
upgrade:
28
remediation:
29
retries: 3
30
remediateLastFailure: true
31
cleanupOnFail: true
32
33
# Rollback configuration
34
rollback:
35
timeout: 5m
36
cleanupOnFail: true
37
38
# Test configuration
39
test:
40
enable: true
41
timeout: 5m
42
43
# Values
44
values:
45
replicaCount: 3
46
47
image:
48
repository: ghcr.io/company/payment-service
49
tag: v1.2.3
50
51
resources:
52
requests:
53
cpu: 100m
54
memory: 128Mi
55
limits:
56
cpu: 500m
57
memory: 512Mi
58
59
ingress:
60
enabled: true
61
className: nginx
62
hosts:
63
- host: payments.example.com
64
paths:
65
- path: /
66
pathType: Prefix
67
68
autoscaling:
69
enabled: true
70
minReplicas: 3
71
maxReplicas: 10
72
targetCPUUtilizationPercentage: 70

HelmRelease with Drift Detection#

1
apiVersion: helm.toolkit.fluxcd.io/v2
2
kind: HelmRelease
3
metadata:
4
name: payment-service
5
namespace: payments
6
spec:
7
interval: 30m
8
chart:
9
spec:
10
chart: payment-service
11
sourceRef:
12
kind: HelmRepository
13
name: company-charts
14
namespace: flux-system
15
16
# Drift detection
17
driftDetection:
18
mode: enabled
19
ignore:
20
- paths: ["/spec/replicas"]
21
target:
22
kind: Deployment
23
24
values:
25
replicaCount: 3

HelmRelease with External Values#

1
apiVersion: helm.toolkit.fluxcd.io/v2
2
kind: HelmRelease
3
metadata:
4
name: payment-service
5
namespace: payments
6
spec:
7
interval: 30m
8
chart:
9
spec:
10
chart: payment-service
11
sourceRef:
12
kind: HelmRepository
13
name: company-charts
14
namespace: flux-system
15
16
# Values from external sources
17
valuesFrom:
18
- kind: ConfigMap
19
name: payment-service-config
20
valuesKey: values.yaml
21
- kind: Secret
22
name: payment-service-secrets
23
valuesKey: secrets.yaml
24
25
# Dependency on other HelmReleases
26
dependsOn:
27
- name: postgresql
28
namespace: databases
29
- name: redis
30
namespace: caching

HelmRelease with OCI Chart#

1
apiVersion: helm.toolkit.fluxcd.io/v2
2
kind: HelmRelease
3
metadata:
4
name: monitoring-stack
5
namespace: monitoring
6
spec:
7
interval: 1h
8
9
chartRef:
10
kind: OCIRepository
11
name: kube-prometheus-stack
12
namespace: flux-system
13
14
values:
15
prometheus:
16
prometheusSpec:
17
retention: 30d
18
storageSpec:
19
volumeClaimTemplate:
20
spec:
21
storageClassName: gp3
22
resources:
23
requests:
24
storage: 100Gi
25
26
grafana:
27
adminPassword: ${GRAFANA_ADMIN_PASSWORD}

Image Automation#

ImageRepository#

1
apiVersion: image.toolkit.fluxcd.io/v1beta2
2
kind: ImageRepository
3
metadata:
4
name: payment-service
5
namespace: flux-system
6
spec:
7
image: ghcr.io/company/payment-service
8
interval: 5m
9
secretRef:
10
name: ghcr-auth

ImagePolicy#

1
# Production: only stable releases
2
apiVersion: image.toolkit.fluxcd.io/v1beta2
3
kind: ImagePolicy
4
metadata:
5
name: payment-service-production
6
namespace: flux-system
7
spec:
8
imageRepositoryRef:
9
name: payment-service
10
policy:
11
semver:
12
range: ">=1.0.0 <2.0.0"
13
filterTags:
14
pattern: '^v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)$'
15
extract: '$version'
16
17
---
18
# Staging: latest including pre-releases
19
apiVersion: image.toolkit.fluxcd.io/v1beta2
20
kind: ImagePolicy
21
metadata:
22
name: payment-service-staging
23
namespace: flux-system
24
spec:
25
imageRepositoryRef:
26
name: payment-service
27
policy:
28
alphabetical:
29
order: desc
30
filterTags:
31
pattern: '^main-[a-f0-9]+-(?P<ts>[0-9]+)$'
32
extract: '$ts'

ImageUpdateAutomation#

1
apiVersion: image.toolkit.fluxcd.io/v1beta2
2
kind: ImageUpdateAutomation
3
metadata:
4
name: application-automation
5
namespace: flux-system
6
spec:
7
interval: 30m
8
9
sourceRef:
10
kind: GitRepository
11
name: application-repo
12
13
git:
14
checkout:
15
ref:
16
branch: main
17
commit:
18
author:
19
20
name: FluxBot
21
messageTemplate: |
22
chore: update images
23
24
Automated image update:
25
{{range .Changed.Changes}}
26
- {{.OldValue}} -> {{.NewValue}}
27
{{end}}
28
push:
29
branch: main
30
31
update:
32
path: ./apps
33
strategy: Setters

Image Update Markers in Manifests#

1
# apps/production/payment-service/deployment.yaml
2
apiVersion: apps/v1
3
kind: Deployment
4
metadata:
5
name: payment-service
6
namespace: payments
7
spec:
8
replicas: 3
9
selector:
10
matchLabels:
11
app: payment-service
12
template:
13
metadata:
14
labels:
15
app: payment-service
16
spec:
17
containers:
18
- name: payment-service
19
# {"$imagepolicy": "flux-system:payment-service-production"}
20
image: ghcr.io/company/payment-service:v1.2.3
21
ports:
22
- containerPort: 8080

Notifications#

Providers#

1
apiVersion: notification.toolkit.fluxcd.io/v1beta3
2
kind: Provider
3
metadata:
4
name: slack-alerts
5
namespace: flux-system
6
spec:
7
type: slack
8
channel: flux-notifications
9
secretRef:
10
name: slack-webhook
11
12
---
13
apiVersion: notification.toolkit.fluxcd.io/v1beta3
14
kind: Provider
15
metadata:
16
name: github-status
17
namespace: flux-system
18
spec:
19
type: github
20
address: https://github.com/company/application
21
secretRef:
22
name: github-token
23
24
---
25
apiVersion: notification.toolkit.fluxcd.io/v1beta3
26
kind: Provider
27
metadata:
28
name: pagerduty
29
namespace: flux-system
30
spec:
31
type: pagerduty
32
secretRef:
33
name: pagerduty-key

Alerts#

1
apiVersion: notification.toolkit.fluxcd.io/v1beta3
2
kind: Alert
3
metadata:
4
name: flux-alerts
5
namespace: flux-system
6
spec:
7
providerRef:
8
name: slack-alerts
9
eventSeverity: info
10
eventSources:
11
- kind: GitRepository
12
name: '*'
13
- kind: Kustomization
14
name: '*'
15
- kind: HelmRelease
16
name: '*'
17
exclusionList:
18
- ".*no new revision.*"
19
20
---
21
apiVersion: notification.toolkit.fluxcd.io/v1beta3
22
kind: Alert
23
metadata:
24
name: critical-alerts
25
namespace: flux-system
26
spec:
27
providerRef:
28
name: pagerduty
29
eventSeverity: error
30
eventSources:
31
- kind: Kustomization
32
name: '*'
33
namespace: production
34
- kind: HelmRelease
35
name: '*'
36
namespace: production

Webhook Receiver#

1
apiVersion: notification.toolkit.fluxcd.io/v1
2
kind: Receiver
3
metadata:
4
name: github-webhook
5
namespace: flux-system
6
spec:
7
type: github
8
events:
9
- push
10
secretRef:
11
name: github-webhook-secret
12
resources:
13
- kind: GitRepository
14
name: application-repo
15
namespace: flux-system

Secret Management with SOPS#

SOPS Configuration#

1
# .sops.yaml
2
creation_rules:
3
- path_regex: .*\.enc\.yaml$
4
encrypted_regex: ^(data|stringData)$
5
age: age1...public-key...
6
7
- path_regex: clusters/production/.*
8
encrypted_regex: ^(data|stringData)$
9
age: >-
10
age1...production-key...,
11
age1...backup-key...
12
13
- path_regex: clusters/staging/.*
14
encrypted_regex: ^(data|stringData)$
15
age: age1...staging-key...

Encrypted Secret#

1
# secrets/database.enc.yaml
2
apiVersion: v1
3
kind: Secret
4
metadata:
5
name: database-credentials
6
namespace: payments
7
type: Opaque
8
stringData:
9
username: ENC[AES256_GCM,data:...,type:str]
10
password: ENC[AES256_GCM,data:...,type:str]
11
sops:
12
age:
13
- recipient: age1...
14
enc: |
15
-----BEGIN AGE ENCRYPTED FILE-----
16
...
17
-----END AGE ENCRYPTED FILE-----
18
lastmodified: "2024-01-15T10:30:00Z"
19
version: 3.8.1

SOPS Key Secret#

1
# Create SOPS key secret
2
age-keygen -o age.agekey
3
4
kubectl create secret generic sops-age \
5
--namespace=flux-system \
6
--from-file=age.agekey=age.agekey

Repository Structure#

1
flux-repo/
2
├── apps/
3
│ ├── base/
4
│ │ ├── payment-service/
5
│ │ │ ├── deployment.yaml
6
│ │ │ ├── service.yaml
7
│ │ │ └── kustomization.yaml
8
│ │ └── user-service/
9
│ └── overlays/
10
│ ├── development/
11
│ ├── staging/
12
│ └── production/
13
14
├── infrastructure/
15
│ ├── base/
16
│ │ ├── cert-manager/
17
│ │ ├── ingress-nginx/
18
│ │ └── monitoring/
19
│ └── overlays/
20
│ ├── development/
21
│ ├── staging/
22
│ └── production/
23
24
├── clusters/
25
│ ├── development/
26
│ │ ├── flux-system/
27
│ │ ├── apps.yaml
28
│ │ └── infrastructure.yaml
29
│ ├── staging/
30
│ └── production/
31
│ ├── flux-system/
32
│ ├── apps.yaml
33
│ ├── infrastructure.yaml
34
│ └── notifications.yaml
35
36
└── tenants/
37
├── team-payments/
38
│ ├── rbac.yaml
39
│ └── namespace.yaml
40
└── team-users/

Cluster Configuration#

1
# clusters/production/apps.yaml
2
apiVersion: kustomize.toolkit.fluxcd.io/v1
3
kind: Kustomization
4
metadata:
5
name: apps
6
namespace: flux-system
7
spec:
8
interval: 10m
9
sourceRef:
10
kind: GitRepository
11
name: flux-system
12
path: ./apps/overlays/production
13
prune: true
14
dependsOn:
15
- name: infrastructure

Best Practices#

Flux Configuration#

  1. Use interval appropriately - Balance between responsiveness and API load
  2. Enable pruning - Remove resources not in Git
  3. Set health checks - Verify deployments before marking as ready
  4. Use dependencies - Ensure correct deployment order

Security#

  1. SOPS for secrets - Never commit plain secrets
  2. RBAC isolation - Use separate service accounts per tenant
  3. Network policies - Restrict Flux controller network access
  4. Audit logging - Enable notification alerts for all changes

Performance#

  1. Repository caching - Reduce Git operations
  2. Selective reconciliation - Only reconcile changed paths
  3. Resource limits - Set appropriate controller limits
  4. Parallel reconciliation - Configure controller concurrency

Flux vs ArgoCD#

AspectFluxArgoCD
UIWeave GitOps (separate)Built-in rich UI
Image UpdatesNative ImagePolicyArgo Image Updater
ArchitectureModular controllersMonolithic
Multi-tenancyBuilt-in isolationProject-based
Learning CurveSteeperGentler
Resource UsageLowerHigher