[toc]
YAML 语法与 k8s 资源清单
YAML(YAML Ain't Markup Language)是一种人性化的数据序列化语言,Kubernetes 的资源清单(Manifest)约定使用 YAML 编写。本文从 YAML 语法基础讲起,再到 k8s 资源清单的结构与实战,帮助你彻底看懂并手写 k8s 的各种 YAML 文件。
官方文档参考
| 文档 | 链接 |
|---|---|
| 理解 Kubernetes 对象(Objects In Kubernetes,四大必需字段出处) | https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/ |
| Kubernetes API 参考(各资源 spec 字段权威定义) | https://kubernetes.io/docs/reference/kubernetes-api/ |
| YAML 官网(当前规范为 YAML 1.2.2) | https://yaml.org/ |
| yamllint 在线校验(检查 YAML 合法性) | http://www.yamllint.com/ |
1. YAML 语法规则
YAML 的基本语法规则:
- 大小写敏感
- 使用缩进表示层级关系
- 缩进时不允许使用 Tab 键,只允许使用空格
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
#表示注释,从这个字符一直到行尾,都会被解析器忽略

Tab 字符是 YAML 解析错误最常见的来源,编辑器请配置「Tab 键自动转换为空格」。
1.1 文档结构与多文档分隔
第一行的 --- 是文档分隔符(可选),在单一文件中可用连续三个连字号 --- 区分多个文档。k8s 中经常在一个 yaml 文件里写多个资源:
---
apiVersion: v1
kind: Service
metadata:
name: my-svc
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deploy
kubectl apply -f 处理这种多文档文件时会把每个资源都创建出来,这是 k8s 管理 ConfigMap + Deployment + Service 组合的常见做法。
1.2 Maps(映射)
Map 是字典,就是一个 key: value 的键值对(注意冒号后面必须有一个空格),Maps 可以多层嵌套:
---
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
上面的 YAML 文件转换成 JSON 格式的话,就非常容易理解了——metadata 这个 KEY 对应的值是一个 Map,嵌套的 labels 的值又是一个 Map:
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "kube100-site",
"labels": { "app": "web" }
}
}
YAML 处理器根据行缩进判断内容之间的关联性:name 和 labels 缩进相同,属于同一个 Map;app 缩进更深,所以是 labels 的值。空格数量不重要(1 个或 2 个都行),但同一层级必须一致。
1.3 Lists(列表)
List 就是数组,每个项以破折号(-)开头:
args:
- Cat
- Dog
- Fish
对应的 JSON 格式:
{ "args": ["Cat", "Dog", "Fish"] }
- 与键名之间要有冒号列表必须挂在某个键下面,写成 args:(有冒号)再换行缩进写 - Cat;直接写 args 换行是错误语法。
1.4 Maps 与 Lists 嵌套
List 的子项可以是 Maps,Map 的值也可以是 Lists——k8s 资源清单就是这两种结构无限嵌套出来的:

一个典型的 Pod 清单,containers 是一个 List,每个子项是由 name、image、ports 组成的 Map,ports 的值又是一个 List:
---
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: flaskapp-demo
image: jcdemo/flaskapp
ports:
- containerPort: 5000
转换成 JSON 后结构完全等价,但明显比 YAML 冗长——这正是 k8s 选择 YAML 的原因:语义清晰、便于手写和 review。
1.5 标量类型与隐式转换
key: value 中的 value 不写引号时,YAML 会自动推断类型,这是 k8s YAML 的经典坑来源:
| 写法 | 解析结果 | 说明 |
|---|---|---|
name: web | 字符串 web | 普通文本直接写 |
version: 1.37 | 浮 点数 1.37 | 数字会被转成 number! |
version: "1.37" | 字符串 "1.37" | 想要字符串必须加引号 |
enabled: true | 布尔 true | true/false 是保留字 |
value: null | 空值 | null/~/留空都是空值 |
replicas: 2 | 整数 2 | k8s 中副本数就该是数字 |
- 值以数字开头但语义是字符串:
version: "1.37"(不加引号会被解析成浮点数) - 值包含特殊字符(冒号、
#、{}等):command: "sh -c 'echo hi'" - YAML 1.1 解析器中
yes/no/on/off也会被转成布尔,写布尔时统一用true/false最安全
多行字符串在写 ConfigMap 内嵌脚本时非常常用:
# | 保留换行(每一行原样保留,最常用)
entrypoint.sh: |
#!/bin/sh
echo "hello"
nginx -g "daemon off;"
# > 折叠换行(所有行折叠成一行,用空格连接)
description: >
这是一段很长的描述文字
会被折叠成一行
1.6 锚点与引用(复用配置)
YAML 支持 & 定义锚点、* 引用锚点,避免重复配置:
resources: &default-resources
requests:
cpu: 100m
memory: 128Mi
sidecar:
<<: *default-resources # << 合并键:把锚点内容合并进来
limits:
cpu: 200m
sidecar 最终会拥有 requests(来自锚点合并)和自己的 limits。这在 Helm values、CI 配置里很常见;k8s 官方清单中较少用,但看懂别人写的 YAML 需要掌握它。