Argo CD — Level by Level›09 · Hands-on lab: Argo CD deploying to a second cluster

Lesson 09 of 9 · Hands-on lab

Hands-on lab: Argo CD deploying to a second cluster

A free, code-first lab that puts this whole course into practice: Argo CD on a tools cluster deploys to a second (target) cluster from a Git repo, through 13 short steps from registering the cluster to ApplicationSets, RBAC, notifications and webhooks.

Practitioner → Advanced

Open the lab on GitHub13 steps · each folder has a short README (goal → run → expect → break it) and the code

Key wordshands-on labArgo CDtwo clustershub and spokeargocd cluster addregistry trustself-healprunerollbackhealthHelmKustomizesync hooksApplicationSetRBACnotificationswebhook

What you'll build

The argocd-gitops-lab is a free, hands-on companion to this course. Argo CD runs on one cluster (the "tools" cluster) and deploys to another (the "target" cluster), from a Git repo and a registry on a third machine:

 git server + registry           Argo CD (tools cluster)            target cluster
 (repo: deploy-demo,  ◄─ polls ──┤ Application hello-web  ── apply ──► API :6443
  image: hello-web)              │                                      │ nodes
        ▲                                                               │
        └────────────────────── image pull (containerd) ────────────────┘

Two repos, on purpose: the app repo holds code and CI builds the image (that's the companion gitea-action-lab, step 05); the deploy repo holds only the desired state that Argo CD applies, and needs no pipeline at all.

A model railway with a control room. The control room (Argo CD) has the timetable (Git) and remote control of a layout in the next room (the target cluster). Change the timetable, and the trains follow it; push a train off the track by hand, and the control room puts it back.

What you need

  • A tools cluster with Argo CD installed (plain manifests or the Helm chart), and its UI reachable.
  • A target cluster you have a kubeconfig for, reachable from the Argo CD pods.
  • A Git server and registry (the lab uses Gitea for both).
  • The hello-web image, built by the CI lab or any small web image of your own.

Single-node k3s clusters on small VMs are enough for every step.

The 13 steps, mapped to this course

Step Folder You practise Course lesson
00 00-register-cluster CLI login, argocd cluster add, everyday CLI 02 · Installing Argo CD & the first app
01 01-registry-trust Target nodes pulling from your registry (containerd hosts.toml) 02, and Docker & Containers, lesson 09
02 02-first-app Deploy by git push; Synced · Healthy in the UI tree 02
03 03-drift-selfheal-prune-rollback Self-heal, drift detection, prune, rollback with git revert 06 · Sync policies, hooks & waves
04 04-health Synced but Degraded; Synced but Progressing 08 · Troubleshooting
05 05-helm-kustomize Dev/prod overlays and a Helm chart from one repo 04 · Helm & Kustomize
06 06-sync-hooks PreSync migration, waves, PostSync smoke test 06
07 07-appset-folders One folder = one app (Git directory generator) 05 · Multi-cluster management
08 08-appset-repos One repo = one app (SCM-provider generator) 05
09 09-multi-cluster One app on every cluster; then a full four-cluster platform: least-privilege access, projects per team, sync windows, RBAC with a tested permission matrix 05
10 10-rbac-projects AppProject + RBAC: sync only your team's apps 07 · Production patterns
11 11-notifications Messages on sync and on Degraded 07
12 12-webhook-instant-sync Sync on push instead of polling 07

Every folder follows the same pattern: goal → run → expect → break it. The "break it" part is where most of the learning happens.

Highlights worth knowing before you start

  • Register clusters with the CLI. The UI can't add a cluster; argocd cluster add <context> stores a credential for it. The context is the NAME column of kubectl config get-contexts, not the cluster name. The cluster shows Unknown until the first app targets it; that's normal.
  • Nodes pull images themselves. If the registry is plain HTTP, every node's containerd must be told to trust it, or pods sit in ImagePullBackOff. The lasting fix is TLS on the registry.
  • Alert on Health, not Sync. A wrong image tag is perfectly "Synced"; it's Health that turns Degraded.
  • Argo CD renders Helm itself. helm list on the target shows nothing, because Argo CD applies rendered manifests, not Helm releases.
  • Rollback is git revert. A UI rollback needs auto-sync off, and the next sync undoes it.
  • SCM-provider scans are slow by default. New repos are discovered every 30 minutes unless you tune requeueAfterSeconds or trigger a refresh. Changes inside existing apps still sync on the normal poll or webhook.

When something breaks

The lab ships a TROUBLESHOOTING.md built from errors actually hit while writing it: CLI argument mistakes, empty hosts.toml files, ApplicationSets applied before the repo had a commit, SSH clone URLs from an unconfigured Git server, and scanners pointed at a user instead of an organisation. Combine it with lesson 08 of this course.

Run the series end to end

  1. Do the gitea-action-lab first: it builds and pushes the hello-web image tagged with a commit SHA.
  2. Then work through steps 00–12 of argocd-gitops-lab in order.
  3. Finish by changing the image tag in the deploy repo and watching the new version roll out to the target cluster, with a webhook making it near-instant.

Recap

  • One Argo CD on a tools cluster deploys to a target cluster from Git: hub and spoke.
  • 13 short steps cover registration, registry trust, first app, drift and rollback, health, Helm/Kustomize, hooks, ApplicationSets, multi-cluster, RBAC, notifications and webhooks.
  • Each step is goal → run → expect → break it; pair it with the course lesson in the table.
  • Do the CI lab first, then this CD lab, for the full commit-to-cluster loop.

This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.