Flux CD’s RBAC, policies, and audit logging are crucial for securing your GitOps workflows, but their interaction can be surprisingly subtle.

Here’s Flux CD in action, managing a simple deployment. Imagine this source.yaml pointing to a Git repository:

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: my-app-repo
  namespace: flux-system
spec:
  interval: 1m
  url: ssh://git@github.com/my-org/my-app.git
  ref:
    branch: main
  secretRef:
    name: github-ssh-key

And this kustomization.yaml in that repo:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app-deployment
  namespace: flux-system
spec:
  interval: 5m
  path: ./deploy/production
  sourceRef:
    kind: GitRepository
    name: my-app-repo
  prune: true
  validation: client

When Flux reconciles these, it first fetches the Git repo (triggering RBAC checks for the source.toolkit.fluxcd.io API group and the flux-system namespace), then applies the Kustomization (again, RBAC checks for kustomize.toolkit.fluxcd.io and the flux-system namespace). If the Kustomization points to a HelmRelease or Deployment, further RBAC checks occur for those resources in their target namespaces.

The core problem Flux solves is the reliable, automated synchronization of Kubernetes cluster state with a Git repository. It does this by running controllers within the cluster that continuously watch for changes in both Git and the Kubernetes API. When a discrepancy is found, Flux applies the necessary changes to the cluster.

The key levers you control are:

  • GitRepository and HelmRepository objects: These define where Flux gets its manifests from (Git URLs, Helm chart repositories).
  • Kustomization and HelmRelease objects: These define what Flux applies to the cluster, including paths within Git repos, Helm chart values, and reconciliation intervals.
  • ImageRepository and ImagePolicy objects: These enable Flux to monitor container image registries and automatically update Kustomization or HelmRelease objects when new image tags are found.
  • RBAC roles and rolebindings: These grant Flux controllers the necessary permissions to read from Git (via secrets) and write to the Kubernetes API.
  • Policy controllers (e.g., Kyverno, OPA Gatekeeper): These enforce custom rules on what Flux can apply to the cluster, preventing drift or unauthorized changes.
  • Audit logging: This provides a trail of Flux’s actions, showing what it applied, when, and by whom (if using user-impersonation).

The most surprising thing most people don’t realize is that Flux’s validation: client setting on Kustomization objects doesn’t actually validate the content of your manifests against your cluster’s schema. Instead, it tells Flux to perform a client-side check to see if the Kubernetes API server would accept the manifest before attempting to apply it. This is a lightweight pre-flight check, not a deep schema validation. It catches basic API errors but won’t prevent you from deploying a manifest that is syntactically valid but semantically wrong for your cluster’s current state or installed CRDs.

By default, Flux controllers operate with a service account that has broad permissions. To truly harden Flux, you need to scope down these permissions using RBAC and then use policy engines to enforce specific constraints on the resources Flux is allowed to deploy.

The next logical step after mastering RBAC and policies is to explore Flux’s capabilities for managing secrets securely.

Want structured learning?

Take the full Flux course →