Getting Started
Install ArgoCD on kind, bootstrap from a Git repo, deploy an app, watch reconciliation, rollback via git revert
Getting Started
This page sets up ArgoCD on a local cluster, points it at a Git repo, and walks the full loop: push a change, watch ArgoCD sync it, break the cluster, watch ArgoCD repair it, rollback via Git.
Prerequisites
-
A Kubernetes cluster (kind is fine for learning):
kind create cluster --name gitops kubectl cluster-info --context kind-gitops -
kubectl,argocdCLI:brew install argocd # or: curl -sSL https://argo-cd.s3.amazonaws.com/release/argocd-linux-amd64 -o /usr/local/bin/argocd && chmod +x /usr/local/bin/argocd -
A Git repo you can push to (GitHub, GitLab, your own Gitea — anywhere ArgoCD can reach).
Step 1: Install ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Wait for it
kubectl wait --for=condition=available --timeout=300s deployment/argocd-server -n argocdPort-forward the UI:
kubectl port-forward svc/argocd-server -n argocd 8080:443 &Get the initial admin password:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echoLogin at https://localhost:8080 (user: admin) or via CLI:
argocd login localhost:8080 --insecure
# Change the password
argocd account update-passwordStep 2: Prepare a Git Repo
Make a repo (or use an existing one):
my-gitops-config/
└── apps/
└── hello/
├── deployment.yaml
└── service.yamlapps/hello/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
namespace: hello
spec:
replicas: 2
selector: { matchLabels: { app: hello } }
template:
metadata: { labels: { app: hello } }
spec:
containers:
- name: hello
image: nginxdemos/hello:plain-text
ports: [{ containerPort: 80 }]apps/hello/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: hello
namespace: hello
spec:
selector: { app: hello }
ports: [{ port: 80 }]Commit + push.
Step 3: Create the ArgoCD Application
kubectl create namespace hello
argocd app create hello \
--repo https://github.com/youruser/my-gitops-config.git \
--path apps/hello \
--dest-server https://kubernetes.default.svc \
--dest-namespace hello \
--sync-policy automated \
--auto-prune \
--self-healOr, store the Application itself in Git as argocd/applications/hello.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: hello
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/youruser/my-gitops-config.git
path: apps/hello
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: hello
syncPolicy:
automated:
prune: true
selfHeal: trueAnd apply: kubectl apply -f argocd/applications/hello.yaml. The "app-of-apps" pattern bootstraps from this.
Step 4: Watch the Sync
In the UI: refresh, you should see hello as Synced and Healthy. The tree view shows the Deployment, ReplicaSet, Pods, Service.
CLI:
argocd app get hello
argocd app sync hello # manual trigger if neededTest the app:
kubectl port-forward svc/hello -n hello 8000:80 &
curl http://localhost:8000Step 5: Change Something via Git
In apps/hello/deployment.yaml, bump replicas:
spec:
replicas: 5Commit + push. Within 3 minutes (default polling) — or instantly if your repo has a webhook to ArgoCD — you'll see ArgoCD sync. The cluster scales to 5.
kubectl get pods -n helloThis is GitOps. Git changed; cluster followed.
Step 6: Watch Self-Healing
Pretend to be a rogue operator:
kubectl scale deployment hello -n hello --replicas=1For about 60 seconds you have 1 pod. Then ArgoCD detects drift (cluster ≠ Git) and reconciles back to 5. The Git state wins.
Try deleting the service:
kubectl delete svc hello -n helloIt gets recreated. Self-heal is on.
Step 7: Rollback
Push a deliberate bad change (image doesn't exist):
image: nginxdemos/hello:does-not-existCommit + push. ArgoCD syncs; pods crash-loop. Now revert in Git:
git revert HEAD
git pushArgoCD re-syncs to the previous good state. Rollback is just Git history.
CLI alternative if you can't wait for repo polling:
argocd app rollback hello # picks last healthy revisionStep 8: App of Apps
A common pattern is bootstrapping multiple apps from one root Application.
argocd/root.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/youruser/my-gitops-config.git
path: argocd/applications
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: trueAnything you put in argocd/applications/*.yaml (more Applications) becomes a managed app. One kubectl apply -f root.yaml and the entire platform follows.
Equivalent in Flux
Same idea, different style:
# Install
brew install fluxcd/tap/flux
# Bootstrap (writes Flux manifests to your repo)
flux bootstrap github \
--owner=youruser \
--repository=my-gitops-config \
--branch=main \
--path=clusters/gitops-cluster
# Add a Kustomization pointing at apps/hello
flux create kustomization hello \
--source=GitRepository/flux-system \
--path=./apps/hello \
--prune=true \
--interval=1mFlux uses GitRepository, Kustomization, HelmRelease CRDs instead of ArgoCD's Application. The discipline is identical.
Cleanup
kind delete cluster --name gitopsWhat's Next
You have a working GitOps loop. Next:
- Patterns — app-of-apps, ApplicationSets, secrets, multi-cluster
- Best Practices — repo structure, RBAC, DR, scaling