phase2-prep: per-component no-secret rollout + component hardening (author-first)
Prep only — nothing deployed; running cluster untouched. Reconciliation graph (operator-approved Option A): author clusters/dev/rollout/ = 4 per-component Flux Kustomizations (kyverno->cilium->longhorn->monitoring, monitoring dependsOn longhorn). Dev overlay $patch:delete's the monolithic base platform/apps and adds ./rollout, so only the no-secret tier reconciles; the secret-blocked components are simply not created until hand-offs arrive. The no-secret tier carries no SOPS content, so it needs no sops-age key. prod is untouched (still builds the monolith). Convergence path coded in (delete rollout/ + the two deletes) — R-ENV-02 divergence flagged for architect review. Component hardening via cluster-vars (prod keeps strict posture): - KYVERNO_VALIDATION_ACTION Enforce->Audit(dev), _WEBHOOK_FAILURE_POLICY Fail->Ignore(dev), _ADMISSION_REPLICAS 3->1(dev); webhook namespaceSelector excludes system+platform namespaces. - MONITORING_STORAGE_CLASS var; GRAFANA_ADMIN_SECRET var (dev ''=chart default); Alertmanager SMTP/secret deferred to Phase-4 with verbatim re-enable markers. Cilium parity verified against the live CNI (no-op adopt). Validated: kubectl kustomize dev/prod/all-components, envsubst->YAML parse, make -C ci gate PASS. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
1 parent
99eef2fe4c
commit
d9a80e5350
16 files changed
+278
-53
No files matched your search
@@ -2,39 +2,38 @@
|
||||
# clusters/dev — the ACTIVE build target overlay.
|
||||
#
|
||||
# `flux bootstrap ... --path=clusters/dev` points the dev cluster's Flux here.
|
||||
# This overlay adds NO resources of its own. Its ONLY job is to patch the shared cluster-vars
|
||||
# ConfigMap with dev-scoped values (R-ENV-02). The base reconciliation graph is reused verbatim.
|
||||
# TRANSITIONAL (Phase-2 bootstrap): this overlay reuses the base source + cluster-vars, but
|
||||
# REPLACES the monolithic base `platform`/`apps` Kustomizations with a per-component NO-SECRET
|
||||
# rollout (./rollout) — so dev brings up cilium/longhorn/monitoring/kyverno in order WITHOUT
|
||||
# dragging in the secret-blocked components. It patches cluster-vars with dev values (R-ENV-02)
|
||||
# and softens Kyverno for bootstrap. CONVERGENCE: delete ./rollout + the two $patch:delete
|
||||
# below to return to the unified base graph once all operator hand-offs land. See DECISIONS-LOG.
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../base
|
||||
- rollout
|
||||
patches:
|
||||
# --- SOPS decryption + bootstrap source (PM-inlined from bootstrap/flux/patches/, 2026-08-16) ---
|
||||
# Inlined (not cross-dir file refs) to stay within kustomize's default load restrictions.
|
||||
# Realises the commented decryption TODOs in clusters/base and sets the real source URL.
|
||||
# The `sops-age` Secret is created out-of-band (bootstrap/sops/install-age-key.sh) — name only.
|
||||
# --- Drop the monolithic base platform/apps Kustomizations. They reconcile ALL 11 components
|
||||
# as one unit (incl. secret-blocked cert-manager/externaldns/velero/keycloak/oauth2-proxy/
|
||||
# image-automation/gateway/kubevirt); ./rollout replaces them with the per-component
|
||||
# no-secret set for dev bootstrap. Remove these two deletes to re-adopt the unified graph.
|
||||
# (No decryption patch is needed here: the rollout components carry no SOPS content, so
|
||||
# the `sops-age` Secret is not required for the dev bootstrap tier.) ---
|
||||
- patch: |-
|
||||
$patch: delete
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: platform
|
||||
namespace: flux-system
|
||||
spec:
|
||||
decryption:
|
||||
provider: sops
|
||||
secretRef:
|
||||
name: sops-age
|
||||
- patch: |-
|
||||
$patch: delete
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: apps
|
||||
namespace: flux-system
|
||||
spec:
|
||||
decryption:
|
||||
provider: sops
|
||||
secretRef:
|
||||
name: sops-age
|
||||
- patch: |-
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
@@ -84,3 +83,18 @@ patches:
|
||||
- op: replace
|
||||
path: /data/VELERO_RETENTION
|
||||
value: "72h"
|
||||
# dev-softened Kyverno for cold-start (base defaults Enforce/Fail/3 = prod posture).
|
||||
- op: replace
|
||||
path: /data/KYVERNO_VALIDATION_ACTION
|
||||
value: "Audit"
|
||||
- op: replace
|
||||
path: /data/KYVERNO_WEBHOOK_FAILURE_POLICY
|
||||
value: "Ignore"
|
||||
- op: replace
|
||||
path: /data/KYVERNO_ADMISSION_REPLICAS
|
||||
value: "1"
|
||||
# dev: no Grafana admin Secret yet → empty makes the chart use its default admin password
|
||||
# (dev-only, NAT-isolated). Prod keeps the by-name SOPS secret from the base default.
|
||||
- op: replace
|
||||
path: /data/GRAFANA_ADMIN_SECRET
|
||||
value: ""
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
# Cilium — ADOPT the running Ansible-installed CNI. Parity between platform/cilium and the
|
||||
# live config was verified (k8sServiceHost/port via pod env, kube-proxy-replacement, gateway-api,
|
||||
# egress+bpf masquerade, hubble, l2, cgroup, v1.16.5) → this reconcile is a NO-OP.
|
||||
# prune: false — Cilium was bootstrapped out-of-band; adopt its config, never own-delete the CNI.
|
||||
# No decryption (no SOPS content). No dependsOn (it is the datapath everything else rides on).
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: cilium
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 30m
|
||||
retryInterval: 2m
|
||||
timeout: 10m
|
||||
prune: false
|
||||
wait: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./platform/cilium
|
||||
postBuild:
|
||||
substituteFrom:
|
||||
- kind: ConfigMap
|
||||
name: cluster-vars
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
# Phase-2 NO-SECRET incremental rollout — DEV bootstrap scaffold.
|
||||
#
|
||||
# Per-component Flux Kustomizations for the components that need NO operator secret:
|
||||
# kyverno (admission, dev-softened) · cilium (adopt running CNI) · longhorn (storage)
|
||||
# · monitoring (dependsOn longhorn).
|
||||
# Secret-blocked components (cert-manager, externaldns, gateway, velero, keycloak,
|
||||
# oauth2-proxy, image-automation, kubevirt) are intentionally NOT created until their
|
||||
# operator hand-offs arrive (DECISIONS-LOG A2 / hand-off table).
|
||||
#
|
||||
# TRANSITIONAL: this is the dev bootstrap graph. Once every hand-off lands, dev drops
|
||||
# ./rollout and re-adopts the unified base monolith (clusters/base/platform.yaml) so dev
|
||||
# and prod share one reconciliation graph again (R-ENV-02 convergence). See DECISIONS-LOG.
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- kyverno.yaml # first: admission present (Audit/Ignore in dev — non-blocking) before workloads
|
||||
- cilium.yaml # adopt the running CNI (parity verified — no-op reconcile)
|
||||
- longhorn.yaml # storage; monitoring depends on its StorageClass
|
||||
- monitoring.yaml # dependsOn longhorn
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
# Kyverno — in-cluster admission enforcer. DEV-SOFTENED via cluster-vars:
|
||||
# KYVERNO_VALIDATION_ACTION=Audit, KYVERNO_WEBHOOK_FAILURE_POLICY=Ignore,
|
||||
# KYVERNO_ADMISSION_REPLICAS=1 (base defaults Enforce/Fail/3 for prod).
|
||||
# Non-blocking on today's cluster (policies match only `app-namespace=true` namespaces,
|
||||
# none exist yet). No SOPS content. Listed first so admission is present before workloads.
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: kyverno
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1h
|
||||
retryInterval: 2m
|
||||
timeout: 10m
|
||||
prune: true
|
||||
wait: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./platform/kyverno
|
||||
postBuild:
|
||||
substituteFrom:
|
||||
- kind: ConfigMap
|
||||
name: cluster-vars
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
# Longhorn — block storage / CSI (default `longhorn` StorageClass). No SOPS content.
|
||||
# No dependsOn. The bulk-NFS StorageClass in this component carries REPLACE-ME (OQ-2) but is
|
||||
# an isolated, unreferenced object — it does NOT block Longhorn's HelmRelease reconcile.
|
||||
# PRE-DEPLOY CHECK (runtime, out of git): confirm `iscsid` active + /var/lib/longhorn mounted
|
||||
# on all 3 nodes (cloud-init provides both; verify after the T-1.5 rebuild).
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: longhorn
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 2m
|
||||
timeout: 10m
|
||||
prune: true
|
||||
wait: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./platform/longhorn
|
||||
postBuild:
|
||||
substituteFrom:
|
||||
- kind: ConfigMap
|
||||
name: cluster-vars
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
# Monitoring — kube-prometheus-stack + Loki + Alloy. Prometheus/Loki PVCs bind the
|
||||
# `longhorn` StorageClass, so this dependsOn longhorn (Flux waits for it Ready first).
|
||||
# Grafana admin password (chart default in dev) and Alertmanager SMTP (deferred to the
|
||||
# Phase-4 hand-off) are handled WITHOUT an operator secret in dev → NO decryption block.
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: monitoring
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 2m
|
||||
timeout: 15m
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: longhorn
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./platform/monitoring
|
||||
postBuild:
|
||||
substituteFrom:
|
||||
- kind: ConfigMap
|
||||
name: cluster-vars
|
||||
Reference in new issue
Block a user