GitOps plane — Argo CD v3.4.8 bootstrap and app layout¶
Purpose¶
The deployment plane for everything that runs inside the cluster. The
ownership boundary (ADR-0003 split, made operational): Ansible = node
bootstrap only; Argo CD = everything in-cluster after node bootstrap.
There is deliberately no CI kubectl apply pipeline — Git is the
deployment path.
Install and version pin¶
- Argo CD v3.4.8, non-HA plain install, pinned by commit-tagged URL
(
argoproj/argo-cdv3.4.8manifest, upstream SHA-256 recorded indocs/gitops.mdof the infrastructure repo) and vendored bit-identical inkubernetes/gitops/bootstrap/argocd-install-v3.4.8/(namespace file,server.insecure="true"params,install.yaml). - Installed by human from
wetopi-ops01during apply runbook Phase G (2026-08-30), with two recorded apply-time deviations: the org disables deploy keys (repo credential is therefore a read-only HTTPS token in repository Secretargocd/repo-infra-https), and theapplicationsets.argoproj.ioCRD exceeds kubectl's client-side annotation cap and is applied server-side (split manifest). - Edge-terminated TLS:
server.insecure: "true"— the Argo CD server serves plain HTTP; TLS forargo.wetopi.netterminates at the edge Gateway (edge.md). - No HA at bootstrap (single replicas); HA layout is OPEN. Upgrades replace
the pinned directory — never a moving
stableURL.
Project and app layout¶
One AppProject, platform
(kubernetes/gitops/app.project.yaml):
sourceRepos: the private infrastructure repo over HTTPS (token inargocd/repo-infra-https) +quay.io/jetstack/charts(public OCI Helm registry for cert-manager; nothing outside that exact path is admitted).destinations: in-cluster only,namespace: '*'— AppProject destinations support globs but not negation, so the argocd-namespace self-management exclusion is procedural (the Argo control plane is installed only from the pinned manifests by human apply; Applications are reviewed before apply; mechanical enforcement = admission control, which does not exist at bootstrap — OPEN).ResourceQuota/LimitRangekinds are blacklisted.clusterResourceWhitelist: */*(cluster-scoped resources needed at bootstrap).
The layout is a minimal viable app-of-apps:
flowchart TB
subgraph GIT["GitHub (private)"]
R["wetopi-platform/infrastructure<br/>kubernetes/ (desired state)"]
end
subgraph CL["cluster (ops01 kubectl for bootstrap only)"]
RC["AppProject platform"]
ROOT["Application root<br/>path kubernetes/platform/"]
ROOT --> CM["Application cert-manager<br/>→ Helm chart + F3 manifests"]
ROOT --> DS["Application docs-site<br/>→ 6 workload manifests"]
ROOT --> VT["Application vault<br/>→ Infisical manifests (ns vault)"]
OE["Application argo-edge (not anchored)<br/>→ kube-system edge-argo manifests"]
CL2["Application cilium (not anchored)<br/>→ Helm 1.20.1 + edge-node-config"]
end
R -->|"HTTPS + repo Secret argocd/repo-infra-https"| RC
RC --> ROOT
RC -. "bootstrap apply (ops01)" .-> OE & CL2
- Anchored in Git (child Application manifests live in the root app's
synced path
kubernetes/platform/, so they survive cluster state loss via root prune+selfHeal):root,cert-manager,docs-site,vault. Anchored children carry theresources-finalizer.argocd.argoproj.iofinalizer — deleting an anchoring merge cascades foreground (children's workloads are deleted before the Application CR disappears), so a revert never orphans live state. - Not yet anchored (operator-bootstrap path, include-only self-management
contract each):
argo-edge,cilium. - Live app inventory (2026-08-31): 5 applications —
root,argo-edge,cert-manager,docs-site,vault.vaultis Degraded: its two operator-provisioned Secrets (postgres/infra credentials) predate S0 inputs and must exist on-cluster before first sync — expected, tracked by OBJ-VAULT-001. Per-service facts live inservices/.
The broader App-of-Apps vs ApplicationSet vs per-domain split remains OPEN (master architecture plan §9.4); this layout is built to stay evolvable.
Invariants¶
- The only deployment path is Git → Argo CD; ad-hoc
kubectlfrom ops01 is for recovery/surgery and must be reconciled back into Git. - Child Applications never self-manage Application objects (include-only sources; anchored ones are applied only by the root app).
- Secrets never live in Git: operator-provisioned Secrets (
argo-basic-auth,docs-site-basic-auth, the vault credentials, the repo token) exist only on-cluster — Argo with default sync options neither prunes nor replaces them. - argocd-namespace exclusion stays procedural until admission control lands.
- Pinned version: upgrades are reviewed replacements of the pin directory.
Dependencies¶
- Depends on: the cluster + API VIP (rke2-cluster.md), the edge plane for the public WebUI path (edge.md).
- Depends on this: every in-cluster add-on and service (cert-manager → edge TLS; docs-site, vault, argo-edge, cilium).
Verified state (2026-08-31, live from ops01)¶
Argo CD v3.4.8 7/7 pods Running/Ready; 5 Applications in project
platform as listed above; argocd/repo-infra-https present. Dated
observation — re-read argocd app list before relying on it.
Live inventory (verified 2026-09-06, BookStack mirror — T1.6)¶
- v3.4.8 non-HA (sin Postgres — Redis only); WebUI argo.wetopi.net.
- App-of-apps: app
gitops→ platform-gitops@main (apps/*.yaml) conrecurse: true. - 11 apps: argocd, bookstack, cert-manager, docs-site, docs-runtime, gitops, hindsight, litellm, litellm-postgres, observability, vault — todas Synced+Healthy.
- include-glob CONTRACT (Ley 4): añadir/quitar ficheros del include EN EL MISMO PR.
- Repo Secrets:
repo-<name>-https(auto-discovery por label, con url/username/password/project). - Chicken-and-egg:
AppProject.sourceReposdebe aplicarse LIVE antes del root Application que lo adopta. - Ley de flip: la route/objeto que muere sale de Git EN el flip, nunca antes (incidente 09-01: 404 6h).
Repo: platform-gitops.