← Kubernetes: основы
4 мин · intro · Урок 1 из 11

YAML для k8s

Минимум синтаксиса который нужен чтобы читать манифесты.

Анкета для машины

Представь бумажную анкету: сверху ФИО, ниже список языков, потом подформа «адрес» со своими графами. YAML устроен ровно так же. Это анкета, только её читает не человек, а парсер.

Поле слева, значение справа, между ними двоеточие и пробел. Привычное «ФИО: Иван» превращается в name: Иван. Никакой магии тут нет, и почти весь манифест pod-а будет такими же парами.

Анкета ФИО Иван Петров Языки • Русский • Английский Адрес Страна: Россия Город: Москва YAML name: Иван Петров languages: ··- Русский ··- Английский address: ··country: Россия ··city: Москва

Map, list, вложенность

name: Иван — это map: ключ, двоеточие, пробел, значение. Из таких пар собирается весь манифест. Каждая строка — одно поле формы.

Список языков работает иначе. В анкете там галочки, а в YAML вместо галочек тире. Каждый пункт со своей строки:

languages:
  - Русский
  - Английский

Это list. А подформа «адрес» вкладывается в родителя через отступ:

address:
  country: Россия
  city: Москва

Два пробела сдвига говорят парсеру «эти поля относятся к адресу». Два — это пример: YAML допускает любой отступ, главное — одинаковый внутри одного блока, иначе вложенность ломается.

Комментарии и несколько объектов в одном файле

Комментарий начинается с # и идёт до конца строки. Парсер его пропускает:

# вся строка комментарий
name: web  # хвост строки тоже можно

В k8s часто несколько объектов лежат в одном файле и разделяются тремя дефисами ---:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
---
apiVersion: v1
kind: Service
metadata:
  name: app-svc

kubectl apply -f all.yaml применит оба объекта за один заход.

5 граблей

Дальше пять ошибок, на которые наступают почти все. Большая часть «странных» падений kubectl apply это не баги kubectl. Это YAML, который тихо распарсился не так, как ты ожидал.

1. Tabs вместо spaces

# неверно: tab в отступе
spec:
→containers:

# верно: два пробела
spec:
  containers:

YAML запрещает табуляцию в отступах. Парсер падает на первой же строке. Часто прилетает копипастом из браузера или CMS, где пробелы подменились табами.

2. no и yes без кавычек

# неверно: no превратится в false (YAML 1.1)
country: no

# верно: строка в кавычках
country: "no"

Тут важная оговорка. Сам kubectl использует YAML 1.2, где no/yes уже строки. Но это правило живёт в YAML 1.1, на котором работают Helm (Go-шаблоны + sprig), PyYAML и многие CI-инструменты. Один и тот же файл через разные парсеры даст разный результат, поэтому привычка брать такие значения в кавычки спасает везде.

3. Смешанные отступы

# неверно: на одном уровне разный сдвиг
spec:
  containers:
    - name: web
      ports:
       - 80   # три пробела
       - 443  # три пробела, а у name 6

# верно: один уровень = одинаковый сдвиг
spec:
  containers:
    - name: web
      ports:
        - 80
        - 443

Парсер смотрит на колонку. Разный отступ читается как разный уровень вложенности, и поле уезжает не в тот объект.

4. Ведущий ноль и кавычки

YAML читает число с ведущим нулём как восьмеричное: 0644 для парсера равно десятичному 420. Для прав доступа это ровно то, что нужно, поэтому в манифестах Kubernetes режим файла пишут без кавычек:

# правильно: числом, как в документации Kubernetes
defaultMode: 0644

Кавычки здесь всё ломают. Поле defaultMode в API объявлено целым числом, и строку API-сервер не принимает:

$ kubectl apply -f pod.yaml
Error from server (BadRequest): cannot unmarshal string into Go struct field
ConfigMapVolumeSource.spec.volumes.VolumeSource.configMap.defaultMode of type int32

Кавычки нужны там, где значение по смыслу строка, а YAML норовит превратить её в число или в булево: теги образов, версии, значения в ConfigMap.

data:
  version: "1.10"     # без кавычек станет числом 1.1
  debug: "false"      # без кавычек станет булевым false

5. Пропущенный пробел после :

# неверно: ключ слипся со значением
name:nginx

# верно: пробел обязателен
name: nginx

Без пробела парсер читает name:nginx как ключ целиком, а значение оказывается пустым. Ошибка вылезает в неочевидной строке ниже, и ты долго ищешь её не там, где она реально живёт.

Минимальный pod-манифест

apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
    - name: nginx
      image: nginx:1.27

apiVersion это «бланк такого-то образца», какую версию API брать. kind это тип документа: pod, deployment, service. metadata это служебные поля: имя, метки. spec это сама заявка, что именно ты просишь у кластера.

Self-check: не подглядывая в код выше, какой отступ должен быть у containers относительно spec? Ответ: два пробела.

Дальше

Следующий урок: зачем вообще нужен Kubernetes и какую задачу он решает.

Прошли материал до конца? Отметьте урок пройденным.