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
2
3
4
5
6
7
8
9
10
servers:
- name: web-1
cpu: 2
mem: 4
- name: web-2
cpu: 2
mem: 4
- name: web-3
cpu: 2
mem: 4 # 三台机器只能复制三遍,没法循环

HCL(可以写逻辑,一次生成 N 台):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
locals {
count = 3
size = { cpu = 2, mem = 4 }
}

resource "server" "web" {
for_each = toset([for i in range(local.count) : "web-${i + 1}"])

name = each.key
cpu = local.size.cpu
mem = local.size.mem

tags = {
env = var.env
owner = "sre-team"
}
}

注意 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. 元组)