11 Aug 2026
Kubernetes Blog
How to Pretty-Print Your Kubernetes YAML as KYAML and Why You'd Want To
YAML has been the standard way to write Kubernetes manifests for years. Every example, tutorial, and configuration file you come across is written in it. The problem isn't that YAML is a bad format. It's that YAML gives you a lot of choices, and not all of them are equally good for writing Kubernetes manifests. Some features make files harder to read, some are easy to misuse and others can lead to surprising behavior.
The interesting part is that Kubernetes doesn't actually need most of those features. It only relies on a small subset of YAML. This led to a simple question: if Kubernetes only needs a small part of YAML, why not standardize on that part and avoid the rest? Instead of introducing a new configuration language, SIG CLI introduced KYAML, a stricter, more consistent way to write YAML.
What is KYAML?
KYAML is a strict subset (or "dialect") of standard YAML, designed to be parseable by the existing ecosystem without any changes, as proposed in KEP 5295. It does not introduce a new format or a new parser. It just narrows the scope of choices you make when writing YAML, so everyone ends up making the same ones.
Think of it less like a new language and more like an agreed-upon style. Everything valid in KYAML is valid YAML.
How KYAML solves it
Standard YAML has a few well-known traps and JSON is not without its own.
Whitespace sensitivity. Indentation defines structure in YAML, which means a wrongly indented file can remain syntactically valid while representing a different object than intended. This gets especially painful with templating tools like Helm, where you are manipulating indentation from outside the YAML context.
Silent type coercion. String quoting is optional in YAML, which sounds convenient until it is not. Some values that look like strings get coerced into other types without warning. The classic example is the "Norway Bug".
country: NO
In standard YAML, NO is parsed as a boolean false, not the string "NO" and it has caught more than a few people off guard.
JSON is not the answer either. It lacks comment support, is strict about trailing commas, and requires every key to be quoted, none of which makes for a good config writing experience.
KYAML addresses all of these by making structure and types explicit:
- Does not depend on whitespace for structure
- Always quotes value strings so no silent type coercion
- Always uses
{}for maps and structs - Always uses
[]for lists - Allows comments and trailing commas, unlike JSON
- Includes a
---header to distinguish it from JSON at a glance, since both start with{
YAML calls this flow style, as opposed to the conventional block style most people use. KYAML sits halfway between JSON and YAML, more explicit than default YAML, friendlier than JSON.
Here is the same Pod manifest written in both formats for comparison.
Standard YAML
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: demo
spec:
containers:
- name: nginx
image: nginx:1.20
KYAML
---
{
apiVersion: "v1",
kind: "Pod",
metadata: {
name: "my-pod",
labels: {
app: "demo",
},
},
spec: {
containers: [{
name: "nginx",
image: "nginx:1.20",
}],
},
}
Notice the double-quoted string values, the braces around every mapping, the brackets around the list and the trailing commas. The additional syntax makes the document structure explicit instead of relying on indentation.
How to pretty print YAML as KYAML
There are different ways to get KYAML output.
Option 1: kubectl -o kyaml
Since Kubernetes 1.34, kubectl supports KYAML as a native output format.
# Kubernetes 1.35+ (beta; feature enabled by default, still requires -o kyaml CLI param)
kubectl get deployment my-app -o kyaml
# Kubernetes 1.34 (alpha, opt-in)
export KUBECTL_KYAML=true
kubectl get deployment my-app -o kyaml
To save the output to a file:
kubectl get deployment my-app -o kyaml > my-app.yaml
There are currently no plans to make KYAML the default output format. If you prefer using KYAML by default, you can configure your preferred default with kuberc. For more details, see the kuberc documentation.
# Kubernetes 1.36+
kubectl kuberc set --section defaults --command get --option output=kyaml
# Kubernetes 1.33-1.35 (alpha prefix still required)
kubectl alpha kuberc set --section defaults --command get --option output=kyaml
Option 2: Kubernetes' yamlfmt
sigs.k8s.io/yaml ships a yamlfmt tool that can convert files to KYAML.
Install via Go:
go install sigs.k8s.io/yaml/yamlfmt@latest
Running it against a file prints the KYAML version to stdout. It also accepts a directory, in which case it converts and prints every file in that directory. So you'll need to redirect the output to a file (or files) if you want the conversion to stick.
yamlfmt -o=kyaml my-deployment.yaml
It can also show you a diff instead of a full conversion:
yamlfmt -o=kyaml -d my-deployment.yaml
Option 3: Google's yamlfmt
For converting existing files, Google's yamlfmt added a dedicated kyaml formatter in v0.21.0.
Install via Go, or grab a binary from the releases page:
go install github.com/google/yamlfmt/cmd/yamlfmt@latest
It is also available as a pre-commit hook and as a Docker image for CI pipelines.
Add a .yamlfmt config to your project root:
formatter:
type: kyaml
Preview the output without modifying your file:
yamlfmt -dry my-deployment.yaml
then apply:
yamlfmt my-deployment.yaml
To convert an entire directory:
yamlfmt ./k8s/
The kyaml formatter takes no additional configuration and does not share options with the default formatter so mixing them will cause an error.
For more on the available modes and flags, check the command usage docs.
Is KYAML worth adopting?
Every valid KYAML file is a valid YAML file. So whatever you write in KYAML, your existing tools, your kubectl, your CI pipelines, none of them need to change. You can even pass KYAML as input to any version of kubectl, not just 1.34+, because at the end of the day it is just YAML.
KYAML is not strictly necessary. You can keep writing block-style YAML and things will work. But it is a deliberate choice to make your configs less error-prone and more consistent especially across a team or a larger repo.
It is less of a migration and more of a better habit.
11 Aug 2026 6:00pm GMT
03 Aug 2026
Kubernetes Blog
Gateway API v1.6: TCPRoute and UDPRoute Graduate to Standard
The Kubernetes SIG Network community is thrilled to share the release of Gateway API v1.6.0, which was released on June 30th of this year!
Gateway API has become the standard for modern, role-oriented, and expressive service networking in Kubernetes. In previous releases, Gateway API established a production-grade foundation for HTTP and TLS layer 7 traffic. With version 1.6.0, Gateway API takes a major step forward by expanding standard layer 4 protocol routing and introducing cleaner API boundaries for experimental innovation.
Here is a quick summary of what's new in Gateway API v1.6.0:
- TCPRoute and UDPRoute Graduate to Standard: Raw L4 TCP and UDP traffic routing reach GA stability in the
v1API version. - Experimental API Group Separation: Experimental resources transition to a distinct API group (
gateway.networking.x-k8s.io) with anXprefix to make experimental vs. standard boundaries crystal clear.
Let's dive into the details!
TCPRoute and UDPRoute graduate to Standard
Leads: Nick Young, Ricardo Katz and Zac Nixon
Until now, Gateway API only offered a stable routing model for HTTP and TLS traffic. Workloads that speak a raw protocol over TCP or UDP - databases, DNS, VoIP, gaming, IoT telemetry - had no portable way to plug into a Gateway. Users either fell back to a plain Kubernetes Service, or to an implementation-specific CRD that doesn't travel between Gateway controllers.
TCPRoute and UDPRoute close that gap: they route traffic to backends based on protocol and port alone, no L7 awareness required. With this release, both have graduated from the Experimental channel to Standard, and moved to the v1 API version. The v1alpha2 version of each was deprecated as of the v1.6 release, and will be removed in a future release.
How it works
A Gateway needs a listener that allows TCPRoute attachment:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-gateway
spec:
gatewayClassName: example-gateway-class
listeners:
- name: foo
protocol: TCP
port: 12345
allowedRoutes:
kinds:
- kind: TCPRoute
A TCPRoute then attaches to that listener and forwards traffic to a backend:
apiVersion: gateway.networking.k8s.io/v1
kind: TCPRoute
metadata:
name: tcp-app
spec:
parentRefs:
- name: example-gateway
sectionName: foo
rules:
- backendRefs:
- name: my-foo-service
port: 6000
Traffic arriving on the Gateway's port 12345 is proxied to the endpoints of my-foo-service on port 6000. Omitting sectionName and port from parentRefs attaches the route to every TCP listener on the Gateway instead of a single one.
UDPRoute follows the same pattern; swap the listener protocol and the route kind:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-gateway
spec:
gatewayClassName: example-gateway-class
listeners:
- name: foo
protocol: UDP
port: 12345
allowedRoutes:
kinds:
- kind: UDPRoute
---
apiVersion: gateway.networking.k8s.io/v1
kind: UDPRoute
metadata:
name: udp-app
spec:
parentRefs:
- name: example-gateway
sectionName: foo
rules:
- backendRefs:
- name: my-foo-service
port: 6000
XBackend arrives in Experimental
Leads: Keith Mattix II
Gateway API v1.6 introduces the new XBackend resource, which is a general-purpose decorator for Service (and other backend types) within Gateway API.
The Service resource is an amazing, stable, and flexible object, but that comes with some costs: The flexibility creates a lot of edge cases that Gateway API needs to handle, and the stability makes it impossible to add new concepts to Service.
The XBackend resource builds on the ideas in the upstream EndpointSelector KEP, to add a Gateway API-native object that still targets the backend app, while allowing the community to extend it to handle use cases that are difficult or dangerous to handle with Service.
The first version of XBackend includes support for ExternalHostname destinations, which are ruled out from Service support in Gateway API because of the possibility of confused deputy attacks.
For XBackend, this support is an Extended/Optional feature, allowing implementations and users to opt in once they understand the security tradeoffs.
This support is very useful for egress use cases (which are most commonly used for cluster-hosted agentic workloads), which the community is also working towards formalizing in GEPs about Gateways for Egress (work in progress, stay tuned!)
The XBackend API is experimental and its behavior can change, do not assume it is ready for production
An example of a Gateway with an ExternalName backend that can be used for egress to a cloud AI API is as follows:
# Gateway-level TLS remains authoritative for incoming connections
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
spec:
listeners:
- name: https
protocol: HTTPS
tls:
certificateRefs:
- name: gateway-cert
---
# Backend resource for external destination
apiVersion: gateway.networking.x-k8s.io/v1alpha1
kind: XBackend
metadata:
name: ai-provider-api
namespace: ai-apps
spec:
type: ExternalHostname
externalHostname:
hostname: api.ai-provider.com
---
# HTTPRoute referencing XBackend
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
spec:
rules:
- backendRefs:
- name: ai-provider-api
kind: XBackend
group: gateway.networking.x-k8s.io
The community is also working on moving Session Persistence config from XBackendTrafficPolicy into XBackend, along with other use cases like retries, TLS origination and similar config that is useful to be able to configure per-application rather than per-Route.
Experimental resources move off the standard API group
Previously, experimental resources shared the same API group as standard ones - gateway.networking.k8s.io - distinguished only by a v1alpha2-style version. TCPRoute and UDPRoute were the last resources to graduate under that scheme.
Going forward, new experimental resources are defined in a separate group, gateway.networking.x-k8s.io, and the names of their API types get an X prefix - for example XBackend and XMesh. When one of these graduates to Standard, it's renamed into the gateway.networking.k8s.io group and drops the X prefix, the same way XMesh is expected to become Mesh.
This separation makes the experimental/standard boundary explicit at the API group level, rather than relying on version strings alone.
What's next & getting involved
The graduation of TCPRoute and UDPRoute to Standard marks an essential milestone in making Gateway API a complete, universal ingress and mesh networking API for Kubernetes workloads across layer 4 and layer 7 protocols.
Try it out
You can start using Gateway API v1.6.0 today with your favorite Gateway controller implementation:
- Check out the Gateway API Documentation for detailed guides and API references.
- View the v1.6.0 Release Notes for complete details on the CRD installation and changes.
Gateway API relies on an extensive conformance test suite to ensure consistent, portable behavior across all implementations. Here is a list of the implementations that are conforment with v1.6 on the day we published the article:
Get involved
Gateway API is an open, community-driven project built under Kubernetes SIG Network. We welcome contributions, feedback, and participation from everyone!
- Join our Slack Channel: Join
#sig-network-gateway-apion the Kubernetes Slack. - Attend Community Meetings: We hold weekly community meetings. Check out the SIG Network Calendar for dates and agendas.
- Contribute on GitHub: File issues, suggest enhancements (GEPs), or submit PRs at kubernetes-sigs/gateway-api.
Acknowledgments
A huge thank you to all the contributors, reviewers, maintainers, and implementation authors whose hard work made Gateway API v1.6.0 possible!
03 Aug 2026 4:00pm GMT
31 Jul 2026
Kubernetes Blog
Kubernetes v1.37 Sneak Peek
As we get closer to the release date for Kubernetes v1.37, the project develops and matures, features may be deprecated, removed, or replaced with better ones for the project's overall health. This blog outlines some of the planned changes for the Kubernetes v1.37 release that the release team feels you should be aware of for the continued maintenance of your Kubernetes environment and keeping up to date with the latest changes. The information below reflects the current status of the v1.37 release and may change before the actual release date.
Deprecations and removals for Kubernetes v1.37
Kubectl: kubectl run --filename/-f to be deprecated
The --filename (or -f) flag for kubectl run is being deprecated as the generated pod is always built purely from CLI arguments like NAME and --image.
See kubernetes/kubernetes#138671 for the original issue and discussion.
Kubelet: Static Pods can no longer reference Secrets or ConfigMaps
Static Pods were never meant to read API resources directly, since they aren't created through the API server - but a bug let them reference Secrets or ConfigMaps via fields like configMapRef or secretRef. That bug is now fixed: as of v1.37 these references are strictly prohibited, and the PreventStaticPodAPIReferences feature gate that previously let you opt out of the restriction has been removed.
See kubernetes/kubernetes#140226 for the original issue and discussion.
Deprecating kube-proxy's support for ipvs mode
kube-proxy support for ipvs mode was introduced in v1.8 to resolve iptables performance bottlenecks. However, since the kernel ipvs API alone cannot fully implement Kubernetes Services, ipvs mode continues to use iptables underneath (KEP-3866, "The ipvs mode of kube-proxy will not save us").
Clusters running kube-proxy in ipvs mode (or mode: ipvs in KubeProxyConfiguration) would now be logging a deprecation warning on startup. The deprecation timeline looks like this:
- By v1.40,
ipvsmode forkube-proxyis expected to be disabled by default (still selectable via the feature gate) - By v1.43, support for
ipvsmode would be removed entirely KEP-5495, Graduation Criteria. To confirm which mode you're currently running, use:
kubectl -n kube-system get configmap kube-proxy -o jsonpath='{.data.config\.conf}' | grep 'mode:'
To understand the rationale behind this deprecation, see KEP-5495: Deprecate ipvs mode in kube-proxy.
Ongoing major changes
Future removal of cgroup v1 support
As modern Linux distributions and container runtimes use cgroup v2 as the default, support for the legacy cgroup v1 is officially being phased out. Since the v1.35 release, the failCgroupV1 setting has defaulted to true. Consequently, the kubelet will fail to initialize on any nodes that still rely on cgroup v1 unless an explicit configuration override is applied.
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
failCgroupV1: false # temporary override
Using this override should be considered a short-term fix. Advanced resource management capabilities, such as In-Place Pod Resizing and Tiered Memory Protection, depend entirely on cgroup v2. While the override remains available in Kubernetes v1.37, users are encouraged to migrate to cgroup v2, as support for cgroup v1 is planned to be removed in a future release.
To learn more about this deprecation, refer to KEP-5573: Remove cgroup v1 support.
Breaking changes in Kubernetes v1.37
SELinux volume relabeling ("SELinuxMount") graduates to GA
SELinuxMount is expected to reach GA and be enabled by default in v1.37. Volumes would then be mounted with -o context=<label> (the mount option default) instead of being recursively relabeled, but only when the volume's CSI driver opts in via a CSIDriver that sets .spec seLinuxMount: true.
Because a single mount can only hold one SELinux context, pods with different SELinux labels sharing a volume on the same node (which previously coexisted under recursive relabeling) may now fail to start. To retain the previous recursive behavior for a specific workload, set seLinuxChangePolicy: Recursive in the Pod spec.
Clusters without SELinux enabled see no effect at all. To learn more, check SELinux Volume Label Changes goes GA (and likely implications in v1.37)
Featured enhancements of Kubernetes v1.37
Metrics API goes GA
The metrics.k8s.io API is expected to graduate to Stable (GA) in Kubernetes v1.37 after spending nearly nine years in Beta. The API provides a standard way to retrieve CPU and memory usage for pods and nodes, powering widely used Kubernetes features such as the Horizontal Pod Autoscaler (HPA) and commands like kubectl top.
This graduation recognizes the API's stability and widespread adoption, with no functional changes expected. Both v1 and v1beta1 will remain usable during the transition, enabling developers to adopt the stable API at their own pace without breaking existing workflows.
To learn more about this enhancement, refer to KEP-5207: metrics.k8s.io API definition.
Kubelet in UserNS a.k.a. Rootless Mode
Traditionally, Kubernetes node components such as the kubelet run with root privileges on the host. While necessary for many deployments, this also means that a vulnerability in one of these components could potentially have a greater impact on the underlying system.
With Kubernetes v1.37, kubelet in User Namespace (Rootless Mode) is expected to graduate to Beta. This enhancement allows Kubernetes node components to run inside a Linux user namespace as an unprivileged user on the host while still behaving as root within the namespace. By reducing the need for host-level root privileges, it adds an extra layer of isolation and helps limit the impact of potential vulnerabilities affecting node components.
To learn more about this enhancement, refer to KEP-2033: Kubelet in UserNS(aka Rootless Mode).
Volume health monitor
Historically, Kubernetes has lacked an API for CSI drivers to report storage failures, which become evident only through failed mounts or hung I/O. Since remediation controllers had nothing machine-readable to act upon, the only way to figure out the root cause behind this failure was to cross-reference Kubernetes objects alongside external vendor dashboards.
In Kubernetes v1.37, this KEP resets graduation to Alpha after an initial implementation in v1.21 and introduces four new CSI RPCs. The controller plugin reports the health of storage volumes using ControllerListVolumeHealth (lists unhealthy volumes) and ControllerGetVolumeHealth (checks a specific volume). A controller-side health monitor polls these CSI controllers and stores the results in PersistentVolumeClaim.status.healthStatus.
On the node side, the kubelet calls NodeGetVolumeHealth to obtain the health of individual volumes on that node and records it in Pod.status.volumeHealth, while NodeGetStorageHealth reports the health of the drivers registered to a node in CSINode.status.storageHealth.
The error vocabulary is kept simple, extensible, and machine-parsable (Inaccessible, Degraded, etc.), with further driver-specific elaboration available via reason and message. Finally, the controller-side and node-side reports are kept independent and are hence displayed separately, providing a more holistic view of storage health to consumers.
To learn more about this enhancement, refer to KEP-1432: Volume Health Monitor.
Want to know more?
New features and deprecations are also announced in the Kubernetes release notes. We will formally announce what's new in Kubernetes v1.37 as part of the CHANGELOG for that release.
Kubernetes v1.37 release is planned for Wednesday, August 26th, 2026. Stay tuned for updates!
You can see the announcements of changes in the release notes for:
Get involved
The simplest way to get involved with Kubernetes is by joining one of the many Special Interest Groups (SIGs) that align with your interests.
If you don't know where to start, join our monthly New Contributor Orientations where we teach the community how the project is structured, and we'll guide you on how to make your first contribution to the project.
- Read more on how to become a Kubernetes Contributor
- Read more about what's happening with Kubernetes on our blog
- Join us on Slack
- Follow us on X
- Follow us on LinkedIn
- Follow us on Bluesky for the latest updates
- Join the community discussion on Discuss
- Post questions (or answer questions) on Stack Overflow
- Share your Kubernetes End User Story
- Learn more about the Kubernetes Release Team
31 Jul 2026 4:00pm GMT