47674969a1
---ci--- project: atelier phase: 1 milestone: v0.3 status: complete requirements: covered: [ATELIER-60, ATELIER-61, ATELIER-62, ATELIER-63, ATELIER-64] partial: [] ---/ci---
176 lines
8.3 KiB
Markdown
176 lines
8.3 KiB
Markdown
# ArgoCD — Derived Rules
|
||
|
||
> Derives from `domains/gitops-operators/first-principles.md`.
|
||
> Applies P1–P10 to ArgoCD specifically. For the ArgoCD-vs-Flux
|
||
> decision, see the decision matrix at the end of this doc and in
|
||
> `flux.md`.
|
||
|
||
## What ArgoCD Is (P1 Git is the Source of Truth, P3 Pull, Don't Push)
|
||
|
||
- ArgoCD is a pull-based GitOps controller for Kubernetes. It runs
|
||
inside the target cluster, pulls desired state from git, and
|
||
reconciles the cluster to match. CI never holds `kubectl` rights
|
||
against the cluster (P3).
|
||
- An Application is a declarative binding of "this git path" to
|
||
"this cluster destination." The Application CRD is the unit of
|
||
reconciliation. The cluster is a derivative of git, never the
|
||
authority (P1).
|
||
- ArgoCD supports Helm charts, Kustomize overlays, ksonnet, and raw
|
||
manifests as source formats — see `domains/kubernetes/helm.md`
|
||
and `domains/kubernetes/kustomize.md`.
|
||
|
||
## Application CRD (P2 Declarative Over Imperative, P4 Continuous Reconciliation)
|
||
|
||
- An Application declares `source` (repo, path, revision, chart),
|
||
`destination` (server, namespace), and `syncPolicy`. The
|
||
reconciler loops continuously; drift is corrected automatically,
|
||
not on-demand (P4).
|
||
|
||
```yaml
|
||
apiVersion: argoproj.io/v1alpha1
|
||
kind: Application
|
||
metadata:
|
||
name: payments-api
|
||
namespace: argocd
|
||
spec:
|
||
source:
|
||
repoURL: https://git.example.com/platform/payments
|
||
targetRevision: 1.2.3
|
||
path: manifests/prod
|
||
destination:
|
||
server: https://kubernetes.default.svc
|
||
namespace: payments
|
||
syncPolicy:
|
||
automated:
|
||
prune: true
|
||
selfHeal: true
|
||
syncOptions:
|
||
- CreateNamespace=false
|
||
```
|
||
|
||
- `automated.prune: true` deletes resources removed from git.
|
||
`selfHeal: true` corrects hand-edited drift back to git (P8).
|
||
Disable both for workloads that need manual approval gates.
|
||
|
||
## App-of-Apps (P6 Operators Encode Domain Knowledge, C6 Composability)
|
||
|
||
- The App-of-Apps pattern: one root Application points at a git
|
||
directory of child Application manifests. The root app reconciles
|
||
the children; the children reconcile the workloads. This is the
|
||
ArgoCD expression of composition — a fleet of apps as a tree of
|
||
Applications.
|
||
- Use App-of-Apps for cluster bootstrapping (one repo, many
|
||
clusters, many apps). Do not use it as a substitute for a package
|
||
manager; if you are templating hundreds of near-identical
|
||
Applications, use a generator (ApplicationSet) instead.
|
||
|
||
## Sync Waves and Hooks (P4 Continuous Reconciliation, P7 Reversibility)
|
||
|
||
- Sync waves order resources within a sync: `PreSync` → `Sync` →
|
||
`PostSync`. Use waves to run a job before a Deployment, or a
|
||
migration before the app that depends on it.
|
||
- Sync hooks (`PreSync`, `Sync`, `PostSync`, `SyncFail`) are
|
||
Resources annotated to execute at a wave boundary. A `SyncFail`
|
||
hook runs on sync failure — the abort path (P7).
|
||
- Wave ordering is a correctness mechanism, not a performance one.
|
||
Mis-ordered waves (e.g., app starts before its migration job)
|
||
are a correctness bug.
|
||
|
||
## Health and Status (P9 Failure is Observable and Surfaced)
|
||
|
||
- ArgoCD assesses every resource's health (`Healthy`, `Progressing`,
|
||
`Degraded`, `Missing`, `Suspended`) and surfaces the aggregate as
|
||
Application status. Sync status (`Synced`, `OutOfSync`) reports
|
||
drift against git.
|
||
- Health checks are pluggable via Lua scripts for custom CRDs. An
|
||
Operator-managed CRD without a health check reads as `Progressing`
|
||
forever — write one (see `operators.md`).
|
||
- Out-of-sync or degraded status must emit a notification (Slack,
|
||
PagerDuty, webhook). Silent drift is the bug (P9). Wire status to
|
||
`domains/observability/metrics.md`.
|
||
|
||
## Diff and Drift (P8 Reconcile, Don't Mutate by Hand, P4)
|
||
|
||
- `argocd app diff` shows the diff between git and live cluster.
|
||
A non-empty diff on a synced app is hand-edit drift — the
|
||
recovery is `selfHeal`, not a manual `kubectl apply` (P8).
|
||
- Drift detection runs continuously (P4). The gap between "git
|
||
changed" and "cluster matches git" is observable, not assumed.
|
||
|
||
## RBAC and SSO (P10 Least Privilege Reconciliation)
|
||
|
||
- ArgoCD's own RBAC governs who can view, sync, and admin
|
||
Applications. Bind to SSO (OIDC, SAML) for human identity; bind
|
||
the controller's service account to a Role scoped to the
|
||
namespaces it reconciles.
|
||
- The controller's credentials must not be `cluster-admin` (P10).
|
||
Use namespace-scoped Roles via `ApplicationSet` namespaces or
|
||
cluster-wide AppProject restrictions. See
|
||
`domains/kubernetes/rbac.md` and `domains/security/authorization.md`.
|
||
- AppProjects bound the blast radius of what an Application can
|
||
deploy (allowed repos, destinations, roles). One AppProject per
|
||
team or environment; the default project is for nothing in
|
||
production.
|
||
|
||
## Multi-Cluster (P4 Locality, P10)
|
||
|
||
- ArgoCD registers external clusters by secret. The controller
|
||
pulls from git and pushes to the registered cluster's API server.
|
||
The "pull, don't push" boundary (P3) is between the target
|
||
cluster's reconciler and CI — the controller-to-apiserver hop is
|
||
internal to the platform.
|
||
- Scope each registered cluster's credentials to the namespaces
|
||
ArgoCD manages there. Do not register a cluster with cluster-admin
|
||
and call it done (P10).
|
||
|
||
## Sync Windows (P5 Reversibility, P7)
|
||
|
||
- Sync windows restrict when automated sync runs (e.g., no syncs
|
||
during business hours, or syncs only in a maintenance window).
|
||
They are a reversibility mechanism: a bad commit lands in git,
|
||
but the sync window holds it until review.
|
||
- Sync windows do not replace health monitoring (P9). A degraded
|
||
app inside a window is still an incident.
|
||
|
||
## Secrets (P10, cross-link security/secrets)
|
||
|
||
- Do not store raw Secrets in the GitOps repo. Use a sealed-secret
|
||
controller (Bitnami Sealed Secrets, SOPS, External Secrets
|
||
Operator) so the git store holds encrypted material only. See
|
||
`domains/security/secrets.md` for the general secret-hygiene
|
||
principles.
|
||
|
||
## ArgoCD vs Flux — Decision Matrix (IDEATE-21, D-039)
|
||
|
||
| Axis | ArgoCD | Flux |
|
||
|------|--------|------|
|
||
| Architecture | Monolithic controller + Application CRD | Composable GitOps Toolkit controllers (source, kustomize, helm, notification) |
|
||
| Reconciliation unit | Application (one CRD per app) | Kustomization / HelmRelease (one per deploy unit) |
|
||
| UI | Web UI + CLI (full dashboard, tree view, diff viewer) | CLI-first; UI via Weave GitOps or FluxUI (add-on) |
|
||
| Sync model | Periodic poll or webhook; sync waves + hooks | Poll + webhook; runs continuously, no explicit sync waves |
|
||
| Multi-cluster | One ArgoCD manages many clusters (hub-and-spoke) | One Flux per cluster (per-cluster autonomy) |
|
||
| Templating in repo | Helm, Kustomize, ksonnet, raw manifests, Jsonnet | Helm, Kustomize, raw manifests |
|
||
| RBAC | Built-in RBAC + SSO + AppProjects | Kubernetes RBAC (no built-in RBAC layer) |
|
||
| Progressive delivery | Argo Rollouts (sister project, tight integration) | Flagger (sister project, tight integration) |
|
||
| Best for | Teams wanting a UI, multi-cluster from one pane, App-of-Apps bootstrapping | Teams wanting composable controllers, per-cluster autonomy, minimal footprint |
|
||
| Watch out for | Monolithic controller scaling, UI as ops crutch, AppProject sprawl | No native UI, steeper learning curve, manual multi-cluster orchestration |
|
||
|
||
- Use ArgoCD when you want a UI, central multi-cluster management,
|
||
and sync-wave ordering. Use Flux when you want composable
|
||
controllers, per-cluster autonomy, and a minimal footprint.
|
||
- Both are CNCF graduated and both implement the OpenGitOps
|
||
principles. The choice is architectural fit, not correctness. See
|
||
`flux.md` for the Flux-side perspective.
|
||
|
||
## What Violates ArgoCD Discipline
|
||
|
||
| Violation | Principle |
|
||
|-----------|-----------|
|
||
| CI pipeline with `kubectl` rights pushing to the cluster | P3 Pull, Don't Push |
|
||
| `argocd app set` used as the steady state instead of git | P1 Git is the Source of Truth |
|
||
| `selfHeal: false` on a prod app with no manual gate | P8 Reconcile, Don't Mutate by Hand |
|
||
| Controller ServiceAccount bound to `cluster-admin` | P10 Least Privilege Reconciliation |
|
||
| Sync failure with no notification wired | P9 Failure is Observable and Surfaced |
|
||
| AppProject with no destination restrictions in prod | P10 Least Privilege Reconciliation |
|
||
| Raw Secret in the GitOps repo | P10, `domains/security/secrets.md` |
|
||
| Manual `kubectl edit` on an ArgoCD-managed resource | P8 Reconcile, Don't Mutate by Hand | |