PlatformEngr® Argo CD course

Module 02 · Foundations · 45 min · You are: Platform and product

Your first Application, from Git

In this module

  • You learn: What an Application is (a source in Git, a destination in the cluster, a project), the two statuses Argo CD reports (sync and health), and the path a commit takes to a running pod.
  • You do: As team-checkout, put the app's Kubernetes manifests in a Git repo. As the platform team, write an Application that points at them, apply it, sync it, then change the repo and watch the change arrive.
  • You end with: The checkout-config repo holds the manifests, the Application checkout-dev exists in Argo CD, and the demo app (podinfo) runs in the checkout-dev namespace with 2 replicas, deployed from Git.

An Application is the unit of everything in Argo CD: a source in Git, a destination in a cluster, and a project that says whether that is allowed. You will see the two statuses Argo CD reports, sync and health, and the loop every change goes through: commit, detect, render, compare, sync, healthy.

Open this module in the interactive course to track progress and switch tracks.

GitOps loop practised: Committed → Reviewed → Detected → Rendered → Compared → Synced → Healthy → Observed

Concepts

Application
A Kubernetes object in the argocd namespace: source (repo, revision, path), destination (cluster, namespace), project, and an optional sync policy.
Sync status
Does live state equal Git? Synced, OutOfSync, or Unknown when Argo CD cannot even render the source.
Health status
Is it working? Healthy, Progressing, Degraded, Missing, Suspended. Independent of sync: Synced and Degraded is common.
Refresh and sync
Refresh: re-read Git and compare (every 60 s here, or on demand). Sync: apply the difference. Without a sync policy, syncing is manual.

Reading an Application

You seeIt meansFirst thing to check
OutOfSync + MissingIn Git, not in the cluster yetSync it
Synced + ProgressingApplied, pods still startingWait, then the resource tree
Synced + DegradedApplied, but not workingPod events and logs
Unknown + ComparisonErrorArgo CD cannot render or read the sourceThe Application conditions

Files to know

Open them in your editor or on GitHub; the bullets say what to look at.

Steps

1. team-checkout: create the environment repo

team-checkout owns the repo that says what runs in each environment. It is not the product's source code. The product here is "checkout", and its running image is the public demo app podinfo (ghcr.io/stefanprodan/podinfo), standing in for an image your CI would build. This repo only says which image to run and how. It is public for now, so Argo CD can read it without a password. It will hold plain Kubernetes manifests: a Deployment (the app) and a Service (its network address).

cd ~/work && gh repo create YOUR_GITHUB_USER/checkout-config --public --clone

Copy the manifests from the reference into the new repo:

cd ~/work/checkout-config && git switch -C main
cp -r ~/work/argocd-gitops/checkout-config/manifests .

Commit and push them, so they are in Git:

git add -A && git commit -qm "checkout: plain manifests" && git push -qu origin main

2. Platform team: declare the Application

An Application is a short file that tells Argo CD three things. Source: which Git repo and folder to read. Destination: which cluster and namespace to put it in. Project: the permission fence (default allows everything for now). Write it yourself, then read it top to bottom to find those three. It has no sync policy, so Argo CD will only report differences and never change the cluster on its own. CreateNamespace=true lets Argo CD create the checkout-dev namespace.

Create ~/work/argocd-platform/apps/checkout-dev.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: checkout-dev
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/YOUR_GITHUB_USER/checkout-config.git
    targetRevision: main
    path: manifests
  destination:
    server: https://kubernetes.default.svc
    namespace: checkout-dev
  syncPolicy:
    syncOptions:
      - CreateNamespace=true

Commit and push the file, so it is saved in Git:

cd ~/work/argocd-platform && git add -A && git commit -qm "Application: checkout-dev" && git push -q

Create the Application in the cluster. Pushing to Git is not enough: nothing is watching the apps/ folder yet. An Application only exists for Argo CD once the object is in the cluster, in the argocd namespace. This command puts it there.

kubectl apply -n argocd -f apps/checkout-dev.yaml

3. Read what Argo CD reports

Argo CD has now compared Git with the cluster. You will read the answer two ways: a status summary, and the exact differences.

The summary. Find two lines. Sync Status: OutOfSync means Git and the cluster differ. Health Status: Missing means the objects do not exist in the cluster yet. Both are right: everything is in Git and nothing is deployed. At the bottom, each resource is listed with its own status.

argocd app get checkout-dev

The differences. This prints what a sync would change. Everything is new here, so the whole Deployment and the whole Service show up as additions. head -30 keeps just the first 30 lines.

argocd app diff checkout-dev | head -30

Now open the app in the UI. The tree on the right is the desired state from Git, greyed out because none of it exists yet.

4. Sync from the UI

A sync applies what Git says to the cluster. In the UI open checkout-dev, click Sync, then Synchronize. Watch the tree fill in and turn green: namespace, Service, Deployment, ReplicaSet, Pod.

Wait until Argo CD reports the app Healthy. The command returns when it is, or after 180 seconds:

argocd app wait checkout-dev --health --timeout 180

See the app itself. Run this in a new terminal and leave it running (it prints Forwarding from ... and waits), then open http://localhost:9898. You should see a podinfo page with the banner checkout (dev).

kubectl -n checkout-dev port-forward svc/checkout 9898:80

5. Follow one commit, with the CLI

team-checkout wants two replicas. Commit, then watch Argo CD detect it, show the diff, and sync on your command. history records which commit is deployed.

cd ~/work/checkout-config && git switch -q main && git pull -q

Change in ~/work/checkout-config/manifests/deployment.yaml

-   replicas: 1
+   replicas: 2
git commit -qam "checkout: 2 replicas" && git push -q

Ask Argo CD to check Git now. Why --refresh? Argo CD already checks Git by itself, about every 3 minutes, so it would notice your commit without any help. --refresh only skips the wait: it means "look at Git right now". It does not deploy anything, and it is optional; you will use it often in this course just to save time. grep keeps two lines: expect Sync Status: OutOfSync, because Git now says 2 replicas and the cluster still has 1.

argocd app get checkout-dev --refresh | grep -E 'Sync Status|Health'

See the difference. Expect one changed line, replicas: 1 in the cluster, 2 in Git:

argocd app diff checkout-dev

Deploy it. You asked for the change, so you sync it:

argocd app sync checkout-dev

Wait until it is healthy (the second pod has started):

argocd app wait checkout-dev --health

The history lists every deploy with the Git commit it came from. Expect two rows: the first sync, and this one:

argocd app history checkout-dev

Break it on purpose: A typo in the Application

The platform team edits the Application and mistypes the path: manifest instead of manifests. It is committed and applied like any other change.

You practise: telling "cannot render" apart from "out of sync", and finding Argo CD's error message in the UI and the CLI.

1. Break it

Change in ~/work/argocd-platform/apps/checkout-dev.yaml

-     path: manifests
+     path: manifest
cd ~/work/argocd-platform && git commit -qam "checkout-dev: tidy" && git push -q

Apply it to the cluster, the same way as the first version:

kubectl apply -n argocd -f apps/checkout-dev.yaml

2. What you see

Open checkout-dev in the UI, or run argocd app get checkout-dev --refresh. Expected: Synced, as before. You get: sync status Unknown and an error condition.

Now run kubectl -n checkout-dev get pods: still running. Argo CD cannot read the source, so it changes nothing.

3. Fix it yourself

Find the full error message, first in the UI and then in the CLI. Then get checkout-dev back to Synced the same way the typo got in.

Hint 1

In the UI, open checkout-dev and look at the status panel at the top: App Conditions holds the message. In the CLI it is the CONDITION line of argocd app get.

Hint 2

The typo is in Git and, because you applied it, in the cluster. Fix the file, commit, apply.

The fix

Change in ~/work/argocd-platform/apps/checkout-dev.yaml

-     path: manifest
+     path: manifests
cd ~/work/argocd-platform && git commit -qam "checkout-dev: fix the path" && git push -q
kubectl apply -n argocd -f apps/checkout-dev.yaml

Expect Synced and Healthy:

argocd app get checkout-dev --refresh | grep -E 'Sync Status|Health'
After you fixed it: the five questions
What failed?
The Application's source could not be rendered: the path does not exist in the repo.
How was it detected?
Argo CD: sync status Unknown with a ComparisonError condition ("app path does not exist"). The running pods were untouched.
Who responds?
Whoever owns the Application manifest: the platform team here.
How is it corrected?
Correct the path in Git and apply it.
How is it prevented?
Review Application changes in pull requests, and validate them in CI before they merge.

Quiz

  1. An Application is Synced and Degraded. What does that mean?
    • Live state matches Git, but the workload is not working
    • Argo CD tried to apply the manifests from Git and failed, so the cluster was left unchanged
    • The sync is still running, and the workload will turn Healthy once Argo CD finishes applying it
  2. Without a sync policy, what happens when you push a change?
    • Argo CD applies it automatically within about a minute, because syncing is on by default
    • Argo CD detects it and shows OutOfSync, but waits for someone to sync
    • Nothing happens at all until you restart the repo-server so it picks up the new commit
  3. Where does an Application object live?
    • In the destination namespace, next to the workloads that it deploys there
    • Only in Git: the cluster never holds the object, and Argo CD reads it straight from the repository
    • In the argocd namespace, on the cluster where Argo CD runs
Answers
  1. Live state matches Git, but the workload is not working Sync and health are independent. Git can declare something broken, and Argo CD will faithfully apply it.
  2. Argo CD detects it and shows OutOfSync, but waits for someone to sync Detection is always on; acting on it is the sync policy's job (module 03).
  3. In the argocd namespace, on the cluster where Argo CD runs Applications are Argo CD's own objects; the destination namespace holds what they deploy.

Field note

I teach manual sync first on purpose. People who start with auto-sync never learn to read a diff, and reading diffs is most of the job when things go wrong.

Report a problem with this module