The first real hands-on practice: preparing the manifest repository, creating an Application through the UI wizard and CLI, declaring the Application as YAML, then performing the first sync and verifying it in the cluster.

This is the moment you've been waiting for since episode 0: creating your first Application. All the earlier material — GitOps, ArgoCD architecture, manifests, installation, UI and CLI — now comes together in a single hands-on flow. After this episode, you'll see GitOps "magic" for yourself: push to Git, and the cluster follows.
We'll do three things in sequence: prepare a Git repository containing the manifests, create the Application (via the UI, the CLI, then declaratively), and perform the first sync along with verification in Kubernetes.
The structure of the manifest repository for our lab — a single isolated api application:
gitops-lab/
├── manifests/
│ └── api/
│ ├── namespace.yaml
│ ├── deployment.yaml
│ └── service.yaml
└── README.mdExample contents of deployment.yaml (plain manifest, no templating):
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 2
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: ghcr.io/arman/api:v1.0.0
ports:
- containerPort: 8080Commit and push all files to the main branch:
git add manifests/
git commit -m "feat: add api application manifests"
git push origin mainImportant
Core principle: manifests may only change through Git. We established this in episode 1 — now it starts being practiced. Never modify a Deployment in the cluster manually once ArgoCD manages it.
Open the UI → click New Application. Fill in the wizard:
Application Name: api; Project: default; Sync Policy: choose Manual for now so we can control the first sync.Repository URL: your Git URL; Path: manifests/api; Branch: main.Cluster URL: https://kubernetes.default.svc (in-cluster); Namespace: production.Notice: its status is immediately OutOfSync — because the definition in Git has never been applied to the cluster.
The same thing can be done from the CLI with a single command:
argocd app create api \
--repo https://github.com/arman/gitops-lab.git \
--path manifests/api \
--dest-server https://kubernetes.default.svc \
--dest-namespace productionIf you already created it via the UI, the command above will fail with already exists — try another application name, e.g. api-via-cli.
This is the approach that best fits the GitOps spirit: the Application itself is written as YAML. Save it as application.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/arman/gitops-lab.git
path: manifests/api
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated: {}Apply it to the cluster, and ArgoCD automatically creates the Application:
kubectl apply -f application.yaml
argocd app listTip
Writing the Application as YAML is the foundation of the App of Apps pattern: store this Application in the Git repository, and let ArgoCD manage itself. This is covered in more depth in later episodes.
Run the first synchronization:
argocd app sync api
argocd app get apiWatch the output of argocd app get api: Sync Status changes from OutOfSync to Synced, and Health Status becomes Healthy.
Don't just take the dashboard's word for it — prove it in the cluster:
kubectl get all -n production
kubectl get deployment api -n production -o wideWarning
If the status stays OutOfSync or Degraded, check three things in this order: (1) argocd app get api for the error message, (2) the Events of the resources in the UI, (3) the application pod logs. Most first-sync problems come from a wrong path in Source or a wrong namespace in Destination.
This is the final and most important test. Change replicas in deployment.yaml to 4, commit, and push:
git commit -am "chore: scale api to 4 replicas"
git push origin main
argocd app sync api
kubectl get pods -n productionArgoCD detects OutOfSync, you approve the sync, and the cluster follows Git. That's the loop you'll enjoy forever.
Your first Application is now alive:
OutOfSync → Synced and Healthy.kubectl before trusting the dashboard.Everything is still manual — you press the sync button every time. In episode 7 we'll automate this: sync strategies and policies, auto-sync with prune, self-healing, sync windows, sync options, sync phases and waves, and health assessment. See you there!