Why GitOps on a POC Cluster#
Setting up ArgoCD on minikube is not about automating deployments for a local cluster – you could just run kubectl apply. The point is to prove the deployment workflow before production. If your Git repo structure, Helm values, and sync policies work on minikube, they will work on EKS or GKE. If you skip this and bolt on GitOps later, you will spend days restructuring your repo and debugging sync failures under production pressure.
Installing ArgoCD via Helm#
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm upgrade --install argocd argo/argo-cd \
--namespace argocd \
--create-namespace \
--set server.service.type=NodePort \
--set configs.params."server\.insecure"=true \
--wait --timeout 300sSetting server.insecure=true disables TLS on the ArgoCD server, which is fine for minikube where you access it via port-forward. Do not do this in production.
Retrieving the Admin Password#
ArgoCD generates an initial admin password stored in a Kubernetes secret:
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -dAccess the UI:
kubectl port-forward svc/argocd-server -n argocd 8080:80
# Open http://localhost:8080
# Login: admin / <password from above>Install the CLI for programmatic access:
# macOS
brew install argocd
# Login to your local instance
argocd login localhost:8080 --insecure --username admin --password <password>The Repo Structure ArgoCD Expects#
ArgoCD is flexible about repo layout, but the most maintainable pattern separates application manifests from ArgoCD configuration:
my-gitops-repo/
├── apps/ # ArgoCD Application definitions
│ ├── root-app.yaml # The "app of apps"
│ ├── web-api.yaml # Application resource for web-api
│ ├── database.yaml # Application resource for PostgreSQL
│ └── monitoring.yaml # Application resource for monitoring stack
├── manifests/ # Actual Kubernetes manifests
│ ├── web-api/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── ingress.yaml
│ ├── database/
│ │ └── helm-values.yaml
│ └── monitoring/
│ └── helm-values.yaml
└── README.mdThe apps/ directory contains ArgoCD Application custom resources. The manifests/ directory contains what actually gets deployed to Kubernetes. ArgoCD reads from apps/, which points to manifests/.
Connecting a Git Repo#
For a public repo:
argocd repo add https://github.com/yourorg/gitops-repo.gitFor a private repo, use an SSH key or a personal access token:
# SSH
argocd repo add git@github.com:yourorg/gitops-repo.git \
--ssh-private-key-path ~/.ssh/id_ed25519
# HTTPS with token
argocd repo add https://github.com/yourorg/gitops-repo.git \
--username git --password <github-pat>The App-of-Apps Pattern#
Instead of creating each ArgoCD Application manually, define one “root” Application that points to the apps/ directory. ArgoCD reads that directory, finds Application manifests inside it, and creates them automatically.
# apps/root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/yourorg/gitops-repo.git
targetRevision: main
path: apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: trueNow define individual applications:
# apps/web-api.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-api
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/yourorg/gitops-repo.git
targetRevision: main
path: manifests/web-api
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueApply the root app once:
kubectl apply -f apps/root-app.yamlFrom this point, adding a new application means committing a new YAML file to the apps/ directory. ArgoCD picks it up automatically.
How Auto-Sync Works#
When syncPolicy.automated is set, ArgoCD polls the Git repository (default every 3 minutes) and compares the live cluster state against the desired state in Git.
- prune: true – If you delete a manifest from Git, ArgoCD deletes the corresponding resource from the cluster. Without this, orphaned resources accumulate.
- selfHeal: true – If someone manually edits a resource with
kubectl edit, ArgoCD reverts it to match Git. This enforces Git as the single source of truth.
To trigger an immediate sync without waiting for the poll interval:
argocd app sync web-apiWatching for Drift#
The ArgoCD UI shows each application as a card with a sync status:
- Synced (green) – Cluster matches Git.
- OutOfSync (yellow) – Git has changes not yet applied.
- Degraded (red) – Resources exist but are unhealthy (pods crashing, etc.).
From the CLI:
argocd app list
argocd app get web-apiFrom Minikube to Production#
When you move to a production cluster, the ArgoCD setup changes minimally:
- Enable TLS on the ArgoCD server (remove the
server.insecureflag, add a cert). - Add RBAC to restrict who can sync which applications.
- Configure SSO to replace the admin password with your identity provider.
- Point
destination.serverto your production cluster API endpoint instead ofkubernetes.default.svc.
The app-of-apps structure, sync policies, and repo layout remain identical. That is the payoff of setting it up on minikube first.