From c347416668edde3641fcef9207b03173e89feb6a Mon Sep 17 00:00:00 2001 From: Nikholas Pcenicni <82239765+nikpcenicni@users.noreply.github.com> Date: Thu, 14 May 2026 17:18:41 -0400 Subject: [PATCH] Refactor Argo CD application management by removing the obsolete root-application.yaml and updating the bootstrap-root-application.yaml to include optional add-on Application manifests from clusters/noble/apps. Adjust documentation to clarify the deployment order and resource ownership, ensuring a streamlined GitOps process with Ansible and Argo CD. --- ansible/README.md | 6 ++-- ansible/inventory/group_vars/all.yml | 4 +-- ansible/roles/noble_argocd/defaults/main.yml | 3 -- .../tasks/applications_post_platform.yml | 12 ------- .../roles/noble_post_deploy/tasks/main.yml | 10 +++--- clusters/noble/apps/README.md | 9 +++-- .../noble/apps/homepage/kustomization.yaml | 5 +++ clusters/noble/apps/kustomization.yaml | 12 +++---- clusters/noble/apps/trivy/kustomization.yaml | 5 +++ clusters/noble/bootstrap/argocd/README.md | 13 ++++--- .../argocd/bootstrap-root-application.yaml | 6 ++-- .../bootstrap/argocd/root-application.yaml | 35 ------------------- clusters/noble/bootstrap/argocd/values.yaml | 2 +- clusters/noble/bootstrap/kustomization.yaml | 3 +- clusters/noble/wip/eclipse-che/README.md | 2 +- docs/ansible-getting-started.md | 10 +++--- docs/architecture.md | 4 +-- talos/CLUSTER-BUILD.md | 6 ++-- 18 files changed, 54 insertions(+), 93 deletions(-) create mode 100644 clusters/noble/apps/homepage/kustomization.yaml create mode 100644 clusters/noble/apps/trivy/kustomization.yaml delete mode 100644 clusters/noble/bootstrap/argocd/root-application.yaml diff --git a/ansible/README.md b/ansible/README.md index 74c1adf..7c41ce0 100644 --- a/ansible/README.md +++ b/ansible/README.md @@ -2,7 +2,7 @@ **Narrative walkthrough (Proxmox → Talos → platform → Argo):** [`docs/ansible-getting-started.md`](../docs/ansible-getting-started.md). -Automates [`talos/CLUSTER-BUILD.md`](../talos/CLUSTER-BUILD.md): optional **Talos Phase A** (genconfig → apply → bootstrap → kubeconfig), then **Phase B+** (CNI → add-ons → ingress → Argo CD → Kyverno → observability, etc.). **Trivy Operator** is installed via Argo (**`noble-trivy-operator`** app-of-apps), not **`noble.yml`**. **Argo CD** does not reconcile core charts — optional GitOps starts from an empty [`clusters/noble/apps/kustomization.yaml`](../clusters/noble/apps/kustomization.yaml). +Automates [`talos/CLUSTER-BUILD.md`](../talos/CLUSTER-BUILD.md): optional **Talos Phase A** (genconfig → apply → bootstrap → kubeconfig), then **Phase B+** (CNI → add-ons → ingress → Argo CD → Kyverno → observability, etc.). **Trivy Operator** is installed via Argo (**`noble-trivy-operator`** app-of-apps), not **`noble.yml`**. **Argo CD** does not reconcile core charts first — optional add-on **`Application`** manifests live under [`clusters/noble/apps/`](../clusters/noble/apps/) and are included when **`noble_platform`** runs **`kubectl apply -k clusters/noble/bootstrap`** (see [`clusters/noble/apps/README.md`](../clusters/noble/apps/README.md)). ## Order of operations @@ -82,7 +82,7 @@ ansible-playbook playbooks/noble.yml --tags authentik -e noble_authentik_install ### Variables — `inventory/group_vars/` and role defaults -- **`inventory/group_vars/all.yml`:** **`noble_newt_install`**, **`noble_velero_install`**, **`noble_authentik_install`**, **`noble_cert_manager_require_cloudflare_secret`**, **`noble_argocd_apply_root_application`**, **`noble_argocd_apply_bootstrap_root_application`**, **`noble_k8s_api_server_override`**, **`noble_k8s_api_server_auto_fallback`**, **`noble_k8s_api_server_fallback`**, **`noble_skip_k8s_health_check`** +- **`inventory/group_vars/all.yml`:** **`noble_newt_install`**, **`noble_velero_install`**, **`noble_authentik_install`**, **`noble_cert_manager_require_cloudflare_secret`**, **`noble_argocd_apply_bootstrap_root_application`**, **`noble_k8s_api_server_override`**, **`noble_k8s_api_server_auto_fallback`**, **`noble_k8s_api_server_fallback`**, **`noble_skip_k8s_health_check`** - **`roles/noble_platform/defaults/main.yml`:** **`noble_apply_sops_secrets`**, **`noble_sops_age_key_file`**, **`noble_platform_loki_helm_wait_timeout`**, **`noble_platform_wait_longhorn_csi_before_loki`**, **`noble_platform_longhorn_csi_rollout_timeout`** ## Roles @@ -157,7 +157,7 @@ ansible-playbook -i inventory/proxmox.yml playbooks/proxmox_ops.yml ```bash kubectl delete application -n argocd noble-platform noble-kyverno noble-kyverno-policies --ignore-not-found -kubectl apply -f clusters/noble/bootstrap/argocd/root-application.yaml +kubectl apply -f clusters/noble/bootstrap/argocd/bootstrap-root-application.yaml ``` Then run `playbooks/noble.yml` so Helm state matches git values. diff --git a/ansible/inventory/group_vars/all.yml b/ansible/inventory/group_vars/all.yml index fce9e83..4e55bc6 100644 --- a/ansible/inventory/group_vars/all.yml +++ b/ansible/inventory/group_vars/all.yml @@ -22,9 +22,7 @@ noble_cert_manager_require_cloudflare_secret: true # Velero — set **noble_velero_install: true** plus S3 bucket/URL (and credentials — see clusters/noble/bootstrap/velero/README.md) noble_velero_install: false -# Argo CD — apply app-of-apps root Application (clusters/noble/bootstrap/argocd/root-application.yaml). Set false to skip. -noble_argocd_apply_root_application: true -# Bootstrap kustomize in Argo (**noble-bootstrap-root** → **clusters/noble/bootstrap**). Applied with manual sync; enable automation after **noble.yml** (see **clusters/noble/bootstrap/argocd/README.md** §5). +# Bootstrap kustomize in Argo (**noble-bootstrap-root** → **clusters/noble/bootstrap**, includes **clusters/noble/apps**). Applied with manual sync; enable automation after **noble.yml** (see **clusters/noble/bootstrap/argocd/README.md** §5). noble_argocd_apply_bootstrap_root_application: true # Authentik (OIDC IdP) + oauth2-proxy ForwardAuth — set **true** after **.env** has NOBLE_AUTHENTIK_* (see ansible/roles/noble_authentik/README.md). diff --git a/ansible/roles/noble_argocd/defaults/main.yml b/ansible/roles/noble_argocd/defaults/main.yml index 48300ae..2043ca2 100644 --- a/ansible/roles/noble_argocd/defaults/main.yml +++ b/ansible/roles/noble_argocd/defaults/main.yml @@ -1,6 +1,3 @@ --- -# When true, applies clusters/noble/bootstrap/argocd/root-application.yaml (app-of-apps). -# Edit spec.source.repoURL in that file if your Git remote differs. -noble_argocd_apply_root_application: false # When true, applies clusters/noble/bootstrap/argocd/bootstrap-root-application.yaml (noble-bootstrap-root; manual sync until README §5). noble_argocd_apply_bootstrap_root_application: true diff --git a/ansible/roles/noble_argocd/tasks/applications_post_platform.yml b/ansible/roles/noble_argocd/tasks/applications_post_platform.yml index 4636fa2..30719d5 100644 --- a/ansible/roles/noble_argocd/tasks/applications_post_platform.yml +++ b/ansible/roles/noble_argocd/tasks/applications_post_platform.yml @@ -2,18 +2,6 @@ # Run from **ansible/playbooks/noble.yml** *after* roles **noble_platform**, **noble_authentik**, **noble_velero** # (see play **tasks:**). Leaf **Application** CRs must not be reconciled before Ansible Helm finishes, or # **argocd-controller** can SSA resources without Helm release metadata (e.g. chart-owned ServiceAccounts). -- name: Apply Argo CD root Application (app-of-apps) - ansible.builtin.command: - argv: - - kubectl - - apply - - -f - - "{{ noble_repo_root }}/clusters/noble/bootstrap/argocd/root-application.yaml" - environment: - KUBECONFIG: "{{ noble_kubeconfig }}" - when: noble_argocd_apply_root_application | default(false) | bool - changed_when: true - - name: Apply Argo CD bootstrap root Application ansible.builtin.command: argv: diff --git a/ansible/roles/noble_post_deploy/tasks/main.yml b/ansible/roles/noble_post_deploy/tasks/main.yml index ac08539..5e89e14 100644 --- a/ansible/roles/noble_post_deploy/tasks/main.yml +++ b/ansible/roles/noble_post_deploy/tasks/main.yml @@ -6,12 +6,12 @@ Private key: age-key.txt at repo root (gitignored). See clusters/noble/secrets/README.md and .sops.yaml. noble.yml decrypt-applies these when age-key.txt exists. -- name: Argo CD optional root Application (empty app-of-apps) +- name: Argo CD bootstrap root and leaf Applications ansible.builtin.debug: msg: >- App-of-apps: at the **end** of **noble.yml** (after **noble_platform**, **noble_authentik**, - **noble_velero**), **noble_argocd** `applications_post_platform.yml` runs: root-application.yaml when - noble_argocd_apply_root_application is true; bootstrap-root + **kubectl apply -k argocd/app-of-apps** - when noble_argocd_apply_bootstrap_root_application is true (inventory/group_vars/all.yml). - noble-bootstrap-root uses manual sync until you enable automation after the playbook — + **noble_velero**), **noble_argocd** `applications_post_platform.yml` applies **bootstrap-root-application.yaml** + and **kubectl apply -k argocd/app-of-apps** when **noble_argocd_apply_bootstrap_root_application** is true + (inventory/group_vars/all.yml). + **noble-bootstrap-root** syncs **clusters/noble/bootstrap** (which includes **clusters/noble/apps**); manual sync until you enable automation after the playbook — clusters/noble/bootstrap/argocd/README.md §5. See clusters/noble/apps/README.md and that README. diff --git a/clusters/noble/apps/README.md b/clusters/noble/apps/README.md index 2e5d954..70be033 100644 --- a/clusters/noble/apps/README.md +++ b/clusters/noble/apps/README.md @@ -2,6 +2,11 @@ **Base cluster configuration** (CNI, MetalLB, ingress, cert-manager, storage, observability stack, policy, SOPS secrets path, etc.) is installed by **`ansible/playbooks/noble.yml`** from **`clusters/noble/bootstrap/`** — not from here. -**`noble-root`** (`clusters/noble/bootstrap/argocd/root-application.yaml`) points at **`clusters/noble/apps`**. Add **`Application`** manifests (and optional **`AppProject`** definitions) under this directory only for workloads that are additive and do not subsume the core platform. +**`clusters/noble/apps`** is included by **`clusters/noble/bootstrap/kustomization.yaml`** (`resources: - ../apps`), so **`kubectl apply -k clusters/noble/bootstrap`** (Ansible **`noble_platform`**) and Argo **`noble-bootstrap-root`** apply optional **`Application`** / namespace manifests from this tree together with bootstrap static YAML. -Bootstrap kustomize (namespaces, static YAML, leaf **`Application`**s) lives in **`clusters/noble/bootstrap/`** and is tracked by **`noble-bootstrap-root`** — enable automated sync for that app only after **`noble.yml`** completes (**`clusters/noble/bootstrap/argocd/README.md`** §5). Put Helm **`Application`** migrations under **`clusters/noble/bootstrap/argocd/app-of-apps/`**. +## Layout + +- **`kustomization.yaml`** — lists only **subdirectories** that contain their own **`kustomization.yaml`** (add **`yourapp/`** + **`yourapp/kustomization.yaml`** instead of editing a long flat resource list). +- **`*/application.yaml`** — Argo **`Application`** CRs; Helm **`values.yaml`** files stay in the same directory but are **not** kustomize resources (the Application references them via **`$values`** paths in the repo). + +Put Helm **`Application`** definitions for core charts under **`clusters/noble/bootstrap/argocd/app-of-apps/`** (Ansible applies that directory after Helm roles). Use **`clusters/noble/apps`** only for workloads that are additive and do not subsume the core platform. diff --git a/clusters/noble/apps/homepage/kustomization.yaml b/clusters/noble/apps/homepage/kustomization.yaml new file mode 100644 index 0000000..6f311ba --- /dev/null +++ b/clusters/noble/apps/homepage/kustomization.yaml @@ -0,0 +1,5 @@ +# Helm values live alongside but are not kustomize resources — Argo loads them via **$values** in **application.yaml**. +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - application.yaml diff --git a/clusters/noble/apps/kustomization.yaml b/clusters/noble/apps/kustomization.yaml index b7fb62d..b498049 100644 --- a/clusters/noble/apps/kustomization.yaml +++ b/clusters/noble/apps/kustomization.yaml @@ -1,10 +1,8 @@ -# Argo CD **noble-root** syncs this directory. Add **Application** / **AppProject** manifests only for -# optional workloads that do not replace Ansible bootstrap (CNI, ingress, storage, core observability, etc.). -# Helm value files for those apps can live in subdirectories here (for example **./homepage/values.yaml**). +# Optional add-on **Application** CRs and namespaces — composed only of sub-kustomizations (add a directory + **kustomization.yaml**). +# Included from **clusters/noble/bootstrap/kustomization.yaml** so **kubectl apply -k clusters/noble/bootstrap** and +# Argo **noble-bootstrap-root** apply this tree with the rest of bootstrap static YAML. apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - homepage/application.yaml - - trivy/namespace.yaml - - trivy/values.yaml - - trivy/dashboard-values.yaml \ No newline at end of file + - homepage + - trivy diff --git a/clusters/noble/apps/trivy/kustomization.yaml b/clusters/noble/apps/trivy/kustomization.yaml new file mode 100644 index 0000000..ee3bef1 --- /dev/null +++ b/clusters/noble/apps/trivy/kustomization.yaml @@ -0,0 +1,5 @@ +# Operator chart values are referenced from **bootstrap/argocd/app-of-apps** Applications (**$values** paths). +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml diff --git a/clusters/noble/bootstrap/argocd/README.md b/clusters/noble/bootstrap/argocd/README.md index b603315..8315a4c 100644 --- a/clusters/noble/bootstrap/argocd/README.md +++ b/clusters/noble/bootstrap/argocd/README.md @@ -52,20 +52,19 @@ Use **Settings → Repositories** in the UI, or `argocd repo add` / a `Secret` o ## 4. App-of-apps (GitOps) -**Ansible** (`ansible/playbooks/noble.yml`) runs **`kubectl apply -k clusters/noble/bootstrap`** from **`noble_platform`**, then Helm for the platform stack, **then** **`noble_authentik`**, **`noble_velero`**, and **only then** (play **`tasks:`**) **`noble_argocd`** `applications_post_platform.yml` applies **`root-application.yaml`**, **`bootstrap-root-application.yaml`**, and **`kubectl apply -k clusters/noble/bootstrap/argocd/app-of-apps`**. **Trivy Operator** is **not** installed by Ansible; sync the **`noble-trivy-operator`** leaf app (or enable automation) after **`noble.yml`**. That order keeps **Ansible Helm first** and lets Argo **take ownership** when you sync or enable automation (no premature SSA vs Helm). +**Ansible** (`ansible/playbooks/noble.yml`) runs **`kubectl apply -k clusters/noble/bootstrap`** from **`noble_platform`**, then Helm for the platform stack, **then** **`noble_authentik`**, **`noble_velero`**, and **only then** (play **`tasks:`**) **`noble_argocd`** `applications_post_platform.yml` applies **`bootstrap-root-application.yaml`**, and **`kubectl apply -k clusters/noble/bootstrap/argocd/app-of-apps`**. **Trivy Operator** is **not** installed by Ansible; sync the **`noble-trivy-operator`** leaf app (or enable automation) after **`noble.yml`**. That order keeps **Ansible Helm first** and lets Argo **take ownership** when you sync or enable automation (no premature SSA vs Helm). -1. Edit **`root-application.yaml`** and **`bootstrap-root-application.yaml`**: set **`repoURL`** and **`targetRevision`**. The **`resources-finalizer.argocd.argoproj.io/background`** finalizer uses Argo’s path-qualified form so **`kubectl apply`** does not warn about finalizer names. -2. Optional add-on apps: add **`Application`** manifests under **`clusters/noble/apps/`** (see **`clusters/noble/apps/README.md`**). -3. **Bootstrap kustomize** (namespaces, datasource, etc.): **`noble-bootstrap-root`** syncs **`clusters/noble/bootstrap`** (no **`argocd/app-of-apps/`** in that kustomization). Leaf **`Application`** manifests live under **`argocd/app-of-apps/`**; Ansible applies that directory **after** all **`noble_*`** Helm roles in **`noble.yml`** (see §4) so Argo does not SSA charts before Helm. The root app uses **manual** sync; each leaf app is **manual** until you enable automation (see **§5**). +1. Edit **`bootstrap-root-application.yaml`**: set **`repoURL`** and **`targetRevision`**. The **`resources-finalizer.argocd.argoproj.io/background`** finalizer uses Argo’s path-qualified form so **`kubectl apply`** does not warn about finalizer names. +2. Optional add-on apps: add a subdirectory under **`clusters/noble/apps/`** with its own **`kustomization.yaml`** (see **`clusters/noble/apps/README.md`**). The bootstrap kustomization includes **`../apps`**, so **`noble-bootstrap-root`** applies them with the rest of bootstrap static YAML. +3. **Bootstrap kustomize** (namespaces, datasource, optional **`clusters/noble/apps`**, etc.): **`noble-bootstrap-root`** syncs **`clusters/noble/bootstrap`**. Leaf chart **`Application`** manifests for core charts live under **`argocd/app-of-apps/`**; Ansible applies that directory **after** all **`noble_*`** Helm roles in **`noble.yml`** (see §4) so Argo does not SSA charts before Helm. The bootstrap root app uses **manual** sync; each leaf app is **manual** until you enable automation (see **§5**). - **`ansible/playbooks/noble.yml`**: roles **`noble_argocd`** (Argo Helm only), **`noble_platform`**, **`noble_authentik`**, **`noble_velero`**, then play **`tasks`** run **`applications_post_platform`** when **`noble_argocd_apply_*`** flags are set in **`ansible/inventory/group_vars/all.yml`**. Trivy is deployed only via Argo (**`noble-trivy-operator`**). + **`ansible/playbooks/noble.yml`**: roles **`noble_argocd`** (Argo Helm only), **`noble_platform`**, **`noble_authentik`**, **`noble_velero`**, then play **`tasks`** run **`applications_post_platform`** when **`noble_argocd_apply_bootstrap_root_application`** is set in **`ansible/inventory/group_vars/all.yml`**. Trivy is deployed only via Argo (**`noble-trivy-operator`**). ```bash - kubectl apply -f clusters/noble/bootstrap/argocd/root-application.yaml kubectl apply -f clusters/noble/bootstrap/argocd/bootstrap-root-application.yaml ``` -If you migrated from older GitOps **`Application`** names, delete stale **`Application`** objects on the cluster (see **`clusters/noble/apps/README.md`**) then re-apply the roots. +If you migrated from older GitOps **`Application`** names, delete stale **`Application`** objects on the cluster (see **`clusters/noble/apps/README.md`**) then re-apply the bootstrap root. **Trivy (`noble-trivy-operator`):** If an older install left an orphan **`ServiceMonitor`** named **`trivy-operator`** in **`monitoring`** (missing `meta.helm.sh/release-*` annotations), Helm/Argo will refuse to adopt it. Delete once, then sync **`noble-trivy-operator`**: diff --git a/clusters/noble/bootstrap/argocd/bootstrap-root-application.yaml b/clusters/noble/bootstrap/argocd/bootstrap-root-application.yaml index 4dcfc9c..2461a28 100644 --- a/clusters/noble/bootstrap/argocd/bootstrap-root-application.yaml +++ b/clusters/noble/bootstrap/argocd/bootstrap-root-application.yaml @@ -1,6 +1,8 @@ # **noble-bootstrap-root** — Kustomize for **clusters/noble/bootstrap** (namespaces, Grafana datasource, -# VolumeSnapshotClass, etc.). Leaf **Application** CRs under **argocd/app-of-apps/** are **not** in this -# path; Ansible applies them after all **noble.yml** Helm roles (see play **tasks:** → **applications_post_platform.yml**). +# VolumeSnapshotClass, etc.) plus **clusters/noble/apps** (optional leaf **Application** / namespace YAML), +# included via **bootstrap/kustomization.yaml** → **../apps**. Leaf chart **Application** CRs under +# **argocd/app-of-apps/** are **not** in this path; Ansible applies them after all **noble.yml** Helm roles +# (see play **tasks:** → **applications_post_platform.yml**). # # **Initial deploy:** Ansible is the only writer; **automated sync is off** so Argo does not reconcile # during **noble.yml**. **After** the playbook finishes, enable automated sync (see **README.md** §5) diff --git a/clusters/noble/bootstrap/argocd/root-application.yaml b/clusters/noble/bootstrap/argocd/root-application.yaml deleted file mode 100644 index 79924ce..0000000 --- a/clusters/noble/bootstrap/argocd/root-application.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# App-of-apps root — apply after Argo CD is running (optional). -# -# 1. Set spec.source.repoURL (and targetRevision — **HEAD** tracks the remote default branch) to this repo. -# 2. kubectl apply -f clusters/noble/bootstrap/argocd/root-application.yaml -# -# **clusters/noble/apps** holds optional **Application** manifests. **noble_platform** applies -# **clusters/noble/bootstrap/kustomization.yaml** (namespaces + static YAML), Helm installs, then -# **applications_post_platform.yml** applies **bootstrap-root-application.yaml** and **argocd/app-of-apps/**. -# **noble-bootstrap-root** tracks bootstrap kustomize (**manual** sync until README §5). -# -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: noble-root - namespace: argocd - # Path suffix satisfies Kubernetes’ domain-qualified finalizer guidance (avoids kubectl warning). - # Background cascade: Application deletes after resources are removed asynchronously. - # See: https://argo-cd.readthedocs.io/en/stable/user-guide/app_deletion/#about-the-deletion-finalizer - finalizers: - - resources-finalizer.argocd.argoproj.io/background -spec: - project: default - source: - repoURL: https://gitea.pcenicni.ca/gsdavidp/home-server.git - targetRevision: HEAD - path: clusters/noble/apps - destination: - server: https://kubernetes.default.svc - namespace: argocd - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/clusters/noble/bootstrap/argocd/values.yaml b/clusters/noble/bootstrap/argocd/values.yaml index 1055da1..26824ed 100644 --- a/clusters/noble/bootstrap/argocd/values.yaml +++ b/clusters/noble/bootstrap/argocd/values.yaml @@ -11,7 +11,7 @@ # # Initial admin password: kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d # -# Optional: kubectl apply -f clusters/noble/bootstrap/argocd/root-application.yaml +# Optional: kubectl apply -f clusters/noble/bootstrap/argocd/bootstrap-root-application.yaml global: domain: argo.apps.noble.lab.pcenicni.dev diff --git a/clusters/noble/bootstrap/kustomization.yaml b/clusters/noble/bootstrap/kustomization.yaml index 35002bb..feeb537 100644 --- a/clusters/noble/bootstrap/kustomization.yaml +++ b/clusters/noble/bootstrap/kustomization.yaml @@ -1,4 +1,4 @@ -# Ansible **noble_platform**: `kubectl apply -k` this directory (namespaces + static YAML only). +# Ansible **noble_platform**: `kubectl apply -k` this directory (namespaces + static YAML + **../apps** optional Argo leaf Applications). # Leaf Argo **Application** manifests live under **argocd/app-of-apps/** and are applied at the **end** # of **ansible/playbooks/noble.yml** (play **tasks:** → **noble_argocd** `applications_post_platform.yml`) so # **argocd-controller** does not SSA chart resources before **helm upgrade** (platform, authentik, velero, …). @@ -19,4 +19,5 @@ resources: - velero/namespace.yaml - velero/longhorn-volumesnapshotclass.yaml - headlamp/namespace.yaml + - ../apps - grafana-loki-datasource/loki-datasource.yaml diff --git a/clusters/noble/wip/eclipse-che/README.md b/clusters/noble/wip/eclipse-che/README.md index 469b6ee..18f0966 100644 --- a/clusters/noble/wip/eclipse-che/README.md +++ b/clusters/noble/wip/eclipse-che/README.md @@ -10,7 +10,7 @@ Three **Application** resources (sync waves **0 → 1 → 2**): **Prerequisites (cluster):** **cert-manager** + **Traefik** (noble bootstrap). **DNS:** `che.apps.noble.lab.pcenicni.dev` → Traefik LB (edit **`checluster.yaml`** if your domain differs). -**First sync:** Wave ordering applies to **Application** CRs under **noble-root**; if the operator starts before DevWorkspace is ready, **Refresh**/**Sync** the child apps once. See [Eclipse Che on Kubernetes](https://eclipse.dev/che/docs/stable/administration-guide/installing-che-on-kubernetes/). +**First sync:** Wave ordering applies to **Application** CRs under **`clusters/noble/apps/`** (included in **noble-bootstrap-root**); if the operator starts before DevWorkspace is ready, **Refresh**/**Sync** the child apps once. See [Eclipse Che on Kubernetes](https://eclipse.dev/che/docs/stable/administration-guide/installing-che-on-kubernetes/). **URL:** `kubectl get checluster eclipse-che -n eclipse-che -o jsonpath='{.status.cheURL}{"\n"}'` after **Phase** is **Active`. diff --git a/docs/ansible-getting-started.md b/docs/ansible-getting-started.md index e84e4bf..8515625 100644 --- a/docs/ansible-getting-started.md +++ b/docs/ansible-getting-started.md @@ -182,22 +182,20 @@ ansible-playbook playbooks/deploy.yml Important mental model from [`clusters/noble/apps/README.md`](../clusters/noble/apps/README.md) and [`clusters/noble/bootstrap/argocd/README.md`](../clusters/noble/bootstrap/argocd/README.md): -- **Core platform** (CNI, storage, ingress, cert-manager, observability stack, Kyverno, etc.) is installed by **`noble.yml`** from **`clusters/noble/bootstrap/`** via Helm and kubectl — **Argo CD does not reconcile those charts by default** in the “empty apps folder” layout. -- **`noble-root`** tracks **`clusters/noble/apps/`** for **optional** add-on `Application` manifests. -- **`noble-bootstrap-root`** tracks **`clusters/noble/bootstrap/`** for GitOps alignment with bootstrap kustomize — enable **automated** sync only **after** Ansible has finished so Argo does not fight Helm mid-play. +- **Core platform** (CNI, storage, ingress, cert-manager, observability stack, Kyverno, etc.) is installed by **`noble.yml`** from **`clusters/noble/bootstrap/`** via Helm and kubectl — **Argo CD does not reconcile those core Helm charts by default** (those leaves live under **`argocd/app-of-apps/`** and are applied after Ansible Helm). +- **`noble-bootstrap-root`** tracks **`clusters/noble/bootstrap/`** (which **kustomize-includes** **`clusters/noble/apps/`**) for GitOps alignment with bootstrap kustomize and optional add-on **`Application`** manifests — enable **automated** sync only **after** Ansible has finished so Argo does not fight Helm mid-play. ### 4.1 What Ansible already does for Argo At the **end** of **`noble.yml`**, after all Ansible Helm roles (**`noble_platform`**, **`noble_authentik`**, **`noble_velero`** when enabled), the play runs **`noble_argocd`** task file **`applications_post_platform.yml`**, which applies: -- **`clusters/noble/bootstrap/argocd/root-application.yaml`** when **`noble_argocd_apply_root_application`** is true. - **`bootstrap-root-application.yaml`** and **`kubectl apply -k clusters/noble/bootstrap/argocd/app-of-apps`** when **`noble_argocd_apply_bootstrap_root_application`** is true. -So the **root Application CRs** and **leaf Application** registrations typically already exist on the cluster after a successful **`noble.yml`**. They are created **last** on purpose so `argocd-application-controller` does not adopt resources before Helm installs them. +So the **bootstrap root Application CR** and **leaf Application** registrations typically already exist on the cluster after a successful **`noble.yml`**. They are created **last** on purpose so `argocd-application-controller` does not adopt resources before Helm installs them. ### 4.2 Before you enable GitOps automation -1. **Edit Git URLs** in **`root-application.yaml`** and **`bootstrap-root-application.yaml`**: set **`repoURL`** and **`targetRevision`** to your real remote and branch. +1. **Edit Git URLs** in **`bootstrap-root-application.yaml`**: set **`repoURL`** and **`targetRevision`** to your real remote and branch. 2. **Register the repository** in Argo CD (UI, `argocd repo add`, or a repository `Secret`) if it is private. 3. Leave **`noble-bootstrap-root`** on **manual** sync until Helm and the cluster match git (see **§5** in [`clusters/noble/bootstrap/argocd/README.md`](../clusters/noble/bootstrap/argocd/README.md)). diff --git a/docs/architecture.md b/docs/architecture.md index feaed55..995c8f0 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -214,7 +214,7 @@ See [`talos/CLUSTER-BUILD.md`](../talos/CLUSTER-BUILD.md) for the authoritative ## Narrative -The **noble** environment is a **Talos** lab cluster on **`192.168.50.0/24`** with **three control plane nodes and one worker**, schedulable workloads on control planes enabled, and the Kubernetes API exposed through **kube-vip** at **`192.168.50.230`**. **Cilium** provides the CNI after Talos bootstrap with **`cni: none`**; **MetalLB** advertises **`192.168.50.210`–`192.168.50.229`**, pinning **Argo CD** to **`192.168.50.210`** and **Traefik** to **`192.168.50.211`** for **`*.apps.noble.lab.pcenicni.dev`**. **cert-manager** issues certificates for Traefik Ingresses; **GitOps** is **Ansible** for the **initial** platform install (**`clusters/noble/bootstrap/`**), then **Argo CD** for the kustomize tree (**`noble-bootstrap-root`** → **`clusters/noble/bootstrap`**) and optional apps (**`noble-root`** → **`clusters/noble/apps/`**) once automated sync is enabled after **`noble.yml`** (see **`clusters/noble/bootstrap/argocd/README.md`** §5). **Observability** uses **kube-prometheus-stack** in **`monitoring`**, **Loki** and **Fluent Bit** with Grafana wired via a **ConfigMap** datasource, with **Longhorn** PVCs for Prometheus, Grafana, Alertmanager, and Loki. **Secrets** in git use **SOPS** + **age** under **`clusters/noble/secrets/`**; **Kyverno** enforces **Pod Security Standards baseline** in **Audit**. **Public** access uses **Newt** to **Pangolin** with **CNAME** and Integration API steps as documented—not generic in-cluster public DNS. +The **noble** environment is a **Talos** lab cluster on **`192.168.50.0/24`** with **three control plane nodes and one worker**, schedulable workloads on control planes enabled, and the Kubernetes API exposed through **kube-vip** at **`192.168.50.230`**. **Cilium** provides the CNI after Talos bootstrap with **`cni: none`**; **MetalLB** advertises **`192.168.50.210`–`192.168.50.229`**, pinning **Argo CD** to **`192.168.50.210`** and **Traefik** to **`192.168.50.211`** for **`*.apps.noble.lab.pcenicni.dev`**. **cert-manager** issues certificates for Traefik Ingresses; **GitOps** is **Ansible** for the **initial** platform install (**`clusters/noble/bootstrap/`**), then **Argo CD** for the kustomize tree (**`noble-bootstrap-root`** → **`clusters/noble/bootstrap`**, which includes **`clusters/noble/apps/`** for optional add-on **`Application`** manifests) once automated sync is enabled after **`noble.yml`** (see **`clusters/noble/bootstrap/argocd/README.md`** §5). **Observability** uses **kube-prometheus-stack** in **`monitoring`**, **Loki** and **Fluent Bit** with Grafana wired via a **ConfigMap** datasource, with **Longhorn** PVCs for Prometheus, Grafana, Alertmanager, and Loki. **Secrets** in git use **SOPS** + **age** under **`clusters/noble/secrets/`**; **Kyverno** enforces **Pod Security Standards baseline** in **Audit**. **Public** access uses **Newt** to **Pangolin** with **CNAME** and Integration API steps as documented—not generic in-cluster public DNS. --- @@ -230,7 +230,7 @@ The **noble** environment is a **Talos** lab cluster on **`192.168.50.0/24`** wi - **Split horizon:** Confirm whether only LAN DNS resolves `*.apps.noble.lab.pcenicni.dev` to **`192.168.50.211`** or whether public resolvers also point at that address. - **Velero / S3:** optional **Ansible** install (**`noble_velero_install`**) from **`clusters/noble/bootstrap/velero/`** once an S3-compatible backend and credentials exist (see **`talos/CLUSTER-BUILD.md`** Phase F). -- **Argo CD:** Confirm **`repoURL`** in `root-application.yaml` and what is actually applied on-cluster. +- **Argo CD:** Confirm **`repoURL`** in **`bootstrap-root-application.yaml`** and what is actually applied on-cluster. --- diff --git a/talos/CLUSTER-BUILD.md b/talos/CLUSTER-BUILD.md index a7673fe..8190f84 100644 --- a/talos/CLUSTER-BUILD.md +++ b/talos/CLUSTER-BUILD.md @@ -16,7 +16,7 @@ Lab stack is **up** on-cluster through **Phase D**–**F** and **Phase G** (**`t - **Traefik** Helm **39.0.6** / app **v3.6.11** — `clusters/noble/bootstrap/traefik/`; **`Service`** **`LoadBalancer`** **`EXTERNAL-IP` `192.168.50.211`**; **`IngressClass`** **`traefik`** (default). Point **`*.apps.noble.lab.pcenicni.dev`** at **`192.168.50.211`**. MetalLB pool verification was done before replacing the temporary nginx test with Traefik. - **cert-manager** Helm **v1.20.0** / app **v1.20.0** — `clusters/noble/bootstrap/cert-manager/`; **`ClusterIssuer`** **`letsencrypt-staging`** and **`letsencrypt-prod`** (**DNS-01** via **Cloudflare** for **`pcenicni.dev`**, Secret **`cloudflare-dns-api-token`** in **`cert-manager`**); ACME email **`certificates@noble.lab.pcenicni.dev`** (edit in manifests if you want a different mailbox). - **Newt** Helm **1.2.0** / app **1.10.1** — `clusters/noble/bootstrap/newt/` (**fossorial/newt**); Pangolin site tunnel — **`newt-pangolin-auth`** Secret (**`PANGOLIN_ENDPOINT`**, **`NEWT_ID`**, **`NEWT_SECRET`**). Store credentials in git with **SOPS** (`clusters/noble/secrets/newt-pangolin-auth.secret.yaml`, **`age-key.txt`**, **`.sops.yaml`**) — see **`clusters/noble/secrets/README.md`**. **Public DNS** is **not** automated with ExternalDNS: **CNAME** records at your DNS host per Pangolin’s domain instructions, plus **Integration API** for HTTP resources/targets — see **`clusters/noble/bootstrap/newt/README.md`**. LAN access to Traefik can still use **`*.apps.noble.lab.pcenicni.dev`** → **`192.168.50.211`** (split horizon / local resolver). -- **Argo CD** Helm **9.4.17** / app **v3.3.6** — `clusters/noble/bootstrap/argocd/`; **`argocd-server`** **`LoadBalancer`** **`192.168.50.210`**; **`noble-root`** → **`clusters/noble/apps/`**; **`noble-bootstrap-root`** → **`clusters/noble/bootstrap`** (manual sync until **`argocd/README.md`** §5 after **`noble.yml`**). Edit **`repoURL`** in both root **`Application`** files before applying. +- **Argo CD** Helm **9.4.17** / app **v3.3.6** — `clusters/noble/bootstrap/argocd/`; **`argocd-server`** **`LoadBalancer`** **`192.168.50.210`**; **`noble-bootstrap-root`** → **`clusters/noble/bootstrap`** (kustomize includes **`clusters/noble/apps/`** for optional leaf **`Application`** manifests; manual sync until **`argocd/README.md`** §5 after **`noble.yml`**). Edit **`repoURL`** in **`bootstrap-root-application.yaml`** before applying. - **kube-prometheus-stack** — Helm chart **82.15.1** — `clusters/noble/bootstrap/kube-prometheus-stack/` (**namespace** `monitoring`, PSA **privileged** — **node-exporter** needs host mounts); **Longhorn** PVCs for Prometheus, Grafana, Alertmanager; **node-exporter** DaemonSet **4/4**. **Grafana Ingress:** **`https://grafana.apps.noble.lab.pcenicni.dev`** (Traefik **`ingressClassName: traefik`**, **`cert-manager.io/cluster-issuer: letsencrypt-prod`**). **Loki** datasource in Grafana: ConfigMap **`clusters/noble/bootstrap/grafana-loki-datasource/loki-datasource.yaml`** (sidecar label **`grafana_datasource: "1"`**) — not via **`grafana.additionalDataSources`** in the chart. **`helm upgrade --install` with `--wait` is silent until done** — use **`--timeout 30m`**; Grafana admin: Secret **`kube-prometheus-grafana`**, keys **`admin-user`** / **`admin-password`**. - **Loki** + **Fluent Bit** — **`grafana/loki` 6.55.0** SingleBinary + **filesystem** on **Longhorn** (`clusters/noble/bootstrap/loki/`); **`loki.auth_enabled: false`**; **`chunksCache.enabled: false`** (no memcached chunk cache). **`fluent/fluent-bit` 0.56.0** → **`loki-gateway.loki.svc:80`** (`clusters/noble/bootstrap/fluent-bit/`); **`logging`** PSA **privileged**. **Grafana Explore:** **`kubectl apply -f clusters/noble/bootstrap/grafana-loki-datasource/loki-datasource.yaml`** then **Explore → Loki** (e.g. `{job="fluent-bit"}`). - **SOPS** — cluster **`Secret`** manifests under **`clusters/noble/secrets/`** encrypted with **age** (see **`.sops.yaml`**, **`age-key.txt`** gitignored); **`noble.yml`** decrypt-applies when the private key is present. @@ -86,7 +86,7 @@ Lab stack is **up** on-cluster through **Phase D**–**F** and **Phase G** (**`t | Traefik (Helm values) | `clusters/noble/bootstrap/traefik/` — `values.yaml`, `namespace.yaml`, `README.md` | | cert-manager (Helm + ClusterIssuers) | `clusters/noble/bootstrap/cert-manager/` — `values.yaml`, `namespace.yaml`, `kustomization.yaml`, `README.md` | | Newt / Pangolin tunnel (Helm) | `clusters/noble/bootstrap/newt/` — `values.yaml`, `namespace.yaml`, `README.md` | -| Argo CD (Helm) + app-of-apps | `clusters/noble/bootstrap/argocd/` — `values.yaml`, `root-application.yaml`, `bootstrap-root-application.yaml`, `app-of-apps/`, `README.md`; **`noble-root`** syncs **`clusters/noble/apps/`**; **`noble-bootstrap-root`** syncs **`clusters/noble/bootstrap`** (enable automation after **`noble.yml`**) | +| Argo CD (Helm) + app-of-apps | `clusters/noble/bootstrap/argocd/` — `values.yaml`, `bootstrap-root-application.yaml`, `app-of-apps/`, `README.md`; **`noble-bootstrap-root`** syncs **`clusters/noble/bootstrap`** (includes **`clusters/noble/apps/`** via bootstrap **`kustomization.yaml`**) — enable automation after **`noble.yml`** | | kube-prometheus-stack (Helm values) | `clusters/noble/bootstrap/kube-prometheus-stack/` — `values.yaml`, `namespace.yaml` | | Grafana Loki datasource (ConfigMap; no chart change) | `clusters/noble/bootstrap/grafana-loki-datasource/loki-datasource.yaml` | | Loki (Helm values) | `clusters/noble/bootstrap/loki/` — `values.yaml`, `namespace.yaml` | @@ -151,7 +151,7 @@ Lab stack is **up** on-cluster through **Phase D**–**F** and **Phase G** (**`t - [x] **Argo CD** bootstrap — `clusters/noble/bootstrap/argocd/` (`helm upgrade --install argocd …`) — also covered by **`ansible/playbooks/noble.yml`** (role **`noble_argocd`**) - [x] Argo CD server **LoadBalancer** — **`192.168.50.210`** (see `values.yaml`) -- [x] **App-of-apps** — optional; **`clusters/noble/apps/kustomization.yaml`** is **empty** (core stack is **Ansible**-managed from **`clusters/noble/bootstrap/`**, not Argo). Set **`repoURL`** in **`root-application.yaml`** and add **`Application`** manifests only for optional GitOps workloads — see **`clusters/noble/apps/README.md`** +- [x] **App-of-apps** — optional add-ons live under **`clusters/noble/apps/`** (each app is a subdirectory with its own **`kustomization.yaml`**); the tree is included from **`clusters/noble/bootstrap/kustomization.yaml`**. Core charts remain **Ansible**-managed from **`clusters/noble/bootstrap/`** with leaf **`Application`** CRs under **`argocd/app-of-apps/`**. Set **`repoURL`** in **`bootstrap-root-application.yaml`** — see **`clusters/noble/apps/README.md`** - [x] **Renovate** — **`renovate.json`** at repo root ([Renovate](https://docs.renovatebot.com/) — **Kubernetes** manager for **`clusters/noble/**/*.yaml`** image pins; grouped minor/patch PRs). **Activate PRs:** install **[Mend Renovate](https://github.com/apps/renovate)** on the Git repo (**Option A**), or **Option B:** self-hosted chart per [Helm charts](https://docs.renovatebot.com/helm-charts/) + token from **SOPS** or a one-off Secret. Helm **chart** versions pinned only in comments still need manual bumps or extra **regex** `customManagers` — extend **`renovate.json`** as needed. - [ ] SSO — later