Free lesson · GenAI Platform Engineering
Install ArgoCD and deploy first application
You will install ArgoCD on GKE and deploy a FastAPI AI service via GitOps. Install ArgoCD using kubectl apply from the official manifests into the argocd namespace. Access the ArgoCD UI via port-forward and log in with the auto-generated admin password. Create an Application resource that points to a Git repository containing K8s manifests for an AI inference service. Configure the Application with source (repo URL, path, targetRevision: main) and destination (GKE cluster, namespace). Sync the application and verify the pods, service, and ingress are deployed on GKE. Make a change to the Git manifests and watch ArgoCD detect and sync the update.
Course: DevOps Foundations for GenAI Engineers · Chapter 4 · ArgoCD & GitOps
Free to read — no subscription required.
Introduction
When you ship AI inference services to GKE by running kubectl apply from a laptop or a CI job, the cluster's live state silently drifts from anything you can reproduce. A teammate edits a Deployment in place to bump a temperature setting, a hotfix never lands in Git, and on the next rollout the model serves different parameters than the manifests claim — and no one can tell. The consequence is a Friday outage you can't roll back because there is no single source of truth to roll back to.
ArgoCD fixes this by running inside the cluster, pulling manifests from Git, and continuously reconciling the cluster against them. By the end of this lesson you will be able to install ArgoCD into a dedicated namespace on GKE, declare an Application that points at a Git path, and trigger the first sync that brings an AI inference workload online from version control.
Key Terminology
- GitOps — an operating model where the Git repository is the declarative source of truth for cluster state; relevant here because ArgoCD is the controller that makes GitOps real on GKE.
- ArgoCD Application — a custom resource that binds a Git source (repo + path + revision) to a Kubernetes destination (server + namespace); this is the object you create to deploy your first app.
- Sync — the operation that applies manifests from Git to the destination cluster so the live state matches the desired state defined in version control.
- Reconciliation — the controller loop that keeps the live cluster aligned with Git after the initial sync, surfacing drift in the UI or correcting it automatically when self-heal is enabled.
Concepts
ArgoCD runs inside the cluster
ArgoCD installs as a set of controllers in a dedicated argocd namespace on GKE. The four components you must know are the API server (UI, REST/gRPC, login), the repository server (clones and caches Git), the application controller (watches Application resources and performs syncs), and Redis (caches repo and app state). Because the controllers run in-cluster, they reach the Kubernetes API natively — Git never needs to hold cluster credentials, and the cluster never needs to expose webhook endpoints back to Git. This pull-based topology is what makes the model auditable.
The Application resource binds Git to a namespace
An Application CR is the unit of deployment. Its spec.source names the repo URL, the path within the repo, and the target revision (branch, tag, or commit). Its spec.destination names the cluster API endpoint and the namespace where resources should exist. For an AI inference service that path typically contains a Deployment, a Service, and a ConfigMap carrying provider endpoints, temperature, and token limits. Once the Application exists, the app controller takes over: it computes a diff between Git and the cluster, and the first argocd app sync applies the manifests (see Code Walkthrough).
Sync, health, and reconciliation
After the first sync, ArgoCD reports two status fields you watch constantly: sync.status (Synced vs OutOfSync — does the cluster match Git?) and health.status (Healthy, Progressing, Degraded — are the workloads themselves OK?). Manual sync stops there; syncPolicy.automated makes the controller re-apply on every Git commit, selfHeal re-applies on any in-cluster drift, and prune deletes resources removed from Git. Start with manual sync for your first Application so you can see exactly what reconciliation does before you let it run unattended.
Code Walkthrough
This walkthrough demonstrates the three concepts above in order: install the in-cluster controllers, declare an Application pointing at a Git path, and trigger the first sync against an AI inference service.
Code snippetpython
1import subprocess, base64, json, time 2 3ARGOCD_NS = "argocd" 4INSTALL_URL = ( 5 "https://raw.githubusercontent.com/argoproj/" 6 "argo-cd/stable/manifests/install.yaml" 7) 8 9# 1. Install ArgoCD in its own namespace 10if subprocess.run( 11 ["kubectl", "get", "namespace", ARGOCD_NS], 12 capture_output=True, 13).returncode != 0: 14 subprocess.run( 15 ["kubectl", "create", "namespace", ARGOCD_NS], check=True 16 ) 17 18subprocess.run( 19 ["kubectl", "apply", "-n", ARGOCD_NS, "-f", INSTALL_URL], 20 check=True, 21) 22subprocess.run( 23 ["kubectl", "wait", "--for=condition=Ready", "pod", "--all", 24 "-n", ARGOCD_NS, "--timeout=300s"], 25 check=True, 26) 27 28secret = subprocess.run( 29 ["kubectl", "get", "secret", "argocd-initial-admin-secret", 30 "-n", ARGOCD_NS, "-o", "jsonpath={.data.password}"], 31 capture_output=True, text=True, check=True, 32) 33admin_password = base64.b64decode(secret.stdout).decode("utf-8") 34print(f"admin password: {admin_password}") 35 36# 2. Declare an Application that maps Git -> ai-inference namespace 37app = { 38 "apiVersion": "argoproj.io/v1alpha1", 39 "kind": "Application", 40 "metadata": {"name": "ai-inference", "namespace": ARGOCD_NS}, 41 "spec": { 42 "project": "default", 43 "source": { 44 "repoURL": "https://github.com/team/ai-inference-manifests.git", 45 "path": "k8s/inference", 46 "targetRevision": "main", 47 }, 48 "destination": { 49 "server": "https://kubernetes.default.svc", 50 "namespace": "ai-inference", 51 }, 52 }, 53} 54subprocess.run( 55 ["kubectl", "apply", "-f", "-"], 56 input=json.dumps(app), text=True, check=True, 57) 58 59# 3. Trigger the first sync and poll until Synced + Healthy 60subprocess.run( 61 ["kubectl", "-n", ARGOCD_NS, "exec", "deploy/argocd-server", "--", 62 "argocd", "app", "sync", "ai-inference", 63 "--server", "localhost:8080", "--insecure"], 64 check=True, 65) 66 67deadline = time.time() + 180 68while time.time() < deadline: 69 out = subprocess.run( 70 ["kubectl", "-n", ARGOCD_NS, "get", "app", "ai-inference", 71 "-o", "json"], 72 capture_output=True, text=True, check=True, 73 ) 74 status = json.loads(out.stdout).get("status", {}) 75 sync = status.get("sync", {}).get("status", "Unknown") 76 health = status.get("health", {}).get("status", "Unknown") 77 print(f"sync={sync} health={health}") 78 if sync == "Synced" and health == "Healthy": 79 break 80 time.sleep(10)
Step 1 creates the argocd namespace, applies the upstream manifests, waits for every controller pod to reach Ready, and decodes the initial admin password from argocd-initial-admin-secret. Step 2 builds the Application manifest as a dict matching the argoproj.io/v1alpha1 CRD and pipes it through kubectl apply -f -; source points at the Git path and destination names the target namespace. Step 3 issues the first sync by running argocd app sync inside the argocd-server pod (so you don't need the CLI on your laptop), then polls the Application's status.sync and status.health every ten seconds.
You'll know it works when the poll loop prints sync=Synced health=Healthy and kubectl -n ai-inference get pods shows the inference Deployment's pods in Running with all containers ready.
Do's and Don'ts
Do's
- ✓Do install ArgoCD into its own
argocdnamespace — isolation from application workloads keeps controller restarts and RBAC scoped, and the upstream manifests assume that namespace name. - ✓Do start every new Application with manual sync — running the first
argocd app syncby hand lets you read the diff before reconciliation runs unattended on every commit. - ✓Do treat the Git path as the source of truth — never
kubectl edita resource ArgoCD manages; commit the change to Git and let the controller apply it so the audit trail stays intact.
Don'ts
- ✗Don't enable
pruneandselfHealon day one — both are destructive defaults that delete or overwrite live state; turn them on only after you trust the manifests in Git. - ✗Don't hand the initial admin password around — rotate it (or wire SSO) before granting anyone else access; the
argocd-initial-admin-secretis a bootstrap credential, not a long-lived one. - ✗Don't point an Application at a moving branch like
mainfor production — pintargetRevisionto a tag or commit SHA so a stray push can't roll out untested manifests.
This lesson is free to read. Its 3 hands-on labs — real code, in a cloud IDE — are part of the GenAI Platform Engineering subscription.
From · cancel anytime
More free lessons in DevOps Foundations for GenAI Engineers
- Ch 3Build optimized Docker images for AI applications
- Ch 3Automate image builds with GitHub Actions
- Ch 3Sign images with Cosign and enforce Binary Authorization on GKE
- Ch 3Build multi-architecture images for GKE
- Ch 4Install ArgoCD and deploy first applicationYou are here
- Ch 4Compare GitOps controllers: ArgoCD ApplicationSet vs Flux CD
- Ch 4Implement ArgoCD RBAC and multi-tenancy