Lab Guide: GitOps with Helm
Three hands-on exercises covering ArgoCD Application setup, FluxCD HelmRelease configuration, and drift detection.
Prerequisites
A running Kubernetes cluster (minikube, kind, or cloud). kubectl, helm, and git installed. For Exercise 1-2, you need ArgoCD or FluxCD installed (instructions below). A GitHub/GitLab repo you can push to.
Exercise 1: Deploy a Helm Chart with ArgoCD
Create an ArgoCD Application that deploys an nginx chart from an OCI registry with environment-specific values.
Step 1 — Install ArgoCD (if not already running)
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Wait for pods to be ready
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=120s
# Get the admin password
argocd admin initial-password -n argocd
Step 2 — Create a GitOps repository structure
Create a new Git repository (or a directory in an existing one) with this layout:
mkdir -p gitops-lab/apps/nginx
cd gitops-lab
Step 3 — Create the values file
Create apps/nginx/values-dev.yaml:
# apps/nginx/values-dev.yaml
replicaCount: 2
service:
type: ClusterIP
port: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
Step 4 — Create the ArgoCD Application manifest
Create apps/nginx/application.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx-dev
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.bitnami.com/bitnami
chart: nginx
targetRevision: 15.*
helm:
releaseName: nginx-dev
valueFiles:
- $values/apps/nginx/values-dev.yaml
# Reference to your GitOps repo for values files
sources:
- repoURL: https://charts.bitnami.com/bitnami
chart: nginx
targetRevision: 15.*
helm:
releaseName: nginx-dev
valueFiles:
- $values/apps/nginx/values-dev.yaml
- repoURL: https://github.com/YOUR_USER/gitops-lab.git
targetRevision: main
ref: values
destination:
server: https://kubernetes.default.svc
namespace: nginx-dev
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Note
Replace YOUR_USER with your GitHub username. The $values ref allows ArgoCD to pull values files from a separate Git repo while using a Helm chart from a chart repository.
Step 5 — Apply and verify
# Push to your Git repo first
git add . && git commit -m "add nginx ArgoCD application" && git push
# Apply the Application
kubectl apply -f apps/nginx/application.yaml
# Check sync status
argocd app get nginx-dev
# Or via kubectl:
kubectl get application nginx-dev -n argocd -o jsonpath='{.status.sync.status}'
✓ Check: The Application shows Synced and Healthy. Two nginx pods are running in the nginx-dev namespace.
Exercise 2: Deploy with FluxCD HelmRelease
Set up a FluxCD HelmRepository and HelmRelease to deploy Redis with values from a ConfigMap.
Step 1 — Install Flux (if not already running)
# Install the Flux CLI
brew install fluxcd/tap/flux # macOS
# or: curl -s https://fluxcd.io/install.sh | sudo bash
# Bootstrap Flux into your cluster
flux bootstrap github \
--owner=YOUR_USER \
--repository=gitops-lab \
--branch=main \
--path=clusters/dev \
--personal
Step 2 — Create the HelmRepository source
Create clusters/dev/sources/bitnami.yaml:
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: bitnami
namespace: flux-system
spec:
type: oci
url: oci://registry-1.docker.io/bitnamicharts
interval: 10m
Step 3 — Create a ConfigMap for values
Create clusters/dev/redis/values-configmap.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-values
namespace: caching
data:
values.yaml: |
architecture: replication
replica:
replicaCount: 2
auth:
enabled: true
metrics:
enabled: true
serviceMonitor:
enabled: false
Step 4 — Create the HelmRelease
Create clusters/dev/redis/helmrelease.yaml:
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: redis
namespace: caching
spec:
interval: 30m
chart:
spec:
chart: redis
version: "18.x"
sourceRef:
kind: HelmRepository
name: bitnami
namespace: flux-system
interval: 10m
install:
createNamespace: true
valuesFrom:
- kind: ConfigMap
name: redis-values
valuesKey: values.yaml
values:
commonLabels:
managed-by: flux
Step 5 — Commit, push, and verify
git add . && git commit -m "add redis HelmRelease" && git push
# Force Flux to reconcile immediately
flux reconcile source git flux-system
# Check HelmRelease status
flux get helmrelease -n caching
kubectl get pods -n caching
✓ Check: flux get helmrelease -n caching shows Ready: True. Redis master and replica pods are running.
Exercise 3: Drift Detection and Self-Healing
Simulate manual cluster changes and observe how GitOps agents detect and correct drift.
Step 1 — Introduce drift manually
Pick whichever tool you set up in Exercise 1 or 2, then make a direct change:
# Scale the deployment manually (bypassing Git)
kubectl scale deployment nginx-dev --replicas=5 -n nginx-dev
# Or for the Redis exercise:
kubectl scale statefulset redis-master --replicas=0 -n caching
Step 2 — Observe drift detection
ArgoCD:
# Check if ArgoCD detects the drift
argocd app get nginx-dev
# Look for "OutOfSync" status
# With selfHeal enabled, watch it revert:
kubectl get pods -n nginx-dev -w
FluxCD:
# Check the HelmRelease status
flux get helmrelease redis -n caching
# Watch the reconciliation revert the change
kubectl get pods -n caching -w
Step 3 — Perform a GitOps rollback
Make a change via Git (e.g., update the replica count in your values file), push, wait for sync, then roll back:
# Edit values-dev.yaml: change replicaCount to 4
git add . && git commit -m "scale to 4 replicas" && git push
# Wait for sync (verify 4 pods running)
# Now rollback using git revert
git revert HEAD --no-edit
git push
# Watch the agent revert to the original replica count
kubectl get pods -n nginx-dev -w
Step 4 — Document your observations
Answer these questions:
- How long did it take for the drift to be detected and corrected?
- What status did the Application/HelmRelease show during the drift?
- How does the
git revertrollback compare to runninghelm rollbackdirectly?
✓ Check: You observed drift detection and automatic correction. You successfully performed a rollback via git revert and the cluster converged to the reverted state.
Cleanup
# Remove ArgoCD application
argocd app delete nginx-dev --cascade
# Remove Flux resources
flux delete helmrelease redis -n caching
flux delete source helm bitnami
# Or remove everything
kubectl delete namespace argocd nginx-dev caching