Skip to main content
  1. Infrastructure/

Architecture

·2 mins

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.sh and 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/                      # Documentation

Every directory corresponds to a FluxCD Kustomization. The cluster reconciles the master branch continuously.

Related