~/blog

How to validate a Kubernetes manifest in 10 seconds without kubectl

published

#kubernetes#yaml#devops

If you have ever applied a Kubernetes manifest only to watch kubectl reject it with a cryptic error converting YAML to JSON, you know the value of a fast pre-flight check. This post walks through a browser-only workflow that catches syntax errors, type-coercion bugs, and structural drift in under 10 seconds — without installing anything, without running a cluster, and without uploading your manifest to a third-party validator.

The 3-step check

  1. Paste your YAML into the JSON ↔ YAML converter and switch to YAML → JSON mode.
  2. Read the error, if any. The parser surfaces line/column for malformed YAML directly.
  3. Copy the JSON output to the JSON formatter to double-check structure and run optional sort-keys for diffing.

That’s it. Everything client-side. The whole loop fits in a coffee break.

What this catches

YAML syntax errors that kubectl apply reports cryptically

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
spec:
  replicas: 3
  selector:
   matchLabels:
      app: demo

The matchLabels line is indented one space short. kubectl says:

error: error parsing manifest.yaml: error converting YAML to JSON: yaml: line 8: did not find expected key

The JSON ↔ YAML converter says:

Line 8, column 3 — bad indentation of a mapping entry

Same problem, plain-English message, no cluster round-trip.

The Norway problem and other YAML 1.1 coercions

This is the classic foot-gun. In YAML 1.1, the following:

country: NO

…parses as country: false. Because NO, no, N, n, OFF, off, false, and FALSE are all booleans in the 1.1 spec. Same for YES, ON, TRUE, etc.

Kubernetes manifests are usually parsed with YAML 1.2 + the JSON-compatible schema, which strips these aliases. But:

The converter uses YAML 1.2 with the JSON-compatible schema specifically to avoid this. If country: NO round-trips back as the string "NO", you’re safe across modern parsers. If it round-trips as false, the YAML library Kubernetes uses may still treat it as a boolean depending on the cluster’s API server version.

Defensive habit: quote any all-caps string in YAML. country: "NO" works everywhere.

Floats where you wanted strings

version: 1.0

This parses as the float 1, which serializes back as "1". Your image tag silently lost its .0.

version: "1.0"

This parses as the string "1.0" and round-trips correctly.

The converter’s quoting strategy on JSON → YAML quotes any string that would otherwise be coerced — numeric-looking, boolean-looking, null-looking. Round-tripping is safe by default.

Octal numbers

timeout: 010

YAML 1.1 reads this as octal 8. YAML 1.2 reads it as the string "010". Different parsers, different answers. Always quote.

What kubectl --dry-run=client does not catch that this workflow does

kubectl --dry-run=client -o yaml -f manifest.yaml validates schema against the server’s CRDs. It catches:

It does not catch:

The browser workflow handles all three: convert both manifests to JSON, sort keys recursively, then diff the results in JSON-aware mode. Pure formatting drift collapses to zero.

A 30-second drift check

You’re debugging why staging works but prod doesn’t. Both manifests are 200 lines of YAML.

  1. Paste prod manifest into JSON ↔ YAML, JSON output → copy.
  2. Paste staging manifest into JSON ↔ YAML, JSON output → copy.
  3. Open the diff checker, paste prod on the left, staging on the right, switch to JSON-aware mode.
  4. Read the structural diff. Keys reordered between files? Invisible. Real value differences? Highlighted.

The whole process is faster than waiting for kubectl diff to round-trip through the API server, and works on manifests that aren’t even applied yet.

When YAML really does need a server check

The browser workflow is for syntax, structure, and round-trip safety. It cannot validate:

For those you still need kubectl --dry-run=server or a tool like kubeconform running offline against bundled OpenAPI schemas. But 80% of “the manifest is broken” errors are caught by the 10-second loop above.

Privacy notes

The converter, formatter, and diff checker all run entirely in your browser tab. Manifests can contain secrets — secret names, registry credentials, internal service URLs — that you probably don’t want pasted into a random online validator. With browser-only tools the input never leaves your device. Verify with DevTools → Network: nothing fires after the page loads.

Tooling

All three are free, client-side, no signup, no upload.