KYAML: Convergence of JSON Robustness and YAML Flexibility in Kubernetes

22 January 2026 · 4 min read

In Kubernetes operational management, defining manifests has historically swung between two extremes. On one hand, YAML, the de facto standard, offers human readability but is inherently fragile due to its reliance on indentation and data typing ambiguity. On the other hand, JSON, preferred by machines for its strict structure, lacks support for comments and forces a monolithic object definition, making it difficult to maintain in complex environments managed by tools like Helm or Kustomize.

With the arrival of Kubernetes 1.35, a solution that unifies the best features of both formats is consolidated: KYAML.

What is KYAML?

KYAML is not a new language, but the standardized adoption of YAML’s flow style. Its syntax is characterized by the explicit use of delimiters:

  • Objects: Encapsulated in curly braces {}.
  • Arrays: Defined using brackets [].
  • Typing: Requires that all string values be delimited by double quotes ("").

This approach eliminates parsing ambiguity without sacrificing developer ergonomics.

Technical and Operational Benefits

Adopting KYAML directly impacts the stability of CI/CD pipelines and the developer experience (DevEx):

  1. Structural Integrity: By using delimited blocks ({} and []), the manifest becomes immune to indentation errors. Logical structure prevails over visual structure, eliminating critical failures caused by stray whitespace during copy-paste operations.
  2. Documentation Capability: Unlike JSON, KYAML retains YAML’s ability to include comments (#). This is vital for documenting infrastructure decisions (e.g., requests/limits, magic numbers) directly in the code.
  3. Type Safety: The requirement for quotes for strings mitigates implicit type coercion errors (like the well-known case of the country code “NO” interpreted as boolean false in YAML 1.1).

Maturity and Adoption State

The transition to KYAML is designed to be transparent and low-friction:

  • Backward Compatibility: kubectl processes KYAML natively, as it complies with the existing YAML specification.
  • No Extension Changes: Files maintain the .yaml extension, facilitating integration with current linting and validation tools.
  • Native Support in v1.35: Kubernetes 1.35 introduces explicit support in the CLI. It is now possible to serialize existing objects to the new format using kubectl ... -o kyaml.
  • IDE Support: Modern editors like VSCode or Cursor interpret the syntax correctly, although visual differentiation (syntax highlighting) between keys and values still has room for improvement in the extension ecosystem.

Practical Implementation: YAML vs. KYAML

Below, we contrast the definition of a Deployment object in both formats. These examples are available in the reference repository erase-una-vez-k8s/encodings.

Classic Format (Block Style)

Dependent on indentation and verticality:

# manifest fragment in YAML format (Block Style)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: erase-una-vez-2-prod
  labels:
    app: erase-una-vez-2
    env: prod
    tier: frontend
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 25%
  selector:
    matchLabels:
      app: erase-una-vez-2
  template:
    metadata:
      labels:
        app: erase-una-vez-2
    spec:
      containers:
      - name: server
        image: ghcr.io/mmorejon/erase-una-vez-2:v0.5.0

        ports:
        - containerPort: 8000
          name: http

        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 256Mi

KYAML Format (Flow Style)

Structured, compact, and with explicit typing:

# manifest fragment in KYAML format (Flow Style)
apiVersion: "apps/v1"
kind: "Deployment"
metadata: {
  name: "erase-una-vez-2-prod",
  labels: { app: "erase-una-vez-2", env: "prod", tier: "frontend" }
}
spec: {
  replicas: 3,
  strategy: {
    type: "RollingUpdate",
    rollingUpdate: { maxUnavailable: 1, maxSurge: "25%" }
  },
  selector: {
    matchLabels: { app: "erase-una-vez-2" }
  },
  template: {
    metadata: {
      labels: { app: "erase-una-vez-2" }
    },
    spec: {
      containers: [
        {
          name: "server",
          image: "ghcr.io/mmorejon/erase-una-vez-2:v0.5.0",

          ports: [{ containerPort: 8000, name: "http" }],
          resources: {
            requests: { cpu: "100m", memory: "128Mi" },
            limits:   { cpu: "500m", memory: "256Mi" }
          }
        }
      ]
    }
  }
}

KYAML in Practice

First, you need a cluster with version 1.35. You can use the erase-una-vez-k8s repository to spin up a compatible local cluster in seconds (approximately 40 seconds).

git clone https://github.com/mmorejon/erase-una-vez-k8s.git
cd erase-una-vez-k8s
./bash/cluster.sh create

Ensure you are using version 1.35 of kubectl:

kubectl version --client

Client Version: v1.35.0
Kustomize Version: v5.7.1

Once you have the cluster, send the KYAML format manifest to your cluster:

kubectl apply --filename https://raw.githubusercontent.com/mmorejon/erase-una-vez-k8s/refs/heads/main/encodings/kyaml/deployment.yaml

deployment.apps/erase-una-vez-2-prod created

Verify that the deployment has been created correctly:

kubectl get deployment erase-una-vez-2-prod

NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
erase-una-vez-2-prod   3/3     3            3           21s

Take this opportunity to export the manifest in KYAML format:

kubectl get deployment erase-una-vez-2-prod -o kyaml

KYAML represents the next logical step in the maturity of Kubernetes configuration: the precision machines demand with the flexibility humans need.

comments powered by Disqus