多年来,YAML 一直是 Kubernetes 清单的标准写法。你遇到的示例、教程和配置文件几乎都采用它。问题并不是 YAML 格式不好,而是它提供了很多选择,其中并非每一种都适合编写 Kubernetes 清单。有些特性让文件难读,有些容易误用,还有些会导致意外行为。
有意思的是,Kubernetes 实际上并不需要其中大部分特性,它只依赖 YAML 的一个小子集。于是出现了一个简单问题:既然 Kubernetes 只需要一部分 YAML,为什么不统一采用这一部分,并避开其余特性?SIG CLI 没有引入新的配置语言,而是推出了 KYAML,一种更严格、更一致的 YAML 写法。
KYAML 是什么?
根据 KEP 5295,KYAML 是标准 YAML 的严格子集(或称“方言”),现有生态无需修改即可解析。它没有引入新的格式或解析器,只是缩小了编写 YAML 时可作出的选择,使大家采用一致的写法。
与其把它视为新语言,不如把它看作约定好的风格。所有有效的 KYAML 都是有效的 YAML。
KYAML 如何解决问题
标准 YAML 存在一些熟知的陷阱,JSON 也有自己的问题。
对空白敏感。 YAML 用缩进定义结构。这意味着缩进错误的文件可能仍然语法正确,却表达了另一个对象。在 Helm 等模板工具中,问题尤其明显,因为你是在 YAML 上下文之外处理缩进。
静默类型转换。 YAML 中字符串的引号是可选的,看似方便,但有些看起来像字符串的值会被悄悄转换为其他类型。经典例子是“挪威问题”:
country: NO
原文指出,标准 YAML 会将 NO 解析为布尔值 false,而非字符串 "NO"。这个行为让不少人感到意外。
JSON 也不是答案。 它不支持注释,对尾随逗号有严格限制,还要求所有键加上引号,这些都不利于手写配置。
KYAML 通过显式表达结构与类型处理这些问题:
- 不依赖空白表示结构。
- 字符串值始终加引号,避免静默类型转换。
- 映射和结构体始终使用
{}。 - 列表始终使用
[]。 - 允许注释和尾随逗号,与 JSON 不同。
- 包含
---文件头,使它与同样以{开头的 JSON 一眼可辨。
YAML 将这种写法称为流式风格(flow style),与多数人采用的块式风格(block style)相对。KYAML 介于 JSON 与 YAML 之间,比默认 YAML 更明确,比 JSON 更方便。
下面对比同一份 Pod 清单的两种写法。
标准 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",
}],
},
}
注意字符串值的双引号、每个映射外面的花括号、列表外面的方括号,以及尾随逗号。额外的语法让结构变得明确,不再依赖缩进。
如何将 YAML 格式化输出为 KYAML
可以通过几种方式得到 KYAML 输出。
方式一:kubectl -o kyaml
从 Kubernetes 1.34 开始,kubectl 原生支持 KYAML 输出格式。
# 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
将输出保存到文件:
kubectl get deployment my-app -o kyaml > my-app.yaml
目前没有将 KYAML 设为默认输出格式的计划。如果你希望默认使用 KYAML,可以通过 kuberc 设置个人默认选项。详情参见 kuberc 文档。
# 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
方式二:Kubernetes 的 yamlfmt
sigs.k8s.io/yaml 提供了 yamlfmt 工具,可将文件转换为 KYAML。
通过 Go 安装:
go install sigs.k8s.io/yaml/yamlfmt@latest
针对文件运行时,它将 KYAML 版本打印到标准输出(stdout)。它也接受目录参数,此时会转换并打印目录中的每个文件。因此,如果希望保存转换结果,需要将输出重定向到一个或多个文件。
yamlfmt -o=kyaml my-deployment.yaml
也可以仅查看差异,而不输出完整转换结果:
yamlfmt -o=kyaml -d my-deployment.yaml
方式三:Google 的 yamlfmt
Google 的 yamlfmt 在 v0.21.0 加入了专用的 kyaml 格式化器,可以转换现有文件。
通过 Go 安装,或从发行页面获取二进制文件:
go install github.com/google/yamlfmt/cmd/yamlfmt@latest
它也提供 pre-commit 钩子和用于 CI 流水线的 Docker 镜像。
在项目根目录添加 .yamlfmt 配置:
formatter:
type: kyaml
预览输出,不修改文件:
yamlfmt -dry my-deployment.yaml
然后应用:
yamlfmt my-deployment.yaml
转换整个目录:
yamlfmt ./k8s/
kyaml 格式化器不接受额外配置,也不与默认格式化器共享选项,混用会引发错误。
可用模式与参数参见命令用法文档。
值得采用 KYAML 吗?
每一份有效的 KYAML 文件都是有效的 YAML。因此,不论你写什么 KYAML,现有工具、kubectl 和 CI 流水线都不需要改变。甚至任意版本的 kubectl 都可以将 KYAML 作为输入,而不限于 1.34 及以上,因为它归根结底就是 YAML。
KYAML 并不是必需的。继续编写块式 YAML 也能正常工作。不过,它是一种有意识的选择,能让配置更一致、更不容易出错,尤其适用于团队或较大的仓库。
这与其说是一场迁移,不如说是养成更好的习惯。
来源与许可
原文:How to Pretty-Print Your Kubernetes YAML as KYAML and Why You’d Want To。作者:Kashish Verma;发表日期:2026-08-11。Kubernetes 网站内容采用 CC BY 4.0 授权。本文为中文翻译,保留原文代码与版本范围,并整理标题、链接与重点标记。
译者补充:此处 NO 被解析为布尔值,指 YAML 1.1 的布尔类型解析规则,不应推广为所有 YAML 版本与解析器的行为。示例中的 nginx:1.20 为原文示例版本。











暂无评论内容