GitOps Basics
This page is a hands-on intro to GitOps: the repository layout, the minimal manifests, and the first Argo CD and Flux objects you need to make a cluster reconcile itself from Git.
Search across all documentation pages
This page is a hands-on intro to GitOps: the repository layout, the minimal manifests, and the first Argo CD and Flux objects you need to make a cluster reconcile itself from Git.
kubectl access (containerd is the node runtime via CRI).kubectl) and optionally Helm 3.Quick install of the two agents:
# Argo CD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Flux (CLI, then bootstrap)
brew install fluxcd/tap/flux
flux installGitOps needs a declarative target. Start with a plain Deployment and Service committed to Git.
# apps/web/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels: { app: web }
template:
metadata:
labels: { app: web }
spec:
containers:
- name: web
image: registry.example.com/web@sha256:abc123
ports:
- containerPort: 8080@sha256:) makes the deployed version reproducible.Kustomize groups manifests and lets you overlay per environment without templating.
# apps/web/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yamlkubectl apply -k apps/web renders and applies locally for testing.kustomization.yaml and render it automatically.overlays/prod can patch replicas or image tags per environment.An Application tells Argo CD which repo path maps to which cluster namespace.
# argocd/web-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/acme/manifests.git
targetRevision: main
path: apps/web
destination:
server: https://kubernetes.default.svc
namespace: web
syncPolicy:
automated:
prune: true
selfHeal: truesource points at the repo, branch, and path holding the manifests.destination is the cluster and namespace to reconcile.automated with selfHeal reverts manual drift; prune deletes removed resources.Flux splits "where is the source" from "what to apply" into two objects.
# flux/web.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: manifests
namespace: flux-system
spec:
interval: 1m
url: https://github.com/acme/manifests.git
ref:
branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: web
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: manifests
path: ./apps/web
prune: trueGitRepository fetches the repo every interval.Kustomization renders path and applies it with pruning.prune: true removes objects when they disappear from Git.You never edit the live cluster. You change Git and let the agent apply it.
# bump the image, commit, push - the agent does the rest
git commit -am "web: deploy sha256:def456"
git push origin mainBoth tools expose whether the cluster matches Git.
argocd app get web # Synced / OutOfSync + health
flux get kustomizations # Ready, last applied revisionSynced means live state equals the desired state in Git.OutOfSync means a diff exists, from either a new commit or drift.Rollback is a Git operation, not a cluster surgery.
git revert <bad-commit>
git push origin mainSecrets cannot sit in plaintext Git, so encrypt them before committing.
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
git add sealed-secret.yamlkubeseal encrypts with a public key; only the in-cluster controller can decrypt.SealedSecret is safe to commit and reconcile like any other manifest.CRDs must exist before the resources that use them.
metadata:
annotations:
argocd.argoproj.io/sync-wave: "-1"dependsOn between Kustomizations.Image automation bumps the manifest when a new tag is pushed.
# Flux image policy: track semver in the registry
spec:
policy:
semver:
range: ">=1.0.0"ImageUpdateAutomation.Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026