Repository Structure
Repository Layout covers the full directory tree and the base/overlay pattern. This page is narrower: two GitOps-specific mechanisms that decide what Flux actually reconciles from and which controller reconciles it — neither obvious from the directory tree alone.
One GitRepository, sliced into ExternalArtifacts
Every domain Kustomization under clusters/mycluster-0/ — infrastructure,
security, observability, tooling, apps, the flux/* self-management
Kustomizations, crds, namespaces — sources from an ExternalArtifact,
not from the flux-system GitRepository directly. All of them are produced
by one ArtifactGenerator, flux/artifact-generators/monorepo-split.yaml:
apiVersion: source.extensions.fluxcd.io/v1beta1
kind: ArtifactGenerator
metadata:
name: monorepo-split
spec:
sources:
- alias: repo
kind: GitRepository
name: flux-system
artifacts:
- name: infra-artifact
copy:
- from: "@repo/infrastructure/**"
to: "@artifact/infrastructure/"
# one entry per domain: security, observability, tooling, apps,
# flux, crds, namespacesIt re-slices the one GitRepository artifact (the whole repository, fetched
once) into one narrower ExternalArtifact per top-level domain directory.
Every domain Kustomization then points sourceRef at its own slice —
infrastructure.yaml at infra-artifact, security.yaml at
security-artifact, and so on — instead of at the full repository.
Two Kustomizations are the exception, necessarily: flux-artifact-generators
(which applies the ArtifactGenerator above, so it has to read the
GitRepository directly — the ExternalArtifacts don’t exist until it
runs) and the opt-in llm-platform umbrella, whose path
(clusters/mycluster-0-llm-platform/) falls outside every copy.from glob
above.
The from: "@repo/<dir>/**" / to: "@artifact/<dir>/" shape matters: a
trailing / on the source instead of /** copies <dir>/ into
<artifact>/<dir>/ — one level of double-nesting — rather than the
directory’s contents into the artifact root.
Controller sharding: apps vs default
The FluxInstance (opentofu/eks/init/helm_values/flux-instance.yaml)
configures one extra shard:
sharding:
key: "sharding.fluxcd.io/key"
shards:
- "apps"Two Kustomizations — tooling and apps — carry
labels: sharding.fluxcd.io/key: apps and propagate it to what they create
via spec.commonMetadata.labels; everything else reconciles on the default,
unsharded controller set. The isolation has one sharp edge: a GitRepository
or HelmRepository Source placed under an app-owned directory would
inherit that label the same way any other resource there does, and the
default shard’s source-controller/helm-controller cannot see a
HelmChart whose GitRepository is only visible to the apps shard — it
reconciles fine as Ready, and a completely unrelated HelmRelease on the
default shard fails with “source not found”, far from the actual cause.
flux/sources/ carries no shard label for exactly this reason: every
GitRepository/HelmRepository in this repository lives there, never under
an app-owned directory.