Lab 25 — GitOps With Argo CD
Learner Orientation
Lab Metadata
| Item | Value |
|---|---|
| Difficulty | Intermediate to advanced |
| Estimated time | 75-120 minutes |
| VMs | 1 |
| Minimum VM RAM | 4096 MB |
| SSH ports | 2240 |
| Internet required | Yes |
Before You Start, You Should Be Able To
- Yeast installed on a Linux/KVM host
- Comfort opening a terminal and changing directories
- Ability to run
yeast up,yeast ssh <instance>, andyeast destroy - Basic comfort with
curl,systemctl, and reading command output - A GitHub account and
ghauthentication when the lab uses GitHub - Comfort creating SSH tunnels from
ACCESS.mdfor browser-based tools - Patience for Kubernetes startup time and enough host RAM for multi-VM labs
Where Commands Run
- Run
yeastcommands from this lab folder on your laptop. - Run Linux service commands only after you SSH into the target VM.
- When a command says "from your laptop", leave the VM shell first with
exit. - When a browser URL uses
localhost, check whether the lab asked you to open an SSH tunnel first. - Run
kubectlcommands inside the Kubernetes control-plane VM unless the lab says otherwise.
Expected Checkpoints
- After
yeast up,yeast statusshould show the expected VM or VMs as running. - After the main setup steps, the service, tool, or workflow introduced by the lab should respond to the verification commands.
- After
bash assets/validate.sh, the script should report all checks passed. - After
yeast destroy, the lab should be cleaned up before you start the next one.
Common Mistakes To Avoid
- Running a VM command on your laptop, or a laptop command inside the VM.
- Closing an SSH tunnel and then wondering why
localhost:<port>stopped working. - Skipping validation because the final page or command "looked fine".
- Forgetting to run
yeast destroybefore moving to the next lab. - Opening Grafana, Prometheus, Jaeger, or Argo CD before the tunnel is running.
- Running Kubernetes commands before all nodes are Ready.
The Story
You have a Kubernetes cluster. You want to deploy an application to it. The naive approach: kubectl apply -f deployment.yaml. Done.
But now: who ran that kubectl apply? When? Was it the same YAML that is in the repo? What if someone edited the live deployment directly? How do you roll back? How do you know what version is running in production right now?
GitOps solves all of this. The principle: Git is the only source of truth for what runs in the cluster. You never apply manifests manually. Instead, a GitOps controller (Argo CD) watches a Git repository and continuously reconciles the cluster to match what is in Git.
Want to deploy a new version? Commit the updated manifest to Git. Want to roll back? Revert the commit. Want to know what is in production? Look at the Git repo. The cluster always matches the repo, automatically, continuously.
Before You Start — Understanding The Concepts
What Is GitOps?
GitOps is an operational model where: 1. The desired state of your system is stored in Git 2. Changes to the desired state are made through Git (commits, PRs) 3. An automated agent continuously reconciles the actual state to match Git 4. Divergence (drift) is detected and corrected automatically
GitOps makes your infrastructure auditable (git log), reviewable (pull requests), and self-healing (automatic reconciliation).
What Is Argo CD?
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. It: - Watches one or more Git repositories - Compares the Kubernetes manifests in Git to the live cluster state - Shows you what is out of sync - Syncs the cluster to match Git (manually or automatically) - Has a web UI and CLI for visibility
What Is Reconciliation?
Reconciliation is the process of comparing desired state (Git) to actual state (cluster) and making changes to close the gap. Argo CD reconciles continuously — if someone manually edits a deployment in the cluster, Argo CD will detect the drift and revert it to what Git says.
What Is An Argo CD Application?
An Argo CD Application is a custom resource that tells Argo CD:
- Which Git repo and path to watch (repoURL, path)
- Which Kubernetes cluster and namespace to deploy to (destination)
- How to sync: manual or automatic
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/you/your-manifests.git
targetRevision: HEAD
path: apps/myapp
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
automated.prune: true — delete resources removed from Git
automated.selfHeal: true — revert manual changes to match Git
What You Are Building
Your Laptop
│ SSH 2240 → gitops-cluster port 22
│ HTTPS 8080 → gitops-cluster port 443 (Argo CD UI)
▼
┌──────────────────────────────────────────────────────┐
│ gitops-cluster VM │
│ │
│ k3s (lightweight Kubernetes) │
│ └── argocd namespace │
│ └── Argo CD controllers + UI │
│ └── default namespace │
│ └── your app (deployed by Argo CD from Git) │
└──────────────────────────────────────────────────────┘
↑ watches
GitHub repo with Kubernetes manifests
Starting The Lab
Step 1 — Install k3s
k3s is a lightweight Kubernetes distribution. It runs as a single binary and is perfect for labs:
Configure kubectl for the ubuntu user:
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown ubuntu:ubuntu ~/.kube/config
sed -i 's/127.0.0.1/127.0.0.1/' ~/.kube/config
# Install kubectl alias
echo 'alias kubectl="k3s kubectl"' >> ~/.bashrc
source ~/.bashrc
kubectl get nodes
Expected:
Step 2 — Install Argo CD
kubectl create namespace argocd
kubectl apply -n argocd -f \
https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Wait for pods to start (takes 1-2 minutes)
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=argocd-server \
-n argocd --timeout=120s
kubectl get pods -n argocd
Step 3 — Access The Argo CD UI
Get the initial admin password:
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
echo # print newline after the password
Inside the gitops-cluster VM, expose the Argo CD UI on the VM loopback interface:
From your laptop, create a tunnel to that VM-local port:
Keep that tunnel terminal open. Then open: https://localhost:8080 (accept the self-signed cert)
Login: admin / (the password from above)
Step 4 — Create A Git Repository With Manifests
You need a GitHub repository that Argo CD will watch. Create one from your laptop:
# From your laptop
gh repo create gitops-lab25 --public --clone
cd gitops-lab25
mkdir -p apps/sample-app
cat > apps/sample-app/deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
labels:
app: sample-app
spec:
replicas: 1
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: app
image: nginx:1.25
ports:
- containerPort: 80
EOF
cat > apps/sample-app/service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
name: sample-app
spec:
selector:
app: sample-app
ports:
- port: 80
targetPort: 80
type: ClusterIP
EOF
git add .
git commit -m "feat: initial sample app manifests"
git push origin main
Step 5 — Create An Argo CD Application
Back on the cluster VM, create the Argo CD Application pointing to your repo:
# In the gitops-cluster VM
cat > /home/ubuntu/argocd-app.yaml << EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sample-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/$(gh api user --jq .login 2>/dev/null || echo "YOUR_USERNAME")/gitops-lab25.git
targetRevision: HEAD
path: apps/sample-app
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
EOF
Edit the file to replace YOUR_USERNAME with your actual GitHub username, then apply:
kubectl apply -f /home/ubuntu/argocd-app.yaml
# Watch Argo CD sync it
kubectl get application -n argocd sample-app
sleep 30
kubectl get application -n argocd sample-app
The application should show Synced and Healthy.
Verify the deployment:
Step 6 — GitOps In Action: Update Via Git
From your laptop, change the deployment:
cd gitops-lab25
sed -i 's/replicas: 1/replicas: 2/' apps/sample-app/deployment.yaml
git add apps/sample-app/deployment.yaml
git commit -m "feat: scale to 2 replicas"
git push origin main
Watch Argo CD detect and apply the change (within the sync interval, usually 3 minutes):
You did not run kubectl apply. You committed to Git. Argo CD reconciled the cluster. This is GitOps.
Step 7 — GitOps Rollback
Something is wrong with the 2-replica deployment. Roll back by reverting the Git commit:
Argo CD detects the new commit (which reverted to 1 replica) and reconciles. The cluster goes back to 1 pod — no kubectl needed.
Step 8 — Self-Healing: Argo CD Corrects Drift
Test selfHeal: true by manually changing the live deployment:
# In the cluster VM
kubectl scale deployment sample-app --replicas=5
kubectl get pods # briefly shows 5 pods
Wait 1-2 minutes. Argo CD detects the drift and reverts it to match Git (1 replica):
The cluster always converges to what Git says. Manual changes are automatically reverted.
Validate Your Work
Clean Up
Quick Recap
In Lab 25 — GitOps With Argo CD, you moved from explanation to a working lab environment, verified the result, and practiced the operational habit that matters most: do the work, prove it works, then clean it up.
Keep this pattern for every lab:
- Build the thing.
- Verify it from the right place.
- Read the logs or status when it fails.
- Run the validation script.
- Destroy the lab before moving on.
What You Learned
- What GitOps is: Git as the source of truth, automated reconciliation to match
- Argo CD: what it is, how it watches a repo and syncs the cluster
- The Argo CD Application resource: repoURL, path, destination, syncPolicy
automated.prune: delete resources removed from Gitautomated.selfHeal: revert manual cluster changes to match Git- k3s: lightweight Kubernetes for labs
- GitOps workflow: change Git → Argo CD detects → cluster updates
- GitOps rollback:
git revert→ cluster rolls back - Drift detection: manual change detected and reverted automatically
What Is Next
Lab 26 — End-To-End Delivery Platform
Every piece is in place. Lab 26 assembles them: proxy, app, database, monitoring, logging — all on one platform, all wired together, deployed with automation. This is the VM-platform capstone before you move to Kubernetes.