YAML vs HCL 格式对比
YAML是通用数据序列化格式,HCL 是为”声明式基础设施配置”设计的专用语言。YAML 只能存数据,HCL 还能写逻辑。
核心差异
| 维度 | YAML | HCL |
|---|---|---|
| 设计目的 | 数据序列化(通用数据格式) | 基础设施即代码(专用配置语言) |
| 提出方 | YAML 1.1/1.2 规范(YAML Ain’t Markup Language) | HashiCorp(Terraform/Vault/Nomad/Consul) |
| 本质 | 是 JSON 的超集(YAML 1.2),纯数据 | 类 Lisp/Python 风格,数据 + 表达式 + 控制流 |
| 表达式 | 无(纯值,只能存字面量) | 支持 + - * /、比较、字符串插值 ${var.x}、函数调用 |
| 控制流 | 无 | for 循环、if/else 条件块 |
| 变量引用 | 靠锚点 &/*(极少用,容易坑) |
var.、local.、module. 显式命名空间 |
| 校验 | 无 schema 概念(可用 JSON Schema 事后校验) | 原生 schema(Terraform 的 terraform validate、类型推断) |
| 多文档 | --- 分隔多个文档 |
无(单文件单上下文,靠 import/module 组织) |
| 生态 | 几乎所有语言、k8s/CI/CD 标配 | HashiCorp 系:Terraform、Vault、Nomad、Consul、Boundary、Waypoint |
语法对比
同一件事:建 3 台 2C4G 服务器
YAML(纯数据,只能”写”,不能”算”):
1 | servers: |
HCL(可以写逻辑,一次生成 N 台):
1 | locals { |
注意 HCL 里出现的、YAML 完全做不到的东西:
for循环展开资源each.key迭代变量local/var命名空间- 字符串插值
"web-${i + 1}"
优缺点
YAML
优点
- 人可读、写起来最省字符(相比 JSON)
- 全语言生态通吃,CI/CD 和 k8s 的事实标准
- 工具链最成熟(kubectl、yamllint、kubeval)
缺点(生产环境踩过无数坑)
| 坑 | 示例 |
|---|---|
| 缩进即语法 | 差一个空格直接报错或语义改变 |
| 数字歧义 | port: 80 是 int,写成 port: "80" 才安全;1.10 被解析成 1.1 |
| 日期/布尔坑 | on: true 在 YAML 1.1 里 on 本身是布尔 true(CI 里 on: push 曾引发无数 bug) |
| 重复键 | 后者静默覆盖前者,不报错 |
| 无表达式 | 想写”如果 prod 环境加标签”做不到,必须靠外部模板(Jinja2) |
| 多文档难维护 | 一个文件几百行 k8s 资源,改一处影响全局 |
HCL
优点
- 声明 + 逻辑一体:循环、条件、表达式内置,不用外挂模板引擎
- 强校验:
terraform validate / plan能在执行前发现 90% 错误 - 块嵌套天然表达”资源包含配置”,比 YAML 缩进层级少一层(少一级缩进地狱)
- 状态管理(Terraform 的 state)保证幂等
缺点
- 生态封闭:离开 HashiCorp 生态基本没人用,团队要专门学
- 无多文档概念,大项目得靠 module 拆分组织
- 渲染/导出工具不如 YAML 普及
- 语法对新手有点陌生(
for_each表达式、each.元组)