Lab 2: Deploy with GitRepository + Kustomization
Fresh playground? If you're starting this lab on a new playground, run:
curl -sf https://raw.githubusercontent.com/cloudpirates/flux-workshop/main/scripts/catch-up.sh | bashThis sets up Gitea, Flux, and the workshop repo automatically (~4 min).
Lab 2: Deploy with GitRepository + Kustomization
Duration: 15 minutes Goal: Deploy a sample application using Flux's core reconciliation loop
What You'll Do
- Add application manifests to your Git repo
- Create a Flux Kustomization to deploy them
- Make a change in Git and watch Flux apply it
- Introduce manual drift and see Flux correct it
Step 1: Add the Application Manifests
We'll deploy podinfo, a tiny Go app built specifically for Kubernetes demos.
cd ~/workshop/flux-workshop
# Create the apps directory structure (may already exist)
mkdir -p apps/base apps/staging
Create apps/base/deployment.yaml:
cat > apps/base/deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: podinfo
spec:
replicas: 2
selector:
matchLabels:
app: podinfo
template:
metadata:
labels:
app: podinfo
spec:
containers:
- name: podinfo
image: ghcr.io/stefanprodan/podinfo:6.7.0
ports:
- containerPort: 9898
name: http
resources:
requests:
cpu: 100m
memory: 64Mi
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
httpGet:
path: /readyz
port: http
EOF
Create apps/base/service.yaml:
cat > apps/base/service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
name: podinfo
spec:
type: ClusterIP
selector:
app: podinfo
ports:
- name: http
port: 9898
targetPort: http
EOF
Create apps/base/kustomization.yaml:
cat > apps/base/kustomization.yaml << 'EOF'
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: apps
resources:
- deployment.yaml
- service.yaml
EOF
Step 2: Tell Flux to Deploy These Manifests
Create the namespace and Flux Kustomization in your cluster config:
cat > clusters/staging/apps.yaml << 'EOF'
apiVersion: v1
kind: Namespace
metadata:
name: apps
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps
namespace: flux-system
spec:
interval: 1m
path: ./apps/base
prune: true
sourceRef:
kind: GitRepository
name: flux-system
targetNamespace: apps
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: podinfo
namespace: apps
EOF
Commit and push:
git add -A
git commit -m "Add podinfo app with Flux Kustomization"
git push
Step 3: Watch the Deployment
# Trigger immediate reconciliation (or wait ~1 min for the interval)
flux reconcile source git flux-system
# Watch the Kustomization status
flux get kustomizations -w
Press Ctrl+C once you see the apps Kustomization show Ready True.
# Check the pods
kubectl get pods -n apps
# Verify the service
kubectl port-forward -n apps svc/podinfo 9898:9898 &
curl http://localhost:9898
You should see podinfo running with 2 replicas and a JSON response from the API.
Step 4: Update via Git
Change the replica count in Git:
# Edit the deployment — scale from 2 to 3
sed -i 's/replicas: 2/replicas: 3/' apps/base/deployment.yaml
git add -A
git commit -m "Scale podinfo to 3 replicas"
git push
# Trigger reconciliation
flux reconcile source git flux-system
# Watch pods scale up
kubectl get pods -n apps -w
No kubectl scale, no kubectl apply. Just Git push, Flux applies. Press Ctrl+C once you see 3 pods running.
Step 5: Break It — Drift Detection
Now let's prove drift detection works:
# Manually scale down (bypassing GitOps)
kubectl scale deployment podinfo -n apps --replicas=1
# Verify — only 1 pod
kubectl get pods -n apps
# Wait for reconciliation (or trigger it)
flux reconcile kustomization apps
# Watch Flux restore to 3 replicas
kubectl get pods -n apps -w
Flux detects the drift between desired state (3 replicas in Git) and actual state (1 replica)
and corrects it automatically. Press Ctrl+C once restored.
Key Learning: The Git → Cluster reconciliation loop. Flux watches Git and converges the cluster. Manual changes are ephemeral — Git always wins. This is the core of GitOps.
Checkpoint
If you fell behind:
kubectl apply -f ~/workshop/checkpoints/lab2-complete.yaml
Kill any port-forward before moving on:
kill %1 2>/dev/null || true
- Previous lesson
- Lab 1: Bootstrap Flux
- Next lesson
- Lab 3: Helm Releases with HelmRelease