Deploy Your First Application with a GitRepository and Kustomization
Point Flux at manifests in Git using a Kustomization resource and watch it sync.
Flux is configured with Kubernetes resources like everything else in the cluster. Two of them do most of the work: a source such as a GitRepository says where the configuration lives, and a Kustomization says “take the manifests at this path in that source and keep them applied to this cluster”. This guide deploys a small application, then changes Git to see the sync happen. It assumes Flux is bootstrapped against a fleet-infra repository (see the previous guide).
Prepare the manifests
In your fleet-infra clone, add an application folder alongside the clusters folder created by bootstrap:
fleet-infra/
├── clusters/
│ └── dev/
│ ├── flux-system/ # created by bootstrap
│ └── webapp.yaml # the Flux Kustomization (next section)
└── apps/
└── webapp/
├── namespace.yaml
├── deployment.yaml
└── service.yaml
apps/webapp/namespace.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: webapp
apps/webapp/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: webapp
spec:
replicas: 2
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:1.25
ports:
- containerPort: 80
apps/webapp/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: webapp
namespace: webapp
spec:
selector:
app: webapp
ports:
- port: 80
targetPort: 80
Unlike some tools, the manifests here name their namespace explicitly, and the folder includes the Namespace object so Flux creates it. No kustomization.yaml is needed: when a folder doesn’t contain one, Flux builds a list of every YAML file in it.
Write the Flux Kustomization
Bootstrap already created a GitRepository named flux-system that points at this same repository, so you can reuse it. clusters/dev/webapp.yaml:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: webapp
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: flux-system
path: ./apps/webapp
prune: true
wait: true
timeout: 2m
The parts that matter:
sourceRefis where the desired state comes from. Here it is theflux-systemrepository that bootstrap set up.pathis the folder inside the source to apply.intervalis how often Flux re-applies the manifests and corrects drift, even when Git hasn’t changed.prune: truemeans that objects removed from Git are also removed from the cluster. It is off unless you set it.waitandtimeoutmake Flux wait for the applied resources to become ready before reporting success.
You can generate this YAML with the CLI instead of writing it by hand:
flux create kustomization webapp \
--source=GitRepository/flux-system \
--path=./apps/webapp \
--prune=true --wait=true --timeout=2m --interval=10m \
--export > clusters/dev/webapp.yaml
Commit and let Flux pick it up
git add -A
git commit -m "Add webapp"
git push
The flux-system Kustomization already watches ./clusters/dev, so it discovers the new webapp Kustomization on its next run. You never run kubectl apply for the application. To skip the wait, ask Flux to check Git right now:
flux reconcile source git flux-system
flux get kustomizations --watch
Confirm the deployment
The webapp Kustomization appears and moves to Ready with a message naming the applied revision. Check the cluster, and ask Flux to show what it owns:
kubectl get all -n webapp
flux tree kustomization webapp
Change Git and watch it sync
Edit apps/webapp/deployment.yaml, change the image to nginx:1.26, then commit and push. Flux fetches repositories on the GitRepository interval (one minute by default after bootstrap), then applies the change. A new ReplicaSet rolls out. Verify:
flux reconcile kustomization webapp --with-source
kubectl get deploy webapp -n webapp \
-o jsonpath='{.spec.template.spec.containers[0].image}'; echo
That is the whole loop: edit Git, Flux converges the cluster. The next guide covers how to control that behavior.
Using a different repository
You don’t have to keep application manifests in the bootstrap repository. To deploy from another one, create a GitRepository for it and reference that from the Kustomization:
flux create source git webapp-config \
--url=https://github.com/your-org/webapp-config \
--branch=main --interval=1m \
--export > clusters/dev/webapp-source.yaml
For a private repository, add credentials with flux create secret git and reference it with --secret-ref, or use an SSH deploy key. Then set sourceRef.name: webapp-config in the Kustomization.
Popular Guides
-
Push vs Pull: How Flux Delivers to Kubernetes Why pull-based, Git-driven delivery changes how you deploy, secure, and recover clusters. -
Control Sync Behavior: Intervals, Prune, Drift Correction, and Rollback Decide when Flux applies changes, what it deletes, how to pause it, and how to undo a bad deploy. -
Automate Image Updates with Flux Image Automation Let Flux detect new container image tags and commit them back to Git. -
Configure Multi-Cluster with Flux Manage several clusters from one repository, with shared infrastructure and per-cluster differences. -
Flux CD vs Argo CD: Choosing a GitOps Tool Compare architecture, UI, Helm, secrets, tenancy, and image automation to pick the right tool.