Skip to content

ArgoCD + Image Updater for GitOps

Date: 2026-03-23 Status: Accepted Context: Choosing a GitOps tool and deployment trigger mechanism for the platform

Decision

Use ArgoCD with ArgoCD Image Updater (polling-based) as the GitOps controller for all deployments.

How it works

graph LR
    push["git push"] --> gha["GitHub Actions<br/>build image"]
    gha --> harbor["Harbor<br/>stores image"]
    harbor --> iu["Image Updater<br/>polls every 1 min"]
    iu --> argocd["ArgoCD<br/>triggers sync"]
    argocd --> k8s["Team namespace<br/>deploys"]

Image Updater watches Harbor for new image tags and automatically updates ArgoCD application annotations, triggering a sync. No webhooks, no per-team configuration.

Rationale

Why ArgoCD?

  • UI for visibility — ArgoCD's web interface makes deployment state visible to admins and coaches without needing kubectl access. You can see at a glance which teams have deployed, what version is running, and whether syncs are healthy.
  • Ecosystem maturity — widely adopted CNCF project with strong community support and documentation.
  • ApplicationSet — enables templated multi-tenant deployments from a single definition.

Why Image Updater with polling?

  • Zero per-team configuration — teams just push to Harbor and deployments happen automatically. No webhooks to set up per student repository.
  • Decoupled from CI — the deployment trigger doesn't depend on GitHub Actions completing a specific step. If an image lands in Harbor (from any source), it gets deployed.
  • Trade-off accepted: polling interval (1 min) means deployments take 1-3 minutes after image push. This is acceptable for an educational context.

Alternatives Considered

Flux

  • ✅ Lightweight, GitOps-native
  • ❌ No built-in UI — coaches would need kubectl or a third-party dashboard
  • Rejected: Lack of UI is a significant gap for our use case

Webhook-based triggers (e.g., Harbor webhook → ArgoCD)

  • ✅ Faster deployment (seconds vs minutes)
  • ❌ Requires webhook configuration per team/project
  • ❌ More fragile (webhook delivery failures, network issues)
  • Rejected: Per-team config overhead doesn't scale with 15+ teams

Jenkins / manual CD

  • ❌ Not GitOps (imperative, not declarative)
  • ❌ Extra infrastructure to maintain
  • Rejected: Counter to our IaC principles

Consequences

Positive

  • Single ArgoCD instance serves all tenants (PRJ2 + SPoHF)
  • Coaches can inspect deployments via UI without platform access
  • Adding a new team requires only an ArgoCD Application manifest — no webhook setup

Negative

  • 1-3 minute delay between image push and deployment (polling interval)
  • Image Updater is an additional component to maintain
  • ArgoCD UI exposes some cluster state (mitigated by RBAC: read-only default policy)