Validate Kubernetes Manifests with Flux Schema
Flux 2.9 shipped Flux Schema, a CLI plugin that checks your Kubernetes manifests against JSON Schema and CEL rules before they merge. Here is how to wire it up.
If you run GitOps with Flux, a broken manifest usually gets caught the slow way: it merges, the reconciler chokes, and you find out from a failing Kustomization. Flux Schema, the plugin that shipped with Flux 2.9, moves that check left into CI. It validates every YAML document against JSON Schema and CEL rules using the same evaluation logic as the Kubernetes API server, so a bad field fails the pull request instead of the cluster.
Install and run it
Flux Schema is a CLI plugin, not part of the core binary. Install it through the plugin system:
$ flux plugin install schema
$ flux schema --help
Pin a version in CI so a new release never changes your gate’s behavior mid-sprint:
$ flux plugin install [email protected]
Point it at a directory of manifests and it validates each document:
$ flux schema validate ./manifests
It ships with built-in schemas for Kubernetes, OpenShift, Gateway API, and the Flux CRDs, so a fresh install already knows your HelmRelease and Kustomization kinds without any setup. Strict validation flags unknown fields, wrong types, and missing required properties as hard errors, which catches the typos kubectl apply --dry-run=client quietly ignores.
What CEL adds over plain schema checks
JSON Schema catches shape problems: a string where an int belongs, a misspelled key. CEL rules catch logic problems. Because Flux Schema runs the x-kubernetes-validations rules embedded in CRDs through the same CEL engine the API server uses, a manifest that violates a cross-field constraint (say, a replica count that must stay below a limit, or two mutually exclusive fields both set) fails in CI with the exact message the cluster would have returned. You are testing against the real admission logic, not a stale copy of it.
Wire it into a config file
Drop a .fluxschema.yml at your repo root to control what gets checked. The file uses the schema.plugin.fluxcd.io/v1beta1 API and a Config kind:
apiVersion: schema.plugin.fluxcd.io/v1beta1
kind: Config
skipKind:
- Secret
skipJSONPath:
- "$.metadata.annotations"
skipKind, skipFile, and skipJSONPath let you exclude the things that legitimately fail strict checks, like sealed secrets or generated fields. Then the command reads it automatically:
$ flux schema validate ./manifests --config .fluxschema.yml
Put it in the pull request gate
The real payoff is in CI. Flux Schema ships two composite GitHub Actions: setup installs the CLI on the runner, and validate auto-detects your kustomize overlays, renders them, and validates every rendered document. A minimal gate looks like this:
name: validate-manifests
on: [pull_request]
jobs:
flux-schema:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: fluxcd/flux-schema/actions/validate@main
with:
config: .fluxschema.yml
Because the Ecosystem Catalog behind the plugin refreshes daily from upstream releases, your CI validates against the current API versions rather than whatever was frozen months ago. That matters most right after a Kubernetes minor bump, when a deprecated field you have used for a year suddenly needs to change.
One habit worth keeping: run flux schema validate locally before you push, not just in CI. The feedback loop is a second or two, and it saves a round trip through the runner. If you are still deciding between Flux and Argo CD for this kind of workflow, our Argo CD vs Flux guide compares them for multi-cluster setups, and our GitOps testing strategies piece covers where manifest validation fits in a broader test pyramid.
Read the Flux Schema announcement on fluxcd.io for the full catalog details, then add the action to one repo and watch the first bad manifest fail its PR instead of your cluster.
Related articles
Get the next article in your inbox
Practical DevOps tips, tutorials, and guides. No spam, unsubscribe anytime.