Flux GitOps Toolkit is an opinionated set of Kubernetes controllers that enable GitOps practices.

Here’s Flux in action, managing a simple Nginx deployment. First, we create a Kubernetes manifest for Nginx:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

Now, let’s commit this to a Git repository. Flux will then automatically detect this change and apply it to the cluster.

To see Flux working, you’d typically have a GitRepository and a Kustomization resource in your cluster.

The GitRepository controller is responsible for continuously cloning the specified Git repository.

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: my-app-repo
  namespace: flux-system
spec:
  interval: 1m
  url: ssh://git@github.com/your-username/your-repo.git
  ref:
    branch: main
  secretRef:
    name: git-creds

This GitRepository resource tells Flux where to find your application’s manifests. The interval specifies how often Flux should check for updates in the Git repository. url is the Git repository URL, and ref specifies the branch or tag to track. secretRef points to a Kubernetes secret containing your SSH private key for accessing private repositories.

The Kustomization controller, on the other hand, takes the manifests from the GitRepository and applies them to your Kubernetes cluster.

apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: nginx-app
  namespace: flux-system
spec:
  interval: 5m
  path: ./nginx
  prune: true
  sourceRef:
    kind: GitRepository
    name: my-app-repo
  targetNamespace: default

This Kustomization resource tells Flux to look for manifests in the ./nginx directory within the my-app-repo Git repository. prune: true ensures that any resources no longer defined in Git will be deleted from the cluster. sourceRef links this Kustomization to the GitRepository defined earlier. targetNamespace specifies where in the cluster these resources should be deployed.

Flux’s core loop is driven by these two types of controllers. The GitRepository controller periodically fetches the latest commit from your Git repository. Once it has a new commit, it updates a GitRepository object in Kubernetes, which the Kustomization controller watches. The Kustomization controller then takes the manifests found at the specified path in the Git repository, applies any transformations (like Kustomize overlays), and reconciles them with the cluster’s current state. If prune is enabled and resources are missing from the latest Git commit, the Kustomization controller removes them from the cluster.

The most surprising thing about Flux is that it doesn’t just apply manifests; it actively reconciles your cluster state with the desired state defined in Git. If someone manually changes a resource in the cluster (e.g., scales a deployment), Flux will detect this drift and automatically revert it to match the state defined in Git during its next reconciliation cycle. This continuous reconciliation is the heart of GitOps.

Flux also offers more advanced features like Helm chart management (HelmRelease resource), image update automation (ImagePolicy and ImageUpdateAutomation resources), and multi-cluster management.

The next step in understanding Flux is exploring how to manage Helm releases and automate image updates within your GitOps workflow.

Want structured learning?

Take the full Flux course →