Traditional workflow (imperative) ──────────────────────────────────────────────── Developer → kubectl apply -f manifests/ → Cluster ↑ manual, error-prone, no audit trail ↑ cluster can drift from what's in Git ↑ no rollback without knowing previous state GitOps workflow (declarative) ──────────────────────────────────────────────── Developer → git push → GitHub repo ↓ ArgoCD watches repo (polls every 3 min or webhook) ↓ Detects diff between Git ↔ Cluster ↓ Auto-syncs cluster to match Git ↓ Cluster always = what's in Git
The key insight: Git becomes the only place you make changes. ArgoCD's job is to
make the cluster look exactly like Git — always. If someone manually changes something
in the cluster, ArgoCD reverts it (selfHeal: true).
# roles/argocd/tasks/main.yml # 1. Create namespace - name: Create argocd namespace command: kubectl create namespace argocd # 2. Install all ArgoCD components via official manifest - name: Install ArgoCD command: > kubectl apply --server-side --force-conflicts -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.13.3/manifests/install.yaml
install.yaml creates
everything in one apply: the namespace, RBAC rules, CRDs, and all five components
(redis, repo-server, application-controller, dex-server, argocd-server).
group_vars/all.yml as
argocd_version. Changing it there updates the install URL in one place.
# roles/argocd/files/argocd-insecure-cm.yaml apiVersion: v1 kind: ConfigMap metadata: name: argocd-cmd-params-cm namespace: argocd data: server.insecure: "true" # run HTTP instead of HTTPS
By default, argocd-server terminates its own TLS and serves HTTPS.
This creates a problem when placed behind an HTTP NGINX Ingress — NGINX tries to
talk HTTP to the backend, but the backend insists on HTTPS, causing a connection error.
kubectl rollout restart deployment/argocd-server and
waits for it to be Ready again before proceeding.
# roles/argocd/files/argocd-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: argocd-ingress namespace: argocd annotations: # tell NGINX the backend speaks HTTP (not HTTPS) nginx.ingress.kubernetes.io/backend-protocol: "HTTP" spec: ingressClassName: nginx rules: - host: argocd.lab.local http: paths: - path: / pathType: Prefix backend: service: name: argocd-server port: number: 80
192.168.56.200
in your Windows hosts file. All requests with this Host header are routed to
the argocd-server service on port 80.
# roles/online-boutique/files/argocd-app.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: online-boutique namespace: argocd spec: project: default source: repoURL: https://github.com/GoogleCloudPlatform/microservices-demo targetRevision: HEAD path: release directory: include: "kubernetes-manifests.yaml" # skip istio-manifests.yaml destination: server: https://kubernetes.default.svc namespace: online-boutique syncPolicy: automated: prune: true # delete resources removed from Git selfHeal: true # revert manual cluster changes syncOptions: - CreateNamespace=true
The Application is ArgoCD's core CRD. It defines the link between
a Git source and a cluster destination — ArgoCD continuously reconciles the two.
release/ folder at some tags includes Istio CRDs we don't have.
HEAD ensures current k8s API compatibility.
release/ folder contains both kubernetes-manifests.yaml
and istio-manifests.yaml. Without this filter, ArgoCD tries to apply
Istio resources (VirtualService, ServiceEntry, Gateway) that require Istio CRDs
which aren't installed — causing a SyncFailed error.
online-boutique namespace automatically before applying resources.
Without this, the sync fails if the namespace doesn't exist.
# All ArgoCD pods Running? kubectl get pods -n argocd # ArgoCD app sync status kubectl get application online-boutique -n argocd # Expected: SYNC STATUS=Synced HEALTH STATUS=Healthy # Get initial admin password (only exists before first login change) kubectl -n argocd get secret argocd-initial-admin-secret \ -o jsonpath="{.data.password}" | base64 -d # Browser access # URL: http://argocd.lab.local # Username: admin # Password: (output from above command)
The ArgoCD UI at http://argocd.lab.local shows every Application,
its sync status, health of each resource, and full deployment history.
The initial admin password is stored in a Kubernetes secret — it's auto-generated
and should be changed after first login.
online-boutique app
to see a live graph of all 11 microservices, their health status, and resource tree.
Any sync errors appear here with full error messages — much easier to debug than
running kubectl describe for each resource.