0Pricing
Linux Command Line & Bash Scripting Mastery · Урок

Редактирование файлов конфигурации YAML с yq

Читайте и изменяйте YAML Kubernetes и CI на месте с помощью yq, сохраняя структуру и комментарии

«Редактирование файлов конфигурации YAML с yq» — бесплатный урок Linux Command Line & Bash Scripting Mastery на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Linux Command Line & Bash Scripting Mastery, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Linux Command Line & Bash Scripting Mastery содержит 4 уроков всего.

Что такое yq и зачем использовать его для YAML

yq — переносимый обработчик YAML в командной строке, аналогично тому, как jq работает с JSON. С его помощью можно читать, фильтровать и редактировать файлы YAML, не создавая скрипт на Python или Ruby.

Существуют два популярных инструмента с именем yq:

  • mikefarah/yq (Go) — активно поддерживается, работает с YAML, JSON, XML и TOML. В этом уроке используется именно эта версия.
  • kislyuk/yq (Python) — оболочка для jq, работающая с YAML; синтаксис отличается.

Установите версию на Go:

  • brew install yq в macOS
  • snap install yq в Linux
  • Или скачайте двоичный файл: wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq && chmod +x /usr/local/bin/yq

Проверьте установку: команда yq --version должна вывести v4.x.x. В версии 4 используется другой синтаксис выражений, чем в v3, поэтому версия имеет значение.

# Install yq (Go version) on Linux
wget -q https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 \
  -O /usr/local/bin/yq
chmod +x /usr/local/bin/yq

# Confirm version
yq --version

Чтение значений из YAML развёртывания Kubernetes

Прежде чем что-либо редактировать, научитесь читать поля YAML. В описании развёртывания Kubernetes можно извлечь любое вложенное значение с помощью путей в точечной нотации.

Пример deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: app
          image: my-app:1.0.0

Основные команды чтения:

  • yq '.metadata.name' deployment.yaml — выводит my-app
  • yq '.spec.replicas' deployment.yaml — выводит 3
  • yq '.spec.template.spec.containers[0].image' deployment.yaml — выводит my-app:1.0.0

По умолчанию выводится обычный текст (без кавычек). Добавьте флаг -r или используйте | yq -r, если в скриптах нужны необработанные строки.

# Create a sample deployment YAML
cat > /tmp/deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: app
          image: my-app:1.0.0
EOF

# Read individual fields
echo "App name:    $(yq '.metadata.name' /tmp/deployment.yaml)"
echo "Replicas:    $(yq '.spec.replicas' /tmp/deployment.yaml)"
echo "Image:       $(yq '.spec.template.spec.containers[0].image' /tmp/deployment.yaml)"

Редактирование на месте с флагом -i

Самый важный флаг для практического использования — -i (редактирование на месте). Без него yq выводит результаты в stdout, не изменяя файл.

Синтаксис:

  • Только чтение (stdout): yq '.spec.replicas' file.yaml
  • Редактирование на месте: yq -i '.spec.replicas = 5' file.yaml

Оператор присваивания = задаёт значение. Выражение представляет собой полноценный фильтр yq, поэтому чтение и запись можно объединить за один проход.

Важно: yq -i полностью перезаписывает файл. Комментарии в той же строке, что и поле, обычно сохраняются, но отдельные блоки комментариев могут переместиться. Всегда фиксируйте YAML в системе контроля версий перед массовым редактированием на месте.

Сначала проверьте результат без -i, а затем добавьте его, когда результат Вас устроит.

# Start with the deployment from the previous scene
echo 'Before:' && yq '.spec.replicas' /tmp/deployment.yaml

# Edit in place: scale to 5 replicas
yq -i '.spec.replicas = 5' /tmp/deployment.yaml

echo 'After:' && yq '.spec.replicas' /tmp/deployment.yaml

Обновление тега образа контейнера

Очень распространённая задача CI — изменить тег образа Docker в манифесте Kubernetes после сборки нового образа. С yq это выполняется одной строкой.

Шаблон выглядит так:

  • Находите контейнер по имени с помощью select(), чтобы не привязываться к индексу 0 в массиве.
  • Используйте |= (оператор обновления) или =, чтобы задать новое значение.

С использованием индекса массива (ненадёжно, если список контейнеров изменится):

  • yq -i '.spec.template.spec.containers[0].image = "my-app:2.1.0"' deployment.yaml

С использованием select() (надёжно):

  • yq -i '(.spec.template.spec.containers[] | select(.name == "app")).image = "my-app:2.1.0"' deployment.yaml

В конвейере CI тег передаётся как переменная оболочки:

NEW_TAG="my-app:2.1.0"
CONTAINER_NAME="app"

# Robust update: target by container name, not index
yq -i \
  "(.spec.template.spec.containers[] | select(.name == \"${CONTAINER_NAME}\")).image = \"${NEW_TAG}\"" \
  /tmp/deployment.yaml

# Verify
yq '.spec.template.spec.containers[0].image' /tmp/deployment.yaml

Добавление и удаление полей

Помимо обновления существующих полей, yq может добавлять новые ключи и удалять существующие.

Добавление поля:

  • Просто присвойте значение пути, которого ещё нет: yq -i '.metadata.labels.version = "v2"' file.yaml
  • Если родительский ключ (labels) отсутствует, yq создаст его автоматически.

Удаление поля:

  • Используйте функцию del(): yq -i 'del(.metadata.annotations)' file.yaml
  • Удалите элемент массива по индексу: yq -i 'del(.spec.template.spec.containers[1])' file.yaml

Добавление элемента в массив:

  • yq -i '.spec.template.spec.containers += [{"name": "sidecar", "image": "envoy:latest"}]' file.yaml
# Add a label to the deployment
yq -i '.metadata.labels.version = "v2"' /tmp/deployment.yaml
yq -i '.metadata.labels.managed-by = "ci-pipeline"' /tmp/deployment.yaml

echo '--- Labels after adding ---'
yq '.metadata.labels' /tmp/deployment.yaml

# Delete one label
yq -i 'del(.metadata.labels.managed-by)' /tmp/deployment.yaml

echo '--- Labels after delete ---'
yq '.metadata.labels' /tmp/deployment.yaml

Работа с многофайловыми документами YAML

Манифесты Kubernetes часто объединяют несколько ресурсов в одном файле, разделённых с помощью ---. По умолчанию yq обрабатывает все документы в таком файле.

Основные приёмы:

  • Вывести виды всех документов: yq '.[].kind' multi.yaml — обратите внимание на начальный .[], который перебирает документы.
  • Выбрать конкретный документ по виду: yq 'select(.kind == "Service")' multi.yaml
  • Редактировать на месте только подходящие документы:

yq -i 'select(.kind == "Deployment").spec.replicas = 2' multi.yaml

Документы, не соответствующие условию select(), передаются без изменений, поэтому Ваши Service, ConfigMap и другие ресурсы сохраняются.

Чтобы разделить многофайловый документ на отдельные файлы, можно перебрать вывод yq в цикле или использовать:

  • yq -s '.kind' multi.yaml — записывает по одному файлу на документ, используя значение его .kind в имени.
cat > /tmp/multi.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 1
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  port: 80
EOF

# Scale ONLY the Deployment, leave Service untouched
yq -i 'select(.kind == "Deployment").spec.replicas = 4' /tmp/multi.yaml

echo '--- Deployment replicas ---'
yq 'select(.kind == "Deployment").spec.replicas' /tmp/multi.yaml

echo '--- Service port (unchanged) ---'
yq 'select(.kind == "Service").spec.port' /tmp/multi.yaml

Исправление YAML CI GitHub Actions

Файлы конфигурации CI (.github/workflows/*.yml, .gitlab-ci.yml) также являются файлами YAML. Те же команды yq работают и с ними, хотя пути могут быть глубоко вложенными.

Распространённые задачи исправления CI:

  • Зафиксировать версию исполнителя: обновить runs-on во всех заданиях.
  • Обновить версию действия: найти шаги, использующие определённое действие, и изменить его поле uses.
  • Переключить флаг: включить или отключить настройку уровня рабочего процесса.

Пример: обновить до v4 все шаги, использующие actions/checkout:

yq -i '(.jobs[].steps[] | select(.uses == "actions/checkout@v3")).uses = "actions/checkout@v4"' .github/workflows/ci.yml

Этот приём — перебирать с помощью [], сужать выбор с помощью select(), присваивать с помощью = — является основным шаблоном любого структурированного редактирования YAML.

cat > /tmp/ci.yml << 'EOF'
name: CI
on: [push]
jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm test
  lint:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v3
      - run: npm run lint
EOF

# Bump all checkout steps from v3 → v4
yq -i '(.jobs[].steps[] | select(.uses == "actions/checkout@v3")).uses = "actions/checkout@v4"' \
  /tmp/ci.yml

# Verify both jobs were updated
yq '.jobs[].steps[] | select(.uses | test("checkout")).uses' /tmp/ci.yml

Использование переменных окружения в выражениях yq

Жёстко заданные значения в выражениях yq делают скрипты хрупкими. yq поддерживает передачу переменных оболочки с помощью функции env() или сокращённой записи strenv().

  • env(VAR_NAME) — считывает переменную окружения и преобразует её в соответствующий тип YAML (число остаётся числом, строка — строкой).
  • strenv(VAR_NAME) — всегда возвращает строку; это удобно для тегов образов.

Так Вы избежите сложного экранирования при подстановке переменных во вложенные строки оболочки в двойных кавычках с путями YAML.

Шаблон:

export IMAGE_TAG="my-app:3.0.0"
yq -i '.spec.template.spec.containers[0].image = strenv(IMAGE_TAG)' deployment.yaml

Используйте env() при задании числовых полей, например replicas, чтобы сохранить тип YAML (целое число, а не строка в кавычках).

export APP_IMAGE="my-app:3.0.0"
export REPLICA_COUNT=6

# Set image using strenv() — result is a YAML string
yq -i '.spec.template.spec.containers[0].image = strenv(APP_IMAGE)' \
  /tmp/deployment.yaml

# Set replicas using env() — result is a YAML integer
yq -i '.spec.replicas = env(REPLICA_COUNT)' \
  /tmp/deployment.yaml

# Confirm types are correct in the output
yq '.spec.replicas, .spec.template.spec.containers[0].image' /tmp/deployment.yaml

Объединение двух YAML-файлов

Иногда необходимо применить файл исправлений (небольшой YAML-файл с переопределениями) к базовой конфигурации — например, чтобы задать переопределения для конкретной среды в рабочих процессах в стиле Kustomize.

yq позволяет объединять два файла с помощью оператора объединения *:

  • yq '. *= load("patch.yaml")' base.yaml — выполняет глубокое объединение patch с base и записывает результат в стандартный вывод.
  • Добавьте -i, чтобы обновить base на месте: yq -i '. *= load("patch.yaml")' base.yaml

Поведение при объединении:

  • Скалярные значения из patch заменяют значения в base.
  • Отображения объединяются рекурсивно (ключи, отсутствующие в patch, сохраняются).
  • Последовательности (массивы) по умолчанию заменяются, а не добавляются в конец. Чтобы добавлять элементы, используйте *+.

Этот подход заменяет хрупкие сценарии sed, которые ломаются при изменении пробелов.

cat > /tmp/base.yaml << 'EOF'
app:
  name: my-service
  port: 8080
  debug: false
database:
  host: localhost
  port: 5432
EOF

cat > /tmp/patch.yaml << 'EOF'
app:
  port: 9090
  debug: true
database:
  host: db.production.svc
EOF

# Deep-merge patch into base (stdout preview first)
yq '. *= load("/tmp/patch.yaml")' /tmp/base.yaml

# Apply in place
yq -i '. *= load("/tmp/patch.yaml")' /tmp/base.yaml

Проверка YAML и преобразование в JSON

Перед применением исправленного YAML к кластеру рекомендуется проверить его и при необходимости преобразовать в JSON для других инструментов.

Проверка синтаксиса:

  • yq '.' file.yaml && echo "Valid" — при ошибках разбора yq завершается с кодом 1, поэтому этот вариант подходит для проверок в CI.

Преобразование YAML в JSON:

  • yq -o=json '.' file.yaml — выводит отформатированный JSON.
  • Передайте результат в jq для дальнейшей обработки JSON: yq -o=json '.' file.yaml | jq '.metadata.name'

Преобразование JSON в YAML:

  • yq -P '.' file.json — флаг -P принудительно задаёт вывод в формате YAML (с форматированием), если входные данные представлены в JSON.

Эти преобразования превращают yq в связующее звено между инструментами, ориентированными на YAML (Helm, kubectl), и инструментами, ориентированными на JSON (Terraform, AWS CLI, jq).

# Validate YAML (exits 0 on success, 1 on parse error)
if yq '.' /tmp/deployment.yaml > /dev/null 2>&1; then
  echo "YAML is valid"
else
  echo "YAML parse error!" >&2
  exit 1
fi

# Convert to JSON and query with jq
yq -o=json '.' /tmp/deployment.yaml \
  | jq '{name: .metadata.name, image: .spec.template.spec.containers[0].image}'

# Round-trip: JSON snippet back to YAML
echo '{"replicas": 7, "strategy": "RollingUpdate"}' \
  | yq -P '.'

Полный сценарий исправления развёртывания в CI

Объединим все рассмотренные приёмы в одном рабочем сценарии CI, который исправляет манифест развёртывания Kubernetes в рамках GitOps-конвейера.

Сценарий:

  1. Проверяет входной YAML, прежде чем вносить изменения.
  2. Использует env() / strenv() для всех подстановок переменных.
  3. Обновляет тег образа контейнера с помощью select() по имени.
  4. Увеличивает количество реплик.
  5. Добавляет в аннотацию deploy-time текущую метку времени.
  6. Снова проверяет результат перед фиксацией изменений.

Этот подход гарантирует атомарность и возможность аудита каждого шага, даже если конвейер выполняется одновременно в нескольких экземплярах.

#!/usr/bin/env bash
set -euo pipefail

MANIFEST="/tmp/deployment.yaml"
export NEW_IMAGE="my-app:$(date +%Y%m%d)-abc1234"
export NEW_REPLICAS=3
export DEPLOY_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
export CONTAINER="app"

# 1. Validate before patching
yq '.' "$MANIFEST" > /dev/null

# 2. Update image (by container name)
yq -i \
  '(.spec.template.spec.containers[] | select(.name == strenv(CONTAINER))).image = strenv(NEW_IMAGE)' \
  "$MANIFEST"

# 3. Set replicas
yq -i '.spec.replicas = env(NEW_REPLICAS)' "$MANIFEST"

# 4. Stamp annotation
yq -i '.metadata.annotations."deploy-time" = strenv(DEPLOY_TIME)' "$MANIFEST"

# 5. Validate result
yq '.' "$MANIFEST" > /dev/null && echo "Patch applied successfully"

# 6. Show diff summary
yq '{image: .spec.template.spec.containers[0].image, replicas: .spec.replicas}' "$MANIFEST"

Проверка знаний: безопасное редактирование нескольких документов

Проверьте, насколько хорошо Вы поняли редактирование YAML-файлов Kubernetes с несколькими документами с помощью yq.

Итоги урока: редактирование YAML с помощью yq

Вы завершили урок о редактировании файлов конфигурации YAML с помощью yq. Ниже приведено краткое резюме всего изученного:

  • Установка: Используйте двоичный файл mikefarah/yq для Go (версии 4). Проверьте установку с помощью yq --version.
  • Чтение: Пути в точечной нотации, например .spec.replicas; доступ к массиву с помощью [0] или перебора через [].
  • Редактирование на месте: Флаг -i перезаписывает файл. Сначала всегда просматривайте результат без -i.
  • Надёжный выбор элементов: Предпочитайте select(.name == "app") жёстко заданным индексам массива.
  • Добавление и удаление: Присвойте значение новому пути, чтобы создать его; используйте del(), чтобы удалить поля.
  • Файлы с несколькими документами: Используйте select(.kind == "..."), чтобы выбрать один ресурс и не затронуть остальные.
  • Переменные CI: Используйте strenv(VAR) для строк и env(VAR) для типизированных значений — это позволяет избежать ошибок экранирования в оболочке.
  • Объединение: . *= load("patch.yaml") выполняет глубокое объединение файла с переопределениями, не теряя ключи, для которых нет исправлений.
  • Проверка и преобразование: Используйте yq '.' как проверку перед продолжением, а -o=json и -P — для преобразования формата.

Основной шаблон любого исправления YAML в CI таков: проверить → выбрать → присвоить → проверить. Сочетайте его с strenv() и select(), и Вам больше не придётся прибегать к хрупким однострочным командам sed.

Часто задаваемые вопросы

Урок «Редактирование файлов конфигурации YAML с yq» бесплатный?

Да — полный текст урока «Редактирование файлов конфигурации YAML с yq» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Linux Command Line & Bash Scripting Mastery, подпишись на CoddyKit PRO. Курс Linux Command Line & Bash Scripting Mastery содержит 4 уроков всего.

Чему я научусь в уроке «Редактирование файлов конфигурации YAML с yq»?

Читайте и изменяйте YAML Kubernetes и CI на месте с помощью yq, сохраняя структуру и комментарии Ты практикуешь Linux Command Line & Bash Scripting Mastery с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Linux Command Line & Bash Scripting Mastery?

Предыдущий опыт не требуется. Linux Command Line & Bash Scripting Mastery на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Редактирование файлов конфигурации YAML с yq»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Linux Command Line & Bash Scripting Mastery?

Да. Каждый урок Linux Command Line & Bash Scripting Mastery включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Фильтрация и выборка JSON с конвейерами jq
  2. Преобразование и создание объектов JSON с jq
  3. Использование REST API с curl и jq
  4. Редактирование файлов конфигурации YAML с yq
← Назад к Linux Command Line & Bash Scripting Mastery