Skip to main content

KYAML Goes Stable in Kubernetes v1.37: What a Canonical YAML Subset Means for the Manifests a Git-Push PaaS Generates on Every Deploy

9 min readDora NodaDora Noda
Share
On this page

Somewhere in a fleet much like yours, a ConfigMap once said country: NO — and Kubernetes read it as country: false. No error, no warning. Norway, the country, silently became a boolean, because unquoted NO in YAML 1.1 means "no". That is the Norway problem, and it is the single best argument for what Kubernetes v1.37 "Garhwal" did on August 26, 2026: among its 67 enhancements (16 stable, 23 beta, 27 alpha), it promoted KYAML — a strict, unambiguous YAML subset — to stable, and with it the kubectl get -o kyaml output format.

If your platform generates Kubernetes manifests programmatically on every git push, this is the first upstream-blessed canonical form for those bytes. Here is the whole story in one before-and-after. A PaaS emitting a tenant's ConfigMap today produces familiar block YAML:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: tenant-flags
data:
  country: NO
  greeting: hello

The same object in KYAML:

yaml
{
  apiVersion: "v1",
  kind: "ConfigMap",
  metadata: {
    name: "tenant-flags",
  },
  data: {
    country: "NO",
    greeting: "hello",
  },
}

Same object, zero ambiguity. Every string value is double-quoted, so NO can never coerce to false. Every level of nesting is delimited by braces instead of indentation depth. And because KYAML is still valid YAML, every parser, apiserver, and kubectl apply in your pipeline reads it unchanged. The verdict up front: stable KYAML gives generated-manifest pipelines a canonical rendering that the diff engine, the admission check, and the agent can all agree on — and it belongs at emit time, as a guarantee your generator makes, not as a linter you run after the fact.

What KYAML actually is​

KYAML comes from SIG CLI's KEP-5295, and its definition fits in a table:

RuleWhat it means
Flow style everywhereMaps use {} and sequences use [], laid out across indented lines
String values always double-quotedString scalars carry explicit quotes (keys may or may not be); no guessing
Bare scalars only for non-stringsNumbers, booleans, and null stay unquoted
Trailing commasEvery element ends with a comma, so diffs stay one-line-per-change
Structure from delimiters, not whitespaceIndentation is cosmetic; braces define nesting
100% valid YAMLAny existing YAML 1.2 parser reads KYAML with no changes

The mental model from the community is "JSON with comments": explicit delimiters plus YAML's comment support, without JSON's trailing-comma intolerance or YAML's significant whitespace. Note the direction of compatibility — every KYAML document is valid YAML, but not every YAML document is KYAML. Nothing in your pipeline needs to change to start reading it.

The graduation path was deliberately slow: KYAML arrived as alpha in v1.34, moved to beta (on by default, though you still request it with -o kyaml) in v1.35, and went stable in v1.37. Alongside the release, the Kubernetes blog published a KYAML explainer and pretty-print guide on August 11, 2026, and the KEP's goals commit to more than a kubectl flag: stable, idempotent conversion libraries, and project documentation showing KYAML alongside conventional YAML in examples. The ecosystem is already moving — Corvus.JsonSchema shipped a KYAML emitter profile for its JSON-to-YAML writer, and independent strict-subset emitters now cite KEP-5295 as their spec.

Why generated manifests are where it pays​

Hand-authored YAML gets human review. Generated YAML gets applied. A git-push PaaS control plane renders manifests on every deploy — per tenant, per environment, per preview — which means it pays YAML's ambiguity tax at machine volume, with no human in the loop to catch the misparse. Three failure modes dominate, and they are exactly the ones the KEP was written to kill.

First, whitespace counting at template-expansion time. Helm substitutes text into templates without understanding YAML structure, so inserting a multi-line value means indent/nindent arithmetic to line up with the surrounding block. Get it wrong and the manifest either breaks outright or — worse — parses into something else. A PaaS generating overlays per tenant hits the same class of bug every time it splices generated blocks into a base document.

Second, implicit type coercion in generated config. The KEP's own list is damning: unquoted NO, no, N, YES, yes, Y, On, and Off all parse as booleans; _42 parses as a number; 11:00 parses as a base-60 number. Tenant-supplied strings flow through generators constantly — environment values, feature flags, locale codes — and any of them can land in this trap. Quoting discipline in a generator is a convention every code path must remember; in KYAML it is the only output the emitter produces.

Third, wrongly-indented YAML that is syntactically valid but marshals wrong. The KEP calls this out explicitly: readers and writers must track nesting depth, and the evidence says that is genuinely hard. When the same logical deploy can serialize three different ways and still apply, every downstream consumer — your diff view, your drift detector, your audit log — has to normalize before it can compare. Canonical output removes that normalization step by making it unnecessary.

Emit-time guarantee, not a post-hoc linter​

The placement question matters more than the format question. KYAML compliance belongs at the point of emission — your generator produces canonical bytes — not as a lint step bolted on after rendering. The pipeline looks like this:

text
git push → build → generate manifests → canonicalize (KYAML) → diff → admit → apply

Canonicalization sits between generation and everything downstream, so every consumer after it reasons about one stable representation. A post-hoc linter is weaker in a specific way: it inspects bytes after the fact and reports violations, but the invariant it checks is one the emitter could have guaranteed by construction. Push the guarantee left and three consumers get simpler at once.

The diff engine sees intent-only diffs. When the same logical object always serializes identically, a diff between the last applied manifest and the new one shows what the deploy actually changed — not quoting churn, key reorder noise, or indentation drift. Preview-environment reviews and GitOps drift detection both become "read the diff" instead of "normalize, then read the diff."

Admission checks validate stable bytes. Whether it is CEL-based policy on the apiserver or a check in your own control plane, validating canonical input means the policy author reasons about one serialization, not the half-dozen ways block YAML can express the same object. The KEP's goal of stable, idempotent conversion is what makes this safe to rely on: canonicalize twice and you get the same bytes twice.

Agents read unambiguous text. An operator agent — or your own deploy-from-chat surface — parsing a manifest no longer has to resolve whether NO is a string or a boolean, or reconstruct nesting from whitespace. For AI agents as first-class operators, canonical form is load-bearing: the model reads what the apiserver will apply, with no silent reinterpretation in between.

None of this requires migrating existing manifests. Because KYAML is valid YAML, you can canonicalize at the emit boundary while every stored template, Helm chart, and hand-written overlay stays exactly as it is.

Honest limits​

The KEP is admirably frank about what KYAML does not do, and a PaaS team should take those limits seriously.

There is no server-side distinction. The apiserver accepts KYAML the way it accepts any YAML — which is to say, KYAML is a client-side and emit-side convention, not an enforcement boundary. Nothing stops a tenant's hand-applied manifest from arriving in the most ambiguous block YAML imaginable. Canonical output cleans your pipeline; it does not clean the cluster.

Helm-style text patching of KYAML breaks. This is the KEP's own drawback, stated plainly: trying to text-patch KYAML with plain YAML will almost certainly not work, because mixing flow and block styles is a mess. If your pipeline splices strings into rendered manifests today, canonical output forces you to move that splicing upstream of emission — which is the right architecture, but it is real migration work, not a free win.

A local dialect dilutes knowledge. Another serialization is another thing to learn, and the KEP answers its own "yet another standard" objection with the only rebuttal that matters: KYAML is YAML, and vanilla YAML is accepted anywhere KYAML is. Adoption can be gradual and one-directional because there is no flag day.

One clarification worth making early: KEP-5295's KYAML is not the kustomize kyaml Go library. The library (sigs.k8s.io/kustomize/kyaml, the RNode-based YAML editing packages kustomize builds on) shares a name and a problem space but is a different artifact. When someone says "KYAML went stable in 1.37," they mean the dialect and the kubectl get -o kyaml output — not a library graduation.

What to do Monday morning​

Four steps, in order of increasing commitment:

  1. Read path first. Start requesting -o kyaml anywhere your tooling renders objects back for review — diff views, drift reports, debug output. Zero migration risk: it is just an output flag, and the Norway-class surprises disappear from what humans read.
  2. Canonicalize at the emit boundary. Teach your manifest generator to emit KYAML (or pipe its output through a canonicalizing encoder) before diffing, admitting, or applying. The KEP promises stable, idempotent conversion libraries; ecosystem emitters are already appearing for JSON-to-YAML paths.
  3. Compare canonical forms. Point your drift detector and preview diffs at canonical bytes so reviews show intent. This is where the daily toil savings land: every avoided "is this diff real?" question compounds across tenants and deploys.
  4. Show both in docs. Follow the KEP's lead and present KYAML alongside conventional YAML in your own platform documentation. Your tenants' agents will thank you — they read your docs too.

The deeper trend is worth naming. Kubernetes spent a decade with YAML as its human interface and JSON as its machine interface, and the two drifted. KYAML is the ecosystem admitting that generated, agent-read configuration needs a form designed for exactness rather than brevity — JSON's explicitness with YAML's comments, blessed upstream so every tool can converge on it. For a platform that turns git pushes into running services, that convergence point is where the emit boundary should aim. Stable output, agreed upon by everything downstream: that is what "canonical" buys you, one deploy at a time.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex