Flux CD is not just a deployment tool; it’s a system that actively watches your Git repository and enforces its desired state on your Kubernetes cluster, continuously.

Let’s see Flux in action. Imagine you have a simple Kubernetes Deployment definition in a Git repository:

# gitops-repo/apps/my-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: nginx:1.25.0

You’ve set up Flux to monitor this Git repository. Flux will detect this file, reconcile it, and create the Deployment in your cluster. Now, if you change the replicas to 3 and push:

# gitops-repo/apps/my-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: nginx:1.25.0

Flux will automatically update the Deployment in your cluster to have 3 replicas. It doesn’t wait for a kubectl apply command; it continuously ensures your cluster matches Git.

The core problem Flux solves is bridging the gap between your declarative infrastructure definitions (usually in Git) and the actual state of your Kubernetes cluster. Traditional CI/CD pipelines push changes to the cluster. GitOps, powered by tools like Flux, pulls changes from the cluster. This pull-based model offers significant advantages in security and reliability.

Flux operates through several components, each with a specific role:

  • Source Controller: This component is responsible for fetching manifests from external sources like Git repositories, Helm repositories, or S3 buckets. It watches your configured sources and makes the fetched content available to other controllers.
  • Kustomize Controller: If you use Kustomize for managing manifest variations, this controller applies them. It takes the sources provided by the Source Controller and applies them to the cluster.
  • Helm Controller: For managing Helm charts, this controller handles the lifecycle of Helm releases based on your Git configuration.
  • Notification Controller: This component handles sending notifications (e.g., Slack, Teams, email) about events happening in Flux, such as successful deployments or reconciliation errors.
  • Image Reflector Controller & Image Automation Controller: These work together to scan container image registries for new image tags and can automatically update your Git repository with new image tags, triggering a GitOps reconciliation.

To set up Flux, you typically start by installing it into your cluster. The easiest way is using the flux bootstrap command. This command installs Flux, configures it to watch a specified Git repository, and registers your cluster with Flux.

Here’s a typical bootstrap command:

flux bootstrap git \
  --url ssh://git@github.com/your-username/your-gitops-repo.git \
  --branch main \
  --path ./clusters/my-cluster

This command does several things:

  1. Installs the Flux controllers into your cluster.
  2. Creates a GitRepository custom resource that points to your specified Git URL and branch.
  3. Creates a Kustomization custom resource that tells Flux to apply manifests found at the ./clusters/my-my-cluster path within that Git repository to your current Kubernetes context.
  4. Generates SSH keys for Flux to access your Git repository securely.

After bootstrapping, you define your desired state in the Git repository. For instance, to deploy an application, you’d create a Kustomization resource in your Git repo that points to a directory containing your Kubernetes manifests.

# gitops-repo/clusters/my-cluster/apps.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-apps
  namespace: flux-system
spec:
  interval: 10m
  sourceRef:
    kind: GitRepository
    name: flux-system # This refers to the GitRepository created by bootstrap
  path: ./apps/my-app
  prune: true
  wait: true

This Kustomization resource tells Flux to:

  • interval: 10m: Periodically check the Git repository for changes every 10 minutes.
  • sourceRef: Use the flux-system Git repository (the one Flux bootstrapped with).
  • path: ./apps/my-app: Look for Kubernetes manifests in the apps/my-app directory within that repository.
  • prune: true: Remove any resources that are no longer defined in Git.
  • wait: true: Wait for all applied resources to be ready before marking the reconciliation as successful.

Flux’s reconciliation loop is the heart of its operation. The Source Controller fetches the latest commit from your Git repository. Then, the Kustomize Controller (or Helm Controller) takes the manifests from the specified path in that commit and applies them to your cluster. If any resource in the cluster doesn’t match the desired state in Git, Flux will take action to correct it. This includes creating, updating, or deleting resources.

A common pattern is to use separate GitRepository and Kustomization resources for different applications or environments. For example, you might have one GitRepository for your core infrastructure and separate Kustomizations pointing to different subdirectories for your staging and production applications.

The most surprising thing about Flux’s reconciliation is its inherent idempotency and how it handles drift. If a user manually changes a resource in the cluster (e.g., scales a deployment using kubectl scale), Flux will detect this discrepancy during its next reconciliation cycle and revert the change to match the state defined in Git. It doesn’t just apply changes; it enforces the Git state.

One of the most overlooked aspects of Flux is its robust eventing and notification system, which can be leveraged to build sophisticated alerting workflows. Beyond simple deployment success/failure, you can configure Flux to send detailed notifications based on specific Kubernetes events or reconciliation outcomes. This allows you to integrate Flux with incident management tools and build automated responses to deployment issues, rather than just basic alerts. For example, you can set up a notification to trigger a rollback if a deployment fails to become ready within a certain timeframe, or to alert a specific team channel when a critical application is updated.

The next step after mastering GitOps-driven deployments is often automating image updates, which Flux also supports through its image automation controllers.

Want structured learning?

Take the full DevOps & Platform Engineering course →