Skip to content

FluxCD Overview ​

How Flux is deployed and configured in RPCU clusters using the Flux Operator pattern.

Architecture ​

RPCU uses a two-layer Flux deployment model:

  1. Flux Operator - A one-time kubectl apply that installs the operator itself
  2. FluxInstance - A CRD that the operator reconciles to deploy the full Flux distribution

This avoids bootstrapping Flux with flux bootstrap and keeps the entire lifecycle GitOps-managed.

┌─────────────────────────────────────────────────────┐
│                   Git Repository                     │
│                  (RPCU/argus)                        │
└──────────────────────┬──────────────────────────────┘
                       │ sync (1m interval)
                       ▼
┌─────────────────────────────────────────────────────┐
│              Flux Operator (v0.40.0)                 │
│  One-time install via kustomize build | kubectl apply│
└──────────────────────┬──────────────────────────────┘
                       │ reconciles
                       ▼
┌─────────────────────────────────────────────────────┐
│               FluxInstance (Flux 2.x)                │
│  source-controller, kustomize-controller,            │
│  helm-controller, notification-controller            │
│  42 concurrent ops per controller                    │
└──────────────────────┬──────────────────────────────┘
                       │ watches
                       ▼
┌─────────────────────────────────────────────────────┐
│         Cluster-specific Kustomizations              │
│  (cert-manager, cilium, CAPI, yaook, etc.)           │
└─────────────────────────────────────────────────────┘

Flux Operator ​

The operator is installed as a plain Kustomize remote base, pinned to a specific release:

yaml
# infrastructure/fluxcd/operator/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - https://github.com/controlplaneio-fluxcd/flux-operator/releases/download/v0.40.0/install.yaml

FluxInstance ​

The FluxInstance CRD tells the operator which Flux distribution to deploy and where to sync from:

yaml
# infrastructure/fluxcd/instances/flux.yaml
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
  name: flux
  namespace: flux-system
spec:
  distribution:
    version: "2.x"
    registry: "ghcr.io/fluxcd"
  components:
    - source-controller
    - kustomize-controller
    - helm-controller
    - notification-controller
  cluster:
    type: kubernetes
    multitenant: false
    networkPolicy: true
    domain: "cluster.local"
  kustomize:
    patches:
      - target:
          kind: Deployment
          name: "(kustomize-controller|helm-controller)"
        patch: |
          - op: add
            path: /spec/template/spec/containers/0/args/-
            value: --concurrent=42
  sync:
    kind: GitRepository
    url: "https://github.com/RPCU/argus.git"
    ref: "refs/heads/main"
    path: "./clusters/PLACEHOLDER"
    interval: "1m"

Key settings:

FieldValuePurpose
distribution.version2.xFlux v2 distribution
components4 controllersFull Flux stack
sync.urlhttps://github.com/RPCU/argus.gitSingle Git source for all clusters
sync.path./clusters/PLACEHOLDEROverridden per cluster
sync.interval1mReconcile every minute
kustomize.patches--concurrent=42High parallelism for large clusters

Per-Cluster Overrides ​

Each cluster patches the base FluxInstance to set its own sync path and domain:

Management Cluster ​

yaml
# clusters/mgmt/fluxcd/flux-instance-patch.yaml
spec:
  cluster:
    domain: "mgmt.local"
  sync:
    path: "./clusters/mgmt"

OpenStack Cluster ​

yaml
# clusters/openstack/fluxcd/flux-instance-patch.yaml
spec:
  cluster:
    domain: "openstack.local"
  sync:
    path: "./clusters/openstack"

Flux Components ​

ControllerPurpose
source-controllerFetches artifacts from Git, Helm repos, OCI registries
kustomize-controllerReconciles Kustomization resources (kustomize overlays)
helm-controllerReconciles HelmRelease resources (Helm chart lifecycle)
notification-controllerSends/receives alerts (GitHub commit status, Slack, etc.)

Kustomization vs HelmRelease ​

Flux provides two primary reconciliation primitives:

  • Kustomization - For raw Kubernetes manifests, kustomize overlays, and remote bases. Used for: CAPI providers, ORC, external-snapshotter, cert-manager issuers, gateway-api CRDs.
  • HelmRelease - For Helm chart lifecycle management. Used for: cert-manager, cilium, kgateway, rook, crossplane, yaook operators, CAPI operator, OCCM, Cinder CSI, external-dns.

Dependency Ordering ​

Flux Kustomizations declare explicit dependsOn to enforce ordering:

flux-operator (no deps)
  └─> fluxcd (depends on flux-operator)
        └─> cert-manager (no deps)
              └─> cluster-api-operator (depends on cert-manager)
                    └─> cluster-api-providers (depends on cluster-api-operator + external-secrets)
                          └─> cluster-api-templates (depends on cluster-api-providers)

This ensures CRDs exist before resources that depend on them, and credentials are ready before components that need them.

Manual Secrets ​

Only one secret must be created manually: capo-variables in the capo-system namespace. This is the root secret from which all other OpenStack credentials are derived via External Secrets Operator. See the Bootstrap Guide for the exact format and creation steps.

Three Kustomizations (capo-identity, openstack-ccm-identity, external-dns) use wait: false because they depend on this manually-placed secret — Flux applies the resources, but they remain "not ready" until the secret appears.

Open source infrastructure documentation