GitOps means your Kubernetes cluster state is defined in Git, and tools automatically keep the cluster in sync with that definition.
Here’s a simple demo cluster running on Minikube, with a Nginx deployment and service, all managed by GitOps.
First, we need a Git repository. Let’s use a simple git clone of a public repo for this example, but in a real scenario, you’d have your own private repo.
git clone https://github.com/fluxcd/flux2-kustomize-example.git
cd flux2-kustomize-example
Inside this directory, you’ll find Kubernetes manifests. For example, kustomization.yaml defines how to build the manifests, and nginx/deployment.yaml defines the Nginx deployment itself.
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- nginx/deployment.yaml
- nginx/service.yaml
Now, let’s set up Flux, a popular GitOps tool, to watch this repository and apply changes to our Minikube cluster.
First, install Flux CLI:
wget https://github.com/fluxcd/flux2/releases/download/v0.36.0/flux_0.36.0_linux_amd64.tar.gz
tar zxvf flux_0.36.0_linux_amd64.tar.gz
sudo mv flux /usr/local/bin/
Next, initialize Flux in your cluster, pointing it to your Git repository. This command creates a GitRepository custom resource in Kubernetes that tells Flux where to find your manifests.
flux bootstrap git \
--url=https://github.com/fluxcd/flux2-kustomize-example \
--branch=main \
--path=./kustomize \
--personal=true
After running the bootstrap command, Flux will deploy itself into your cluster and start reconciling the state. You can check its status:
kubectl get pods -n flux-system
You should see Flux components running. The source-controller will fetch your Git repository, the kustomize-controller will build your manifests using Kustomize, and the helm-controller (if you were using Helm) will manage Helm releases.
The GitRepository object you created now points to your Git repo. Flux continuously monitors this source.
kubectl get gitrepository flux-kustomize-example -n flux-system -o yaml
This will show you the status of the Git sync, including the latest commit that Flux has applied.
Let’s make a change. Edit the nginx/deployment.yaml to change the Nginx image tag from 1.21.6 to 1.23.0:
# nginx/deployment.yaml (snippet)
spec:
template:
spec:
containers:
- image: nginx:1.23.0 # Changed from 1.21.6
Commit and push this change to your Git repository.
git add nginx/deployment.yaml
git commit -m "Update Nginx version to 1.23.0"
git push origin main
Within a minute or two, Flux will detect the change in Git. The kustomize-controller will rebuild the manifests and apply the updated deployment to your cluster. You can observe this by checking the deployment’s rollout status:
kubectl rollout status deployment/nginx -n default
You’ll see the Nginx pods being updated to the new image.
The core idea is that Git is the single source of truth. Any change to the cluster state must go through a Git commit. This provides a full audit log, the ability to roll back by reverting Git commits, and a declarative way to manage your infrastructure. The controllers in the flux-system namespace are constantly polling or watching the Git repository and applying the desired state.
What most people don’t realize is that Flux doesn’t just apply manifests; it understands the lifecycle of Kubernetes resources. If you delete a resource from Git and commit that change, Flux will delete the corresponding resource from your cluster. This isn’t just about adding things; it’s about maintaining the exact state defined in Git.
The next step is to explore how to manage multiple environments (dev, staging, prod) using different branches or paths within your Git repository and how to integrate Flux with Helm charts.