FluxCD dependency chain#
Everything in the cluster is deployed via FluxCD Kustomizations, organized in a dependency chain that ensures components are created in the right order:
graph TD
NS["namespaces"] --> CRDs["crds"]
CRDs --> Routes["routes"]
CRDs --> Base["base
cert-manager, ESO, MetalLB,
Longhorn, kgateway"]
Base --> Operators["operators
Strimzi, OLM, Percona,
KEDA, Dragonfly, etc."]
Operators --> Network["network
MetalLB pools, L2Adv,
Gateway, HTTPRoutes"]
Operators --> Messaging["messaging
Kafka, NATS, RabbitMQ"]
Operators --> DevPlatform["dev-platform
Coder, ARC, TFC agents,
Camel K"]
Operators --> Observability["observability
VMKS, Jaeger,
Headlamp"]
Operators --> Security["security
Keycloak"]
Operators --> Argo["argo
ArgoCD, Workflows,
Events"]
Observability --> VPA["vpa
VPA resources"]
Each box is a FluxCD Kustomization pointing to a directory in the Git repository. Arrows represent dependsOn relationships — a Kustomization won’t reconcile until its dependencies are healthy.
Why this ordering matters#
- Namespaces first — every other resource needs its namespace to exist.
- CRDs before base — operators like cert-manager need their CRDs registered before the HelmRelease can create CRs.
- Base before operators — cert-manager needs to be running before anything that needs TLS certificates. ESO needs to be running before anything that needs secrets from Infisical.
- Security and Argo deploy in parallel — ArgoCD configures Keycloak OIDC endpoints, but doesn’t need Keycloak running to deploy. Login works once Keycloak comes up naturally.
Traffic flow#
External traffic enters the cluster through a single path:
graph LR
Client["Client
(on Tailnet)"] --> DNS["Cloudflare DNS
*.wcloud.sh"]
DNS --> TS["Tailscale
Subnet Router"]
TS --> VIP["MetalLB VIP
192.168.4.2"]
VIP --> GW["kgateway
(Envoy)"]
GW -->|"SNI routing"| Svc["Kubernetes
Service"]
Svc --> Pod["Pod"]
CM["cert-manager"] -.->|"TLS certs"| GW
ExtDNS["external-dns"] -.->|"DNS records"| DNS
Key points:
- All services are exposed under
*.wcloud.shand are only reachable via Tailscale. - external-dns watches Gateway API HTTPRoute resources and automatically creates Cloudflare DNS records.
- cert-manager provisions Let’s Encrypt TLS certificates using Cloudflare DNS-01 challenges.
- kgateway (Envoy-based) performs TLS termination and SNI-based routing.
- MetalLB advertises the VIP (
192.168.4.2) via L2/ARP on the home network.
Repository structure#
k8s-config/
├── clusters/willingham-k8s/ # FluxCD Kustomization entry points
├── namespaces/ # Namespace definitions
├── crds/ # Custom Resource Definitions
├── base/ # Foundational operators
│ ├── cert-manager/
│ ├── external-secrets/
│ ├── longhorn/
│ ├── metallb/
│ └── kgateway/
├── operators/ # Infrastructure operators
├── network/ # MetalLB pools, Gateway, routes
├── messaging/ # Kafka, NATS, RabbitMQ
├── security/ # Keycloak
├── observability/ # VMKS, Jaeger, Headlamp
├── argo/ # ArgoCD, Workflows, Events
├── dev-platform/ # Coder, ARC, TFC, Camel K
├── vpa/ # VPA resources
├── routes/ # Gateway API HTTPRoutes
└── docs/ # DocumentationEvery directory corresponds to a FluxCD Kustomization. The cluster reconciles the master branch continuously.