Flux’s GitOps sync with Kustomize overlays is surprisingly not about Git, but about reconciling the desired state in your Git repo with the actual state in your cluster.
Let’s see it in action. Imagine you have a simple Nginx deployment defined in base/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Now, you want to scale this up for production using an overlay. Your Kustomization file overlays/production/kustomization.yaml might look like this:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patchesStrategicMerge:
- deployment-patch.yaml
And overlays/production/deployment-patch.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
Flux, configured to watch this Git repository, will notice these files. It uses kustomize build internally to generate the final Kubernetes manifests. For the production environment, Flux will effectively run kustomize build overlays/production and get:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 3 # <-- This is the patched value
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Flux then takes these generated manifests and applies them to your Kubernetes cluster, ensuring the cluster’s state matches what Kustomize produced from your Git repo.
The core problem Kustomize + Flux solves is managing environment-specific configurations without duplicating your base manifests. Instead of having separate dev-deployment.yaml and prod-deployment.yaml, you have a single base/deployment.yaml and patches that only modify the differences. Flux then acts as the automated agent, continuously syncing the rendered Kustomize output from Git to your cluster.
Internally, Flux uses a Kustomization controller. When you define a Kustomization resource in Flux, you point it to a Git repository path and a branch. Flux periodically fetches the latest commit from that branch. It then executes kustomize build on the specified directory. The output of this build is a set of standard Kubernetes YAML manifests. Flux’s reconciler then compares these generated manifests with the resources currently running in your cluster and applies any necessary create, update, or delete operations.
The Kustomization resource in Flux is key. A typical Flux Kustomization definition for our example might look like this:
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: nginx-production
namespace: flux-system
spec:
interval: 5m
path: ./overlays/production # Path within the Git repository
prune: true
sourceRef:
kind: GitRepository
name: my-app-repo # Assumes a GitRepository resource named 'my-app-repo' is defined
targetNamespace: default # Where to deploy the resources
This tells Flux to look at the ./overlays/production directory in the my-app-repo GitRepository, build it using Kustomize, and apply the resulting manifests to the default namespace every 5 minutes. prune: true ensures that any resources no longer present in the Kustomize output are removed from the cluster.
The surprising part is how seamlessly Kustomize’s declarative patching integrates with Flux’s declarative reconciliation. Flux doesn’t just apply raw YAML; it understands that Kustomize is the generator of the desired state. This allows for powerful templating without introducing a separate templating language like Helm (though Flux also supports Helm). You’re essentially versioning the build process of your Kubernetes manifests in Git.
One thing most people don’t realize is that Flux doesn’t directly read your kustomization.yaml files to understand the intent. It treats them as instructions for kustomize build. The actual reconciliation happens on the output of kustomize build. This means any Kustomize feature that works locally with kustomize build will work with Flux, provided the Kustomize version Flux uses supports it. You can use bases, patches, generators, and even remote bases if your Kustomize version supports it.
The next concept you’ll likely encounter is managing secrets securely across environments, often involving tools like SOPS integrated into the Flux workflow.