Architecture¶
GitOps-driven Cluster API (CAPI) management
platform. A disposable local kind cluster
bootstraps Flux, provisions the self-managed management
cluster through CAPI, and is deleted after a clusterctl move pivot. The
management cluster then reconciles itself and all downstream infrastructure from
this repository across multiple supported environments: AWS (aws), Azure
(azure), GCP (gcp), local Docker (local-host), bare-metal Talos
(local-talos), and an air-gapped bundle (airgap).
The operator normally runs the imperative lifecycle through the
krops-toolbox container. It mounts the host engine socket, joins the kind
network while the bootstrap cluster exists, and leaves no toolbox workload in
the managed clusters. This packaging changes the host tool boundary, not the
Flux or CAPI reconciliation architecture.
Architecture pillars¶
These principles guide every change to krops. A change that departs from one states why in its pull request.
One reconciliation loop, minimal abstractions¶
Flux is the single reconciliation loop. Every persistent change is YAML in
Git, and Flux converges the clusters toward it: cluster lifecycle (Cluster
API), per-cluster Flux instances (CAPI addons), and cloud resources (ACK,
ASO, Config Connector) are all Kubernetes resources reconciled the same way.
There is no Terraform, no state file, and no second toolchain with its own
plan and apply cycle. The only imperative steps are bootstrap, pivot, and
teardown, run by krops-bootstrap or the shell equivalents bootstrap.sh,
pivot.sh, and teardown.sh (one script per phase); bootstrap and pivot
hand control to Flux and exit.
Each abstraction layer is one more thing a human or AI agent operator must understand before changing the system, and one more place for mistakes and hallucinations. krops therefore uses each component's upstream API (Flux, CAPI, the cloud operators) directly instead of wrapping it in generators, templating layers, or in-house CRDs, and adds a layer only when it removes more complexity than it introduces.
Cloud operators on the management cluster¶
The cloud operators run on the management cluster: ACK for AWS, the ASO
bundled with CAPZ for Azure, and Config Connector for GCP. They reconcile
the per-workload-cluster cloud resources through
mgmt/
The workload clusters run no controllers and hold no credentials: no operator deployment, no workload identity, no secrets at rest. A workload that needs cloud access gets it the same way the management cluster does, not by installing its own operator.
AWS environment (aws)¶
The reference environment manages AWS infrastructure through the Kubernetes API: CAPA provisions EKS workload clusters, CAPI addons deliver per-cluster Flux instances, and ACK operators (S3, RDS, IAM) on the management cluster manage the per-cluster cloud resources with static SOPS credentials. Workload clusters run no controllers and hold no credentials.
flowchart TD
subgraph bootstrap["Bootstrap (one-time, krops-bootstrap CLI)"]
KIND[kind cluster: mgmt, disposable]
HELM[Helm: flux-operator + FluxInstance]
SEC[Secrets: flux-github-pat + sops-age]
KIND --> HELM
KIND --> SEC
end
subgraph git["Git: github.com/polarsquad/krops"]
REPO[(main branch)]
end
HELM -->|"sync: mgmt/aws/"| REPO
subgraph mgmt["Management cluster (self-managed after the pivot) - Flux Kustomizations (dependsOn order)"]
FS[flux-system root]
CM[cert-manager]
CO[capi-operator]
CI[capa-identity]
AMC[aws-managed-clusters]
MGMT[management cluster def<br/>self-hosted via the pivot]
CAPIS[capi-system]
CAPAS["capa-system (SOPS creds)"]
CAAPH[caaph-system]
ACKC["ack-controllers (SOPS creds)<br/>ACK S3 + RDS + IAM controllers"]
WR["workload-resources<br/>Bucket + DBInstance + reader Role CRs"]
AWSIAM["aws-global-iam<br/>krops-reader console user"]
KONF["konflate (SOPS token)<br/>rendered Flux PR review"]
EUN[eu-north-1 cluster def]
EUW[eu-west-1 cluster def]
FA["flux-apps (SOPS pull secret)<br/>HelmChartProxy + ResourceSet"]
FS --> CM --> CO
CO --> CI --> AMC
CO --> CAPIS --> CAPAS --> CAAPH --> FA
CAPAS --> EUN
CAPAS --> EUW
CAPAS --> MGMT
FS --> ACKC --> WR
ACKC --> AWSIAM
FS --> KONF
end
REPO --> FS
subgraph aws["AWS"]
EKS1[EKS: eu-north-1-workload<br/>x86 + ARM node pools]
EKS2[EKS: eu-west-1-workload<br/>x86 + ARM node pools]
B1[(S3: krops-...-eu-north-1-workload-data)]
B2[(S3: krops-...-eu-west-1-workload-data)]
DB1[(RDS: krops-eu-north-1-workload-db)]
DB2[(RDS: krops-eu-west-1-workload-db)]
RD1[IAM Role: krops-eu-north-1-workload-reader<br/>trust: account root]
RD2[IAM Role: krops-eu-west-1-workload-reader<br/>trust: account root]
RUSER[IAM User: krops-reader<br/>console login, assumes reader roles]
end
EUN -->|CAPA provisions| EKS1
EUW -->|CAPA provisions| EKS2
AWSIAM -->|creates| RUSER
RUSER -.->|sts:AssumeRole| RD1
RUSER -.->|sts:AssumeRole| RD2
FA -->|"HelmChartProxy: flux-operator<br/>ResourceSet: FluxInstance + cluster-vars + pull secret (remote-apply)"| WF1
FA -->|same, per region label| WF2
subgraph wl1["Workload cluster eu-north-1"]
WF1["Flux (sync: workload/eu-north-01)<br/>workload/base is empty today"]
end
subgraph wl2["Workload cluster eu-west-1"]
WF2["Flux (sync: workload/eu-west-01)<br/>workload/base is empty today"]
end
WF1 --> REPO
WF2 --> REPO
WR -->|Bucket CR reconciled| B1
WR -->|Bucket CR reconciled| B2
WR -->|DBInstance CR reconciled| DB1
WR -->|DBInstance CR reconciled| DB2
WR -->|Role CR reconciled| RD1
WR -->|Role CR reconciled| RD2
Reconciliation order (AWS management cluster)¶
Enforced with Flux dependsOn:
cert-manager ▶ capi-operator ▶ capi-system ▶ capa-system ▶ clusters (eu-north-1, eu-west-1)
│ └▶ caaph-system ▶ flux-apps
└▶ capa-identity ▶ aws-managed-clusters
ack-controllers ▶ workload-resources
ack-controllers ▶ aws-global-iam
konflate (no dependencies)
The eu-north-1 cluster definitions include the management cluster itself
(clusters/management/): after the pivot, the management cluster's own Flux
instance reconciles the Cluster objects that define it. The bootstrap kind
cluster no longer exists at this point; nothing runs from an operator's
laptop.
PR review: konflate¶
The management cluster also runs a single
konflate instance
(mgmt/aws/infrastructure/konflate/), pointed at this repo
(github://polarsquad/krops, rendering from the repo root). It renders each
open PR at its merge-base and head and shows the diff of the rendered Flux
output (blast radius, image changes, render failures, and danger lint)
instead of the raw file diff. Results reach the PR two ways: a GitHub Actions
workflow (.github/workflows/konflate.yml) runs a one-shot konflate service
container on each PR push and gates the konflate / Rendered Flux diff check
on a clean render, and the in-cluster instance posts the rendered summary
comment and a Konflate commit status itself (write-back, outbound-only, so
the local kind cluster needs no inbound reachability from GitHub). Both upsert
the same marker-keyed comment. Full details (deployment, CI gate, tokens,
write-back, UI access): PR review: konflate.
Reconciliation order (AWS workload clusters)¶
(empty: workload/base reconciles nothing since issue #346; the per-cluster
Flux instance stays installed, ready for a future application workload)
How workload apps are delivered (AWS)¶
- Each
Clusterinmgmt/aws/clusters/carries labelsfluxcd: enabledandregion: <region>. flux-appsmatches those labels: a HelmChartProxy installs the Flux Operator on everyfluxcd: enabledworkload cluster, and a templated ResourceSet remote-applies the per-region Flux bootstrap bag (namespace, cluster-vars, pull secret, FluxInstance) intoflux-systemon each workload via its CAPI kubeconfig Secret, with inventory pruning on re-creation.cluster-varskeepsAWS_REGION,CLUSTER_NAME, andAWS_ACCOUNT_IDas thepostBuildsubstitution channel for a future workload.- The workload cluster's Flux reconciles
workload/<region>-01, whosebase/overlay is intentionally empty since issue #346: the ACK controllers and the Bucket / DBInstance / reader Role CRs moved to the management cluster (mgmt/aws/infrastructure/ack-controllers/andmgmt/aws/infrastructure/workload-resources/). The instance reconciles nothing today but is ready for a future application workload (the local-host Podinfo pattern).
See AWS authentication & IAM for how the ACK controllers authenticate, and Workload resources for what they create.
Azure environment (azure)¶
The azure environment mirrors aws: a disposable kind cluster bootstraps
Flux, CAPZ v1.27.0 provisions an AKS management cluster (swedencentral-management),
the pivot moves the management objects into it, and the management cluster's
ASO (bundled with CAPZ) reconciles the workload Azure resources from
mgmt/azure/infrastructure/workload-resources/.
No Azure secret exists at rest: the management cluster authenticates CAPZ and
the bundled ASO with workload identity against the krops-capz
User-Assigned Identity (federated to the kind cluster's Arc OIDC issuer at
bootstrap, and to the management cluster's own OIDC issuer post-pivot), and
workload clusters hold no credentials at all. The bundled ASO on the
management cluster reconciles the workload Azure resources (VNet, storage
account, PostgreSQL Flexible Server) and the management identity resources
(krops-capz identity and its Federated Identity Credentials), all through
the aso-credentials Secret.
See the architecture diagram in docs/azure-infra.svg and the Azure environment guide.
flowchart TD
subgraph bootstrap["Bootstrap (one-time, krops-bootstrap CLI)"]
KIND[kind cluster: mgmt, disposable]
HELM[Helm: flux-operator + FluxInstance]
SEC[Secrets: flux-github-pat + sops-age]
KIND --> HELM
KIND --> SEC
end
subgraph git["Git: github.com/polarsquad/krops"]
REPO[(main branch)]
end
HELM -->|"sync: mgmt/azure/"| REPO
subgraph mgmt["Management cluster (self-managed after the pivot) - Flux Kustomizations"]
FS[flux-system root]
CM[cert-manager]
CO[capi-operator]
CAPIS[capi-system]
CAPZS["capz-system (CAPZ v1.27.0 + bundled ASO)"]
CAAPH[caaph-system]
AZID["azure-identity (secret-free)<br/>AzureClusterIdentity: WorkloadIdentity"]
ASOWI["aso-workload-identity<br/>krops-capz + FICs + data RG"]
WLR["workload-resources Ks<br/>VNet + storage + PostgreSQL"]
SWEDENC["swedencentral cluster def<br/>swedencentral-management (self-hosted)<br/>swedencentral-workload"]
FA["flux-apps (SOPS pull secret)<br/>HelmChartProxy + ResourceSet"]
FS --> CM --> CO --> CAPIS --> CAPZS
CAPIS --> CAAPH --> FA
CAPZS --> AZID --> ASOWI --> WLR
CAPZS --> SWEDENC
AZID --> SWEDENC
end
REPO --> FS
subgraph azure["Azure: swedencentral"]
AKS[AKS: swedencentral-workload<br/>AzureASOManagedControlPlane + MachinePool]
RG[(Resource Group: krops-swedencentral-workload-data)]
VNET[(VNet: krops-swedencentral-workload-vnet<br/>subnet: postgres<br/>private DNS zone)]
SA[(Storage Account: blob container 'data')]
PSQL[(PostgreSQL Flexible Server<br/>private access, Entra-only auth)]
end
SWEDENC -->|CAPZ provisions| AKS
ASOWI -->|bundled ASO creates| RG
FA -->|"HelmChartProxy: flux-operator<br/>ResourceSet: FluxInstance + cluster-vars + pull secret (remote-apply)"| WF
subgraph wl["Workload cluster swedencentral-workload"]
WF["Flux (sync: workload/swedencentral-01)"]
WCM["cert-manager Ks"]
WF --> WCM
end
WF --> REPO
WLR -->|bundled ASO reconciles| VNET
WLR -->|bundled ASO reconciles in data RG| SA
WLR -->|bundled ASO reconciles with private DNS| PSQL
Reconciliation order (Azure management cluster)¶
cert-manager ▶ capi-operator ▶ capi-system ▶ capz-system (bundled ASO)
├▶ azure-identity ▶ aso-workload-identity ▶ workload-resources
├▶ clusters (swedencentral)
└▶ caaph-system ▶ flux-apps
Reconciliation order (Azure workload cluster)¶
cert-manager (the Azure resources moved to the management cluster in issue #559)
GCP environment (gcp)¶
The gcp environment mirrors azure: a disposable kind cluster bootstraps
Flux, CAPG v1.13.1 provisions a GKE management cluster
(europe-north1-management), the pivot moves the management objects into
it, and the management cluster's Config Connector (KCC 1.159.0) reconciles
the GCP workload resources from
mgmt/gcp/infrastructure/workload-resources/ (issue #560: the workload
cluster no longer runs its own KCC).
No GCP secret exists at rest. CAPG and the management-side Config Connector
authenticate with Workload Identity Federation against the krops pool:
their service accounts present the cluster's projected token through the
kind provider at bootstrap and the Git-declared mgmt provider
post-pivot, and the credential files are plain external_account Secrets
with a subject condition restricted to exactly those two service accounts
(krops-capg is the GSA they impersonate). The pivot applies the two
credential Secrets to the target before clusterctl move
(pivot-manifests) and pins GCP_WIF_PROVIDER=mgmt
(pivot-manifest-vars), because the source-side ConfigMap merge order
cannot guarantee it.
See the architecture diagram in docs/gcp-infra.svg and the GCP environment guide.
flowchart TD
subgraph bootstrap["Bootstrap (one-time, krops-bootstrap CLI)"]
KIND[kind cluster: mgmt, disposable]
WIF["wif-federate (post-kind-create-task)<br/>krops pool + kind provider + JWKS"]
HELM[Helm: flux-operator + FluxInstance]
KIND --> WIF
KIND --> HELM
end
subgraph git["Git: github.com/polarsquad/krops"]
REPO[(main branch)]
end
HELM -->|"sync: mgmt/gcp/"| REPO
subgraph mgmt["Management cluster (self-managed after the pivot) - Flux Kustomizations"]
FS[flux-system root]
GCPV[gcp-vars ConfigMap]
CM[cert-manager]
CO[capi-operator]
CAPIS[capi-system]
CAPGS["capg-system (CAPG v1.13.1)<br/>WIF credential Secret, secret-free"]
CAAPH[caaph-system]
KCCO["kcc-operator (1.159.0, Helm chart via OCIRepository)"]
KCC["kcc (ConfigConnector in cnrm-system)<br/>WIF credential Secret"]
KCCI["kcc-identity (KCC-managed)<br/>krops pool + mgmt provider + GSA grants"]
WRES["workload-resources (KCC CRs, issue #560)<br/>networking / storage / postgres / iam"]
EUNC["europe-north1 cluster defs<br/>europe-north1-management (self-hosted)<br/>europe-north1-workload"]
FA["flux-apps (SOPS pull secret)<br/>HelmChartProxy + ResourceSet"]
FS --> CM --> CO --> CAPIS --> CAPGS
CAPIS --> CAAPH --> FA
FS --> KCCO --> KCC --> KCCI --> WRES
CAPGS --> EUNC
end
REPO --> FS
subgraph gcp["GCP: europe-north1"]
GKE[GKE: europe-north1-management<br/>+ europe-north1-workload]
POOL["Workload Identity Pool: krops<br/>providers: kind (bootstrap) + mgmt (Git)"]
GSAS["krops-capg / krops-reader GSAs"]
VPC[(VPC + PSA range: krops-europe-north1-workload-psa)]
BUCKET[(Storage bucket: krops-<number>-europe-north1-workload-data)]
SQL[(Cloud SQL: krops-europe-north1-workload-db<br/>private IP, IAM auth)]
end
EUNC -->|CAPG provisions| GKE
KCCI -->|KCC creates| POOL
KCCI -->|KCC creates| GSAS
WRES -->|KCC reconciles as krops-capg| SQL
WRES -->|KCC reconciles| VPC
WRES -->|KCC reconciles| BUCKET
FA -->|"HelmChartProxy: flux-operator<br/>ResourceSet: FluxInstance + cluster-vars + pull secret (remote-apply)"| WF
subgraph wl["Workload cluster europe-north1-workload (GKE)"]
WF["Flux (sync: workload/europe-north1-01)<br/>gcp-base root intentionally empty (issue #560)"]
end
WF --> REPO
Reconciliation order (GCP management cluster)¶
gcp-vars ▶ cert-manager ▶ capi-operator ▶ capi-system ▶ capg-system (GCPManaged* CRDs)
├▶ caaph-system ▶ flux-apps
gcp-vars ▶ kcc-operator (StatefulSet Ready) ▶ kcc (cnrm-system) ▶ kcc-identity (krops pool, mgmt provider)
europe-north1 clusters (dependsOn: capg-system, gcp-vars)
Reconciliation order (GCP workload cluster)¶
Flux only. The gcp-base root is intentionally empty (issue #560): the
workload cloud resources reconcile on the management cluster - see the
management-cluster chain above, where workload-resources depends on
kcc-identity (networking first, then postgres after networking, iam last).
Local host environment (local-host)¶
The local-host environment replaces AWS with local Docker containers (CAPD)
and GitHub with a local in-memory OCI registry (krops-registry:5000). It
provisions a one-control-plane/one-worker workload cluster and reconciles the
Podinfo demo application end to end on a single host. The per-workload Flux
bag is delivered by a templated ResourceSet like the clouds, but the
local-host bundle carries only the FluxInstance (no cluster-vars, no pull
secret) and the per-cluster Kustomization sources from the mgmt
flux-system OCIRepository.
See the architecture diagram in docs/local-host-infra.svg.
flowchart TD
subgraph bootstrap["Bootstrap (one-time, krops-bootstrap CLI)"]
KIND[kind cluster: mgmt, disposable]
REG["Local OCI Registry: krops-registry:5000"]
HELM[Helm: flux-operator + FluxInstance]
KIND --> HELM
REG -->|oci://krops-registry:5000/krops| HELM
end
subgraph oci["Local OCI Registry: krops-registry:5000"]
ARTIFACT["OCI Artifact: krops:latest<br/>published via mise run oci-push"]
end
subgraph mgmt["Management cluster (self-managed CAPD after pivot)"]
FS[flux-system root]
CM[cert-manager]
CO[capi-operator]
CAPIS[capi-system]
CAPDS["capd-system (Docker provider)"]
CAAPH[caaph-system]
MGMT["management cluster def<br/>local-management (Docker)"]
DOCKER["clusters/docker def<br/>local-workload"]
FA["flux-apps (HelmChartProxy + ResourceSet)"]
FS --> CM --> CO --> CAPIS --> CAPDS
CAPIS --> CAAPH --> FA
CAPDS --> MGMT
CAPDS --> DOCKER
end
ARTIFACT --> FS
subgraph wl["Workload cluster local-workload (Docker containers)"]
CP[1 Control Plane container]
WORKER[1 Worker container]
WF["Flux (syncs workload/local-host from OCI)"]
APP["podinfo demo application<br/>port-forward to localhost:9898"]
WF --> APP
end
DOCKER -->|CAPD provisions| CP
DOCKER -->|CAPD provisions| WORKER
FA -->|installs Flux via HelmChartProxy| WF
ARTIFACT --> WF
Reconciliation order (local-host)¶
Management cluster:
cert-manager ▶ capi-operator ▶ capi-system ▶ capd-system ▶ clusters (local-management, local-workload)
│ └▶ caaph-system ▶ cni ▶ flux-apps
Workload cluster:
podinfo (HelmRelease reconciled by local workload Flux from OCI artifact)
Bare-metal Talos environment (local-talos)¶
The local-talos environment targets physical bare metal: a disposable kind
cluster installs CAPI with the Tinkerbell infrastructure provider (CAPT pinned
to fork v0.7.1) and Talos bootstrap/control-plane providers (CABPT v0.9.0,
CACPPT v0.9.0). The controllers match a committed Tinkerbell Hardware object
(talos-mgmt-01), PXE-boot the target machine, and bring up an immutable
single-node control plane. The installer image is set with the
hardware.tinkerbell.org/installer-image annotation on the Hardware CR,
mirrored into status.installerImage by the CAPT fork and injected by CABPT;
the committed definition pins no installer image, so without the annotation
installs use the default Image Factory schematic.
Scope fence: local-talos is management-only. It owns no workload clusters and
deploys no CAPI addons (Talos ships its own internal CNI). Teardown deletes the
CAPI objects so CAPT releases the Hardware back to the Tinkerbell pool; the
physical machine is never wiped or reclaimed.
See the architecture diagram in docs/local-talos-infra.svg.
flowchart TD
subgraph bootstrap["Bootstrap (one-time, krops-bootstrap CLI)"]
KIND[kind cluster: mgmt, disposable]
HELM[Helm: flux-operator + FluxInstance]
SEC[Secrets: flux-github-pat + sops-age]
KIND --> HELM
KIND --> SEC
end
subgraph git["Git: github.com/polarsquad/krops"]
REPO[(main branch)]
end
HELM -->|"sync: mgmt/local-talos/"| REPO
subgraph mgmt["Management cluster (bare metal, self-managed after pivot)"]
FS[flux-system root]
CM[cert-manager]
CO[capi-operator]
CAPIS[capi-system]
CAPT["capt-system (Tinkerbell CAPT v0.7.1 fork)"]
CABPT["cabpt-system (Talos bootstrap v0.9.0)"]
CACPPT["cacppt-system (Talos control plane v0.9.0)"]
TALOSMGMT["clusters/management<br/>talos-mgmt-01 (explicit controlPlaneRef)"]
FS --> CM --> CO --> CAPIS
CAPIS --> CAPT
CAPIS --> CABPT
CAPIS --> CACPPT
CAPT --> TALOSMGMT
CABPT --> TALOSMGMT
CACPPT --> TALOSMGMT
end
REPO --> FS
subgraph metal["Physical Metal (Tinkerbell Substrate)"]
HW["Tinkerbell Hardware: talos-mgmt-01<br/>committed MAC / BMC credentials"]
PXE["PXE network boot + Hook environment"]
IMG["Talos installer image streamed to disk"]
NODE["Single-node bare metal control plane<br/>static VIP / Talos API"]
end
TALOSMGMT -->|CAPT claims| HW
HW --> PXE --> IMG --> NODE
Reconciliation order (local-talos)¶
cert-manager ▶ capi-operator ▶ capi-system ▶ capt-system (Tinkerbell CAPT) ──┐
├▶ cabpt-system (Talos bootstrap) ─┼▶ clusters/management (talos-mgmt-01)
└▶ cacppt-system (Talos CP) ───────┘
Air-gapped bundle (airgap)¶
The air-gap bundle packages the local-host profile with Zarf
for completely disconnected deployments. A connected build machine renders the
krops GitOps tree, pulls required container images and charts, generates Syft
SBOMs, and signs the resulting package. On the disconnected deploy host, Zarf
initializes an internal container registry and proxy agent that rewrites image
pulls, while Flux reconciles the offline management and workload clusters with zero
external network traffic.
See the architecture diagram in docs/air-gap-infra.svg and the Air-gapped krops guide.
Pattern comparisons¶
Terraform and OpenTofu store desired state in HCL and a state file and apply it in discrete plan/apply runs; krops stores it as Kubernetes resources in Git that controllers reconcile continuously, so there is no snapshot to drift, no locks to fight or corrupt. One control plane covers infrastructure and workloads, so RBAC, policy, and audit span both, and cluster lifecycle and workload delivery form one dependency graph instead of a Terraform-built cluster that no longer manages what runs inside it.
krops ships no controller of its own: it combines Cluster API for clusters, each cloud's native operator (ACK on AWS) for cloud resources, and Flux for GitOps. If those resource APIs already say what you mean, krops does not wrap them to say it again. Least abstraction and one reconciliation loop are the pillars the pattern is held to.
Crossplane is the closer comparison, and in one use case it is now a sort-of competitor: the composition story, turning provider resources into higher-level platform APIs, is served by Flux ResourceSets templating plain Kubernetes resources. The overlap is that use case; the scope still differs. Crossplane brings its own provider packages, XRDs, and composition machinery, a second reconciliation plane to operate, while krops keeps one reconciliation loop over the upstream APIs of the components it already runs. Crossplane remains the evaluated alternative resource plane, selectable per environment instead of the native operator, never both, with Flux still delivering everything from Git. See Crossplane as a resource plane.
The management cluster is not a long-lived local kind cluster: the bootstrap kind cluster is disposable, and after the pivot the management cluster manages itself through the same GitOps flow it drives.
Pull requests are reviewed as rendered Flux diffs (blast radius, image changes, render failures) by konflate: a GitHub Actions workflow runs it on every PR push as a merge gate, and an in-cluster instance posts the summary to the PR, so what you review is byte-for-byte what reconciles.
Repository layout¶
.
├── .github/workflows/ Validation, Rust/toolbox CI, docs CI and
│ Pages deploy, the konflate PR render gate,
│ the nightly air-gapped bundle build, and
│ signed toolbox releases
├── airgap/ Zarf air-gap bundle, image inventory, scripts
├── virtualized-e2e/ WireMock-virtualized e2e harness (#355):
│ lib/ shared components + one arm per
│ cloud (aws/ is the reference); not
│ Flux-reconciled, no mise task yet
├── bootstrap-rs/ Lifecycle CLI, toolbox Dockerfile, Rust tests
├── bootstrap.toml Repository-owned lifecycle configuration
├── bootstrap.sh / pivot.sh / Native shell references and fallback paths;
│ teardown.sh retained until both parity gates pass
├── scripts/toolbox-run.sh Docker/Podman wrapper: the lifecycle entry
│ point (bootstrap, pivot, teardown)
├── tests/ Config and Renovate coverage cross-checks
├── mkdocs.yml MkDocs Material config for the docs site
├── pyproject.toml / uv.lock Python project for the docs site build
├── tools/assemble_docs.py Assembles build/docs/ from README.md + docs/
├── website/ Docs site assets: colour scheme CSS, CNAME
├── docs/ Detailed documentation (linked from README.md)
├── mise.toml / mise.*.toml Pinned toolchain (the toolbox image is
│ built from these pins) and the helper
│ task definitions (run in the toolbox with
│ --entrypoint mise; validate and the
│ podinfo port-forward stay host tasks)
├── renovate.json5 Hosted Renovate discovery and grouping rules
├── mgmt/aws/ Synced by the MANAGEMENT cluster's Flux
│ ├── infrastructure/ cert-manager, CAPI operator, CAPA identity,
│ │ ACK controllers (S3, RDS, IAM) and the
│ │ per-cluster Bucket/DBInstance/reader Role
│ │ CRs, account-global IAM (reader console
│ │ user), konflate (rendered Flux PR review)
│ ├── capi-providers/ capi-system, capa-system (SOPS creds),
│ │ caaph-system
│ ├── addons/flux-apps/ Installs Flux on each workload cluster
│ │ (HelmChartProxy + ResourceSet)
│ └── clusters/ EKS cluster defs: eu-north-1, eu-west-1
│ (x86 + ARM MachinePools); eu-north-1 also
│ carries the self-managed management cluster
├── mgmt/local-host/ OCI-synced CAPI/CAPD local workload cluster
│ │ and its management cluster definition
│ ├── infrastructure/ capi-operator, cert-manager
│ ├── capi-providers/ caaph-system, capd-system, capi-system
│ ├── addons/ kindnet CNI, flux-apps
│ └── clusters/ docker (workload), management (self-managed)
├── mgmt/local-talos/ Single-node Talos management cluster on
│ │ bare metal via Tinkerbell (CAPT);
│ │ GitHub-synced like mgmt/aws
│ ├── infrastructure/ capi-operator, cert-manager
│ ├── capi-providers/ cabpt-system, cacppt-system, capi-system,
│ │ capt-system (Tinkerbell)
│ └── clusters/ management (self-managed)
├── mgmt/azure/ AKS management cluster (CAPZ + ASO)
├── mgmt/gcp/ GKE management cluster (CAPG + Config
│ │ Connector operator + WIF identities)
└── workload/ Synced by each WORKLOAD cluster's Flux
├── base/ Intentionally empty since #346 (ACK moved
│ to the management cluster); ready for a
│ future application workload
├── azure-base/ cert-manager only (the Azure workload
│ resources moved to the management cluster,
│ #559)
├── gcp-base/ intentionally empty (issue #560: KCC and
│ the GCP resources moved to the management
│ cluster's workload-resources)
├── local-host/ OCI-synced Podinfo workload overlay
├── eu-north-01/ Per-cluster overlay (sync target)
├── eu-west-01/ Per-cluster overlay (sync target)
├── swedencentral-01/ Per-cluster overlay -> azure-base
└── europe-north1-01/ Per-cluster overlay -> gcp-base