Редактирование файлов конфигурации 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в macOSsnap 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-appyq '.spec.replicas' deployment.yaml— выводит3yq '.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-конвейера.
Сценарий:
- Проверяет входной YAML, прежде чем вносить изменения.
- Использует
env()/strenv()для всех подстановок переменных. - Обновляет тег образа контейнера с помощью
select()по имени. - Увеличивает количество реплик.
- Добавляет в аннотацию
deploy-timeтекущую метку времени. - Снова проверяет результат перед фиксацией изменений.
Этот подход гарантирует атомарность и возможность аудита каждого шага, даже если конвейер выполняется одновременно в нескольких экземплярах.
#!/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 — локальная установка не требуется.
Все уроки этого курса
- Фильтрация и выборка JSON с конвейерами jq
- Преобразование и создание объектов JSON с jq
- Использование REST API с curl и jq
- Редактирование файлов конфигурации YAML с yq