使用 yq 编辑 YAML 配置文件
使用 yq 原地读取和修改 Kubernetes 与 CI YAML,同时保留结构和注释。
使用 yq 编辑 YAML 配置文件 是 CoddyKit 上的免费 DevOps Bootcamp 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 DevOps Bootcamp 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 DevOps Bootcamp 课程共包含 4 节课。
yq 是什么,以及为什么使用它处理 YAML
yq 是一个可移植的命令行 YAML 处理器,类似于 jq 处理 JSON 的方式。您可以使用它读取、筛选和编辑 YAML 文件,而无需使用 Python 或 Ruby 编写脚本。
有两个常用的工具都名为 yq:
- mikefarah/yq(Go)— 目前仍在积极维护,支持 YAML、JSON、XML 和 TOML。本课程使用此版本。
- kislyuk/yq(Python)— 用于 YAML 的
jq包装器;语法有所不同。
安装 Go 版本:
- 在 macOS 上运行
brew install yq - 在 Linux 上运行
snap install yq - 或者下载二进制文件:
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从 Kubernetes 部署 YAML 中读取值
在编辑任何内容之前,请先学习如何读取 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 会将结果输出到标准输出,而不会修改文件。
语法:
- 仅读取(标准输出):
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更新容器镜像标签
一项非常常见的持续集成任务,是在构建新镜像后更新 Kubernetes 清单中的 Docker 镜像标签。使用 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
在持续集成流水线中,您可以将标签作为 Shell 变量传入:
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修改 GitHub Actions CI YAML
CI 配置文件(.github/workflows/*.yml、.gitlab-ci.yml)同样是 YAML 文件。相同的 yq 命令也适用,不过路径可能会深度嵌套。
常见的 CI 修改任务:
- 固定运行器版本:更新所有作业中的
runs-on。 - 更新操作版本:查找使用特定操作的步骤,并更新其
uses字段。 - 切换标志:启用或禁用工作流程级设置。
示例:将所有使用 actions/checkout 的步骤更新为 v4:
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() 简写形式注入 Shell 变量。
env(VAR_NAME)— 读取环境变量,并将其转换为适当的 YAML 类型(数字仍为数字,字符串仍为字符串)。strenv(VAR_NAME)— 始终返回字符串,适合用于镜像标签。
这样可以避免在包含 YAML 路径的双引号 Shell 字符串中插入变量时产生复杂的引号问题。
模式:
export IMAGE_TAG="my-app:3.0.0"
yq -i '.spec.template.spec.containers[0].image = strenv(IMAGE_TAG)' deployment.yaml设置 replicas 等数值字段时,请使用 env(),这样可以保留 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— 将补丁深度合并到基础配置,并写入标准输出。- 添加
-i可就地更新基础文件:yq -i '. *= load("patch.yaml")' base.yaml
合并行为:
- 补丁中的标量值会覆盖基础配置中的值。
- 映射会进行深度合并(补丁中不存在的键会保留)。
- 序列(数组)默认会被替换,而不是追加。请改用
*+进行追加。
这种模式可以替代脆弱的 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 退出,因此可以在持续集成门禁中使用。
将 YAML 转换为 JSON:
yq -o=json '.' file.yaml— 输出格式化的 JSON。- 将结果通过管道传给
jq,以便进一步处理 JSON:yq -o=json '.' file.yaml | jq '.metadata.name'
将 JSON 转换为 YAML:
yq -P '.' file.json— 当输入为 JSON 时,-P标志会强制输出 YAML(格式化后的内容)。
这些转换使 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 '.'完整的持续集成部署补丁脚本
将所有技术结合起来:这是一个实际的持续集成脚本,用于在 GitOps 流水线中为 Kubernetes Deployment 清单应用补丁。
该脚本会:
- 在处理输入 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"知识检查:安全地编辑多文档文件
请测试您对使用 yq 编辑多文档 Kubernetes YAML 文件的理解。
课程回顾:使用 yq 编辑 YAML
您已经完成了使用 yq 编辑 YAML 配置文件的课程。以下是本课程内容的简要总结:
- 安装:使用 mikefarah/yq Go 二进制文件(v4)。使用
yq --version验证安装。 - 读取:使用类似
.spec.replicas的点号路径;使用[0]访问数组,或使用[]进行迭代。 - 就地编辑:
-i标志会重写文件。请始终先不使用-i预览结果。 - 可靠定位:优先使用
select(.name == "app"),而不是硬编码的数组索引。 - 添加 / 删除:为新路径赋值即可创建它;使用
del()删除字段。 - 多文档文件:使用
select(.kind == "...")定位一个资源,同时保持其他资源不变。 - 持续集成变量:字符串使用
strenv(VAR),带类型的值使用env(VAR),这样可以避免 Shell 引号错误。 - 合并:
. *= load("patch.yaml")会深度合并覆盖文件,同时不会丢失未打补丁的键。 - 验证与转换:使用
yq '.'作为代码检查门禁;使用-o=json和-P进行格式转换。
在持续集成中为任何 YAML 应用补丁时,核心模式都是:验证 → 选择 → 赋值 → 验证。将此模式与 strenv() 和 select() 结合使用后,您再也不需要依赖脆弱的 sed 单行命令了。
用 AI 导师学习 DevOps Bootcamp — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 142
- 课程
- 568
常见问题解答
「使用 yq 编辑 YAML 配置文件」课时是免费的吗?
是的 — 「使用 yq 编辑 YAML 配置文件」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 DevOps Bootcamp 课程的其余内容,请升级到 CoddyKit PRO。 DevOps Bootcamp 课程共包含 4 节课。
「使用 yq 编辑 YAML 配置文件」这节课中我会学到什么?
使用 yq 原地读取和修改 Kubernetes 与 CI YAML,同时保留结构和注释。 你通过在浏览器中直接运行的动手代码来练习 DevOps Bootcamp,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 DevOps Bootcamp 需要有经验吗?
无需任何先前经验。CoddyKit 上的 DevOps Bootcamp 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「使用 yq 编辑 YAML 配置文件」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 DevOps Bootcamp 课中编写并运行代码吗?
能。每节 DevOps Bootcamp 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 jq 管道筛选和选择 JSON
- 使用 jq 转换和构建 JSON 对象
- 结合 curl 与 jq 调用 REST API
- 使用 yq 编辑 YAML 配置文件