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-configrepo holds the manifests, the Applicationcheckout-devexists in Argo CD, and the demo app (podinfo) runs in thecheckout-devnamespace 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
argocdnamespace:source(repo, revision, path),destination(cluster, namespace),project, and an optional sync policy. - Sync status
- Does live state equal Git?
Synced,OutOfSync, orUnknownwhen 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 see | It means | First thing to check |
|---|---|---|
OutOfSync + Missing | In Git, not in the cluster yet | Sync it |
Synced + Progressing | Applied, pods still starting | Wait, then the resource tree |
Synced + Degraded | Applied, but not working | Pod events and logs |
Unknown + ComparisonError | Argo CD cannot render or read the source | The Application conditions |
Files to know
Open them in your editor or on GitHub; the bullets say what to look at.
checkout-config/manifests/deployment.yaml(reference): team-checkout's first manifests: plain YAML, the simplest source type.docs/debugging.md(reference): The commands you will use every day. Skim the first block.- Inspect an Application from the CLI L6–11
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
Unknownwith aComparisonErrorcondition ("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
- An Application is
SyncedandDegraded. 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
- 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
- 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
- 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.
- 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).
- 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.