什么是 YAML?
YAML(YAML Ain't Markup Language)是一种人类可读的数据序列化格式,常用于配置文件和数据交换。它的设计目标是易于人类阅读和编写,同时便于机器解析和生成。
YAML 的主要特点
- 可读性强:使用缩进和简洁的语法
- 跨语言:支持多种编程语言
- 表达能力丰富:支持复杂数据结构
- 扩展性好:支持自定义数据类型
使用场景
1. 配置文件
- 应用配置:Web 应用、数据库连接配置
- CI/CD 管道:GitLab CI、GitHub Actions
- 容器编排:Docker Compose、Kubernetes
- 构建工具:Travis CI、CircleCI
2. 数据序列化
- API 数据交换
- 测试数据
- 数据迁移脚本
3. 基础设施即代码
- Ansible Playbooks
- Terraform 配置
- CloudFormation 模板
如何执行 YAML 文件
YAML 本身不是可执行文件,需要通过特定的工具或编程语言来解析:
1. 命令行工具
bash
# 使用 yq 处理 YAML(类似 jq 对于 JSON)
yq eval '.key' file.yaml
# 使用 Python 的 yq
pip install yq
cat file.yaml | yq
2. 编程语言解析
python
# Python
import yaml
with open('config.yaml', 'r') as file:
data = yaml.safe_load(file)
print(data)
javascript
// Node.js
const yaml = require('js-yaml');
const fs = require('fs');
const data = yaml.load(fs.readFileSync('config.yaml', 'utf8'));
console.log(data);
java
// Java (使用 SnakeYAML)
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.30</version>
</dependency>
Yaml yaml = new Yaml();
Object data = yaml.load(new FileInputStream("config.yaml"));
YAML 语法详解
1. 基本结构
键值对
yaml
# 简单键值对
name: John Doe
age: 30
is_student: false
注释
yaml
# 这是单行注释
key: value # 行内注释
# 多行注释需要每行都以 # 开头
# 这是第二行注释
2. 数据类型
字符串
yaml
# 多种字符串表示方式
string1: Hello World
string2: '带单引号的字符串'
string3: "带双引号的字符串"
# 多行字符串
description: |
这是多行字符串
第二行内容
第三行内容
# 折叠多行字符串(会转换为单行)
summary: >
这是折叠的多行字符串
所有行会连接成一个字符串
空格会被保留
数字
yaml
integer: 42
float: 3.14
scientific: 1.2e+5
infinity: .inf
not_a_number: .nan
布尔值
yaml
true_value: true
false_value: false
yes_value: yes
no_value: no
on_value: on
off_value: off
空值
yaml
null_value: null
empty_value: ~
3. 集合类型
列表/数组
yaml
# 块样式列表
fruits:
- Apple
- Banana
- Orange
# 内联样式列表
colors: [red, green, blue]
# 嵌套列表
matrix:
- [1, 2, 3]
- [4, 5, 6]
- [7, 8, 9]
字典/对象
yaml
# 块样式字典
person:
name: John Doe
age: 30
address:
street: 123 Main St
city: Anytown
country: USA
# 内联样式字典
person_inline: {name: John Doe, age: 30}
# 复杂嵌套结构
company:
name: Tech Corp
employees:
- name: Alice
department: Engineering
skills:
- Python
- JavaScript
- name: Bob
department: Marketing
skills:
- SEO
- Content Writing
4. 高级特性
锚点和别名
yaml
# 定义锚点
defaults: &defaults
adapter: postgres
host: localhost
development:
<<: *defaults # 合并锚点内容
database: dev_db
test:
<<: *defaults
database: test_db
多文档支持
yaml
# 文档1
---
server: &server-config
host: localhost
port: 8080
# 文档2
---
database:
<<: *server-config
name: mydb
type: postgres
...
类型强制
yaml
# 强制字符串类型
string_int: !!str 123
string_bool: !!str true
# 其他类型强制
integer_string: !!int "123"
boolean_string: !!bool "true"
timestamp: !!timestamp 2023-01-01
5. 复杂示例
Docker Compose 配置
yaml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
environment:
- NGINX_HOST=localhost
- NGINX_PORT=80
volumes:
- ./html:/usr/share/nginx/html
networks:
- frontend
database:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
networks:
- backend
networks:
frontend:
backend:
Kubernetes 部署配置
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
env:
- name: ENVIRONMENT
value: "production"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
最佳实践
- 一致的缩进:使用 2 个空格(推荐)
- 有意义的键名:使用描述性的键名
- 适当使用注释:解释复杂配置
- 避免深层嵌套:保持结构扁平
- 使用锚点减少重复:提高可维护性
常见错误
yaml
# 错误:缩进不一致
person:
name: John
age: 30 # 错误缩进
# 错误:键重复
config:
key: value1
key: value2 # 重复键
# 错误:特殊字符未转义
message: "包含:冒号的字符串" # 需要引号
YAML 的强大之处在于它的简洁性和可读性,使其成为现代软件开发中不可或缺的配置格式。
拓展
Docker、GitLab 和 Kubernetes 都有各自固定的 YAML 语法结构和特定的字段定义。以下详细解释每个工具的 YAML 语法特点:
Docker YAML 语法
主要用于 Docker Compose 文件 (docker-compose.yml)
核心结构
yaml
version: '3.8' # Compose 文件版本
services:
web:
image: nginx:latest
container_name: my-web
ports:
- "80:80"
environment:
- NGINX_HOST=localhost
volumes:
- ./html:/usr/share/nginx/html
networks:
- frontend
depends_on:
- database
database:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
networks:
frontend:
driver: bridge
volumes:
db_data:
Docker 特定字段
version: Compose 文件格式版本services: 定义容器服务image: 使用的 Docker 镜像ports: 端口映射environment: 环境变量volumes: 数据卷挂载networks: 网络配置depends_on: 服务依赖关系
GitLab CI YAML 语法
用于 GitLab CI/CD 配置文件 (.gitlab-ci.yml)
核心结构
yaml
# 定义流水线阶段
stages:
- test
- build
- deploy
# 定义变量
variables:
DOCKER_REGISTRY: registry.gitlab.com
IMAGE_NAME: $CI_PROJECT_NAME
# 在所有作业之前运行的脚本
before_script:
- echo "开始 CI/CD 流水线"
# 测试阶段
unit_test:
stage: test
image: node:16
script:
- npm install
- npm test
only:
- merge_requests
- main
# 构建阶段
build_image:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t $DOCKER_REGISTRY/$CI_PROJECT_NAMESPACE/$IMAGE_NAME:$CI_COMMIT_SHA .
- docker push $DOCKER_REGISTRY/$CI_PROJECT_NAMESPACE/$IMAGE_NAME:$CI_COMMIT_SHA
only:
- main
# 部署阶段
deploy_production:
stage: deploy
image: alpine:latest
script:
- apk add --no-cache openssh-client
- ssh deploy@server "docker pull $IMAGE_NAME && docker-compose up -d"
environment:
name: production
url: https://myapp.example.com
only:
- main
when: manual # 手动触发
GitLab CI 特定字段
stages: 定义流水线阶段variables: 环境变量before_script/after_script: 前后置脚本- 作业名称 (如
unit_test): 自定义作业 stage: 作业所属阶段script: 执行的命令only/except: 触发条件environment: 部署环境配置
Kubernetes YAML 语法
用于定义 Kubernetes 集群资源
核心结构示例
Deployment
yaml
apiVersion: apps/v1 # API 版本
kind: Deployment # 资源类型
metadata:
name: nginx-deployment
labels:
app: nginx
environment: production
spec:
replicas: 3 # 副本数
selector:
matchLabels:
app: nginx
template: # Pod 模板
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80
env:
- name: ENV
value: "production"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
restartPolicy: Always
Service
yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx # 匹配 Pod 标签
ports:
- protocol: TCP
port: 80 # Service 端口
targetPort: 80 # Pod 端口
type: LoadBalancer
ConfigMap
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
config.properties: |
server.port=8080
database.url=jdbc:mysql://localhost:3306/mydb
log-level: "INFO"
Kubernetes 特定字段
apiVersion: Kubernetes API 版本kind: 资源类型 (Pod, Deployment, Service, ConfigMap 等)metadata: 元数据 (名称、标签、注解)spec: 资源规格定义replicas: 副本数量selector: 标签选择器template: Pod 模板containers: 容器定义
各工具 YAML 语法对比
| 特性 | Docker Compose | GitLab CI | Kubernetes |
|---|---|---|---|
| 主要用途 | 容器编排开发环境 | CI/CD 流水线 | 容器编排生产环境 |
| 核心概念 | 服务、网络、卷 | 阶段、作业、变量 | 资源、Pod、Service |
| 执行方式 | docker-compose up |
GitLab Runner | kubectl apply |
| 网络模型 | 简单的服务发现 | 无特定网络 | 复杂的服务网格 |
| 扩展性 | 单机环境 | 代码仓库级别 | 集群级别 |
共同点和差异
共同点
- 都使用 YAML 格式
- 都支持嵌套结构
- 都使用键值对配置
- 都支持环境变量
主要差异
-
字段命名约定:
- Docker: 使用下划线 (
container_name) - Kubernetes: 使用驼峰 (
containerPort) - GitLab: 混合使用
- Docker: 使用下划线 (
-
验证方式:
- Docker:
docker-compose config - GitLab: CI Lint 工具
- Kubernetes:
kubectl apply --dry-run=client
- Docker:
-
执行上下文:
- Docker: 本地开发环境
- GitLab: CI/CD 流水线
- Kubernetes: 生产集群环境
最佳实践总结
-
始终验证语法:
bash# Docker docker-compose config # GitLab # 使用 Web UI 的 CI Lint # Kubernetes kubectl apply --dry-run=client -f file.yaml -
使用官方文档:每个工具都有详细的字段参考
-
保持一致性:在团队中统一缩进和格式
-
版本控制:所有 YAML 文件都应该纳入版本控制
每个工具的 YAML 语法都是为其特定用途设计的,理解各自的模式和约定对于有效使用这些工具至关重要。