YAML
YAML — человеко-читаемый язык для конфигураций (Docker Compose, Kubernetes, Ansible, GitHub Actions). Отступы (пробелы) вместо скобок, комментарии (#), многострочные строки (| — сохраняет переносы, > — сворачивает в пробелы), якоря и ссылки (&, *). Типы данных: строки (кавычки не обязательны, но нужны для чисел и true/false), числа, boolean, null, даты (ISO 8601). YAML vs JSON: YAML читаемее, есть комментарии и якоря, но сложнее (отступы критичны). JSON для API, YAML для конфигов. Проблемы: табуляции запрещены (только пробелы), автоматическое определение типов (version: 1.0 станет числом), безопасность (safe_load вместо load).
Введение: Человеко-читаемый язык для конфигураций
Представьте, что вы пишете инструкцию для сборки шкафа. Можно написать длинный текст. Можно нарисовать схему. А можно сделать список: “1. Взять деталь А. 2. Взять деталь Б. 3. Соединить А и Б винтом 1”. Список читается легко, его можно быстро менять, он не требует специальных программ.
В мире конфигурационных файлов таким “списком” стал YAML. Он создавался как более читаемая альтернатива XML и JSON для файлов, которые пишут и редактируют люди.
YAML (YAML Ain’t Markup Language) — это язык сериализации данных, ориентированный на читаемость человеком. В отличие от JSON, YAML не требует кавычек, скобок и запятых. Он использует отступы (пробелы) для обозначения структуры.
YAML стал стандартом для конфигурационных файлов в DevOps-мире: Docker Compose, Kubernetes, Ansible, GitHub Actions, GitLab CI, CircleCI, Swagger/OpenAPI. Почему? Потому что YAML легче читать и писать, чем JSON, и он поддерживает комментарии. Для конфигураций, которые меняются людьми, это критически важно.
Почему YAML, а не JSON
| Характеристика | JSON | YAML |
|---|---|---|
| Читаемость | Хорошая | Отличная |
| Комментарии | Нет | Да (# комментарий) |
| Кавычки | Обязательны для ключей и строк | Только когда нужны |
| Скобки | {}, [] | Отступы |
| Запятые | Да | Нет |
| Многострочные строки | \n или конкатенация | Да (` |
| Ссылки (якоря) | Нет | Да (&, *) |
| Сложность | Простой | Сложнее (отступы, типы) |
| API | Стандарт | Редко |
JSON: Машиночитаемый, строгий, простой в парсинге. Хорош для передачи данных по сети.
YAML: Человекочитаемый, гибкий, мощный. Хорош для конфигурационных файлов.
Основной синтаксис YAML
Комментарии
# Это комментарий
name: Иван # комментарий после значенияКлючи и значения (пары “ключ-значение”)
# Строка (кавычки не обязательны)
name: Иван
# Число
age: 30
# Логическое
is_active: true
# null (пустое значение)
phone: null
phone: ~ # альтернативная записьОбъекты (словари, хеши, мапы)
# JSON стиль (но без кавычек и скобок)
user:
name: Иван
age: 30
address:
city: Москва
street: Тверская
# Альтернативный синтаксис (блочный, для краткости)
user: {name: Иван, age: 30}Массивы (списки, последовательности)
# Каждый элемент на новой строке с дефисом
phones:
- +7-999-123-45-67
- +7-495-123-45-67
# Альтернативный синтаксис (в одну строку)
phones: [+7-999-123-45-67, +7-495-123-45-67]Вложенные структуры
users:
- name: Иван
age: 30
phones:
- +7-999-123-45-67
- +7-495-123-45-67
- name: Петр
age: 25
phones:
- +7-999-765-43-21Многострочные строки
YAML имеет мощные возможности для работы с многострочным текстом.
Блочные стили
| Стиль | Символ | Поведение |
|---|---|---|
| Literal block | ` | ` |
| Folded block | > | Сворачивает переносы в пробелы |
Пример literal block (|)
description: |
Это первая строка.
Это вторая строка.
Это третья строка.
# Результат: "Это первая строка.\nЭто вторая строка.\nЭто третья строка.\n"Пример folded block (>)
description: >
Это длинное предложение,
которое разбито на несколько строк,
но в итоге будет одной строкой.
# Результат: "Это длинное предложение, которое разбито на несколько строк, но в итоге будет одной строкой.\n"Управление переносом строк
# Сохранить переносы в конце
text: |-
Строка без переноса в конце
# Добавить перенос в конце
text: |+
Строка с переносом в конце
# Количество отступов для блока
code: |2
def hello():
print("Hello")Типы данных в YAML
Строки
# Без кавычек
name: Иван
# В двойных кавычках (экранирование)
path: "C:\\Users\\ivan"
# В одинарных кавычках (без экранирования)
regex: '\d+'
# Пустая строка
empty: ''Числа
integer: 42
float: 3.14
negative: -10
exponential: 1.5e3
hex: 0x2A
octal: 0o52
binary: 0b101010
infinity: .inf
not_a_number: .nanЛогические
true_value: true
false_value: false
# Альтернативные записи (лучше не использовать)
yes_value: yes
no_value: no
on_value: on
off_value: offДаты и время
date: 2024-01-15
datetime: 2024-01-15T10:30:00Z
datetime_with_offset: 2024-01-15T10:30:00+03:00null
empty: null
empty2: ~
empty3: # просто ничего после двоеточияПродвинутые возможности
Якоря (Anchors) и ссылки (Aliases)
Позволяют повторно использовать данные.
# Определение якоря &defaults
defaults: &defaults
timeout: 30
retries: 3
backoff: 2
# Использование ссылки *defaults
production:
<<: *defaults
url: https://prod.example.com
development:
<<: *defaults
url: http://localhost:8080
timeout: 60 # переопределениеРезультат (как будет выглядеть после парсинга):
production:
timeout: 30
retries: 3
backoff: 2
url: https://prod.example.com
development:
timeout: 60
retries: 3
backoff: 2
url: http://localhost:8080Якоря для массивов и объектов
users:
- &admin
name: Admin
role: admin
- &user
name: User
role: user
# Ссылки
admins:
- *admin
- name: BackupAdmin
role: admin
users_copy: [*admin, *user]Теги (явное указание типа)
# Явное указание типа
not_string: !!str 42
not_float: !!int 3.14
binary_data: !!binary SGVsbG8gV29ybGQ=
timestamp: !!timestamp 2024-01-15T10:30:00ZНаборы (Sets)
# Уникальные значения (редко используется)
colors: !!set
? red
? green
? blueПорядок ключей (не гарантирован)
YAML сохраняет порядок ключей (в отличие от JSON), но не стоит на это полагаться в критичных случаях.
YAML в реальных проектах
Docker Compose
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
restart: always
db:
image: postgres:15
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0.0
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
value: postgres://db:5432/myapp
resources:
limits:
memory: "512Mi"
cpu: "500m"GitHub Actions
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: pip install -r requirements.txt
- run: pytest tests/Ansible
- name: Установка и настройка веб-сервера
hosts: webservers
become: yes
tasks:
- name: Установка nginx
apt:
name: nginx
state: present
- name: Копирование конфигурации
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: reload nginx
handlers:
- name: reload nginx
service:
name: nginx
state: reloadedOpenAPI / Swagger
openapi: 3.0.0
info:
title: User API
version: 1.0.0
paths:
/users/{id}:
get:
summary: Получить пользователя
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Успех
content:
application/json:
schema:
$ref: '#/components/schemas/User'
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: stringYAML vs JSON vs XML
| Характеристика | JSON | XML | YAML |
|---|---|---|---|
| Читаемость человеком | Хорошая | Средняя | Отличная |
| Комментарии | Нет | Да | Да |
| Размер (типичный) | Средний | Большой | Маленький (без скобок) |
| Сложность синтаксиса | Низкая | Средняя | Средняя (отступы) |
| Ссылки/якоря | Нет | Нет | Да |
| Многострочные строки | Плохо | Плохо | Отлично |
| Типы данных | Базовые | Все строки (через схему) | Расширенные (даты, бинарные) |
| Поддержка в языках | Все | Все | Хорошая (но не все) |
| Парсинг | Простой | Сложный | Средний |
| Где используется | API | Документы, SOAP | Конфиги, DevOps |
Проблемы и ограничения YAML
Проблема 1: Отступы (критичны)
# Правильно (2 пробела)
user:
name: Иван
age: 30
# Ошибка (смесь пробелов и табуляций)
user:
name: Иван # табуляция
age: 30 # пробелыПравило: Только пробелы, никаких табуляций. Количество пробелов должно быть одинаковым в одном уровне.
Проблема 2: Автоматическое определение типов
# Неожиданное число
version: 1.0 # станет числом 1.0, не строкой
# Неожиданный null
null_value: null # null
empty: # null (пустое значение)
# Неожиданное логическое
on: on # true
off: off # false
yes: yes # true
no: no # falseРешение: Использовать кавычки для строк.
version: "1.0"
on: "on"
empty: ""Проблема 3: Длинные файлы
Большие YAML файлы (1000+ строк) сложно редактировать из-за отступов.
Решение: Разбивать на несколько файлов или использовать JSON для больших объёмов.
Проблема 4: Безопасность
YAML может выполнять произвольный код в некоторых парсерах (например, Ruby YAML). Атака через “YAML deserialization”.
Решение: Использовать безопасные парсеры (safe_load вместо load).
# Опасно
import yaml
data = yaml.load(user_input) # может выполнить код
# Безопасно
data = yaml.safe_load(user_input)Проблема 5: Поддержка в языках
Не все языки имеют полноценную поддержку YAML. Например, в Go стандартная библиотека не включает YAML.
YAML vs JSON в конфигах
| Аспект | JSON | YAML |
|---|---|---|
| Читаемость | Хорошая (со скобками) | Отличная (без скобок) |
| Комментарии | Нет | Да |
| Редактирование вручную | Нормально (но без комментариев) | Легко |
| Diff в Git | Нормально | Отлично (меньше изменений) |
| Поддержка в IDE | Отличная (автодополнение) | Хорошая (но сложнее с отступами) |
Пример: один и тот же конфиг в JSON и YAML
JSON:
{
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp",
"user": "admin",
"password": "secret"
},
"redis": {
"host": "localhost",
"port": 6379
},
"features": ["analytics", "logging", "notifications"]
}YAML:
# Конфигурация приложения
database:
host: localhost
port: 5432
name: myapp
user: admin
password: secret
redis:
host: localhost
port: 6379
features:
- analytics
- logging
- notificationsВывод: Для конфигов YAML удобнее (комментарии, читаемость). Для API JSON (стандарт, простота парсинга).
Инструменты для работы с YAML
| Инструмент | Назначение |
|---|---|
| yaml-online-parser.appspot.com | Валидация |
| json2yaml.com | Конвертер JSON → YAML |
| yamltojson.com | Конвертер YAML → JSON |
IDE поддержка
| IDE | Поддержка |
|---|---|
| VS Code | Плагины: YAML, Red Hat YAML, YAML Schemas |
| IntelliJ IDEA | Встроенная поддержка |
| PyCharm | Встроенная поддержка |
| Vim | Плагин: vim-yaml |
Распространённые ошибки
Ошибка 1: Табуляции вместо пробелов
# Плохо (табуляция)
user:
name: Иван
# Хорошо (2 пробела)
user:
name: ИванОшибка 2: Неправильные отступы
# Плохо (разное количество пробелов)
user:
name: Иван
age: 30
# Хорошо
user:
name: Иван
age: 30Ошибка 3: Строка, похожая на число или логическое
# Плохо (станет числом 1.0)
version: 1.0
# Плохо (станет true)
feature_enabled: on
# Хорошо (строка)
version: "1.0"
feature_enabled: "on"Ошибка 4: Пустое значение вместо null
# Плохо (null, но может быть неожиданностью)
phone:
# Лучше (явно)
phone: null
phone: ~Ошибка 5: Двоеточие без пробела
# Плохо (синтаксическая ошибка)
name:Иван
# Хорошо
name: ИванОшибка 6: Дефис без пробела в массиве
# Плохо
phones:
-+7-999-123-45-67
# Хорошо
phones:
- +7-999-123-45-67Резюме для системного аналитика
YAML (YAML Ain’t Markup Language) — язык сериализации данных, ориентированный на читаемость человеком. Стандарт для конфигурационных файлов в DevOps.
Ключевые особенности: отступы вместо скобок, комментарии (
#), многострочные строки (|,>), якоря и ссылки (&,*), богатые типы данных.Где используется: Docker Compose, Kubernetes, Ansible, GitHub Actions, GitLab CI, CircleCI, Swagger/OpenAPI, Helm, Terraform.
YAML vs JSON: YAML читаемее, поддерживает комментарии, многострочные строки, якоря. JSON проще, строже, быстрее парсится. YAML для конфигов, JSON для API.
Проблемы: отступы критичны (только пробелы, не табуляции), автоматическое определение типов (нужны кавычки для строк, похожих на числа), безопасность (использовать safe_load).