yq で YAML を扱う — k8s / GitHub Actions 用 30+ パターン
yq は YAML/JSON/XML を扱う CLI。kubectl・GitHub Actions YAML・Helm values・docker-compose
を編集する時に必須です。本記事は最も普及している mikefarah/yq (Go 製) を前提にします。
jq とほぼ同じ書き方で扱えるのが強み。
2 種類の yq に注意:
- mikefarah/yq (Go 製、本稿対象) —
yq -i '.x.y = "v"' file.yaml形式。最も普及。 - kislyuk/yq (Python 製) — jq のラッパで
yq '.x.y'のみ、書き換えは別ツール。互換性なし。
yq --version で確認。
目次
サンプル YAML として下記を仮定:
# app.yaml
apiVersion: v1
kind: Deployment
metadata:
name: web
labels:
app: web
env: prod
spec:
replicas: 3
template:
spec:
containers:
- name: web
image: nginx:1.25
resources:
requests:
cpu: 100m
memory: 128Mi
1. 読み取り
# 全表示(フォーマット維持)
yq . app.yaml
# 値取得
yq '.spec.replicas' app.yaml # 3
yq -r '.metadata.name' app.yaml # web (raw 出力、クォート無し)
# 配列展開
yq '.spec.template.spec.containers[]' app.yaml
yq '.spec.template.spec.containers[].image' app.yaml
# 条件抽出
yq '.spec.template.spec.containers[] | select(.name == "web")' app.yaml
# キー一覧
yq '.metadata | keys' app.yaml
# 型確認
yq '.spec.replicas | type' app.yaml # !!int
# 長さ
yq '.spec.template.spec.containers | length' app.yaml
2. in-place 更新 (-i)
jq と決定的に違うのが、yq はファイルの直接編集 (-i) ができる点。
YAML のコメントや順序を維持したまま値だけ書き換えられる。
# 値を更新
yq -i '.spec.replicas = 5' app.yaml
yq -i '.metadata.labels.env = "stg"' app.yaml
# 環境変数からの注入
yq -i ".spec.replicas = $REPLICAS" app.yaml
yq -i '.spec.replicas = env(REPLICAS)' app.yaml # 型推論あり (env())
yq -i '.image = strenv(IMAGE)' app.yaml # 強制 string (strenv)
# 配列要素の更新( index 指定)
yq -i '.spec.template.spec.containers[0].image = "nginx:1.27"' app.yaml
# 全要素一括変更
yq -i '.spec.template.spec.containers[].imagePullPolicy = "IfNotPresent"' app.yaml
# select で絞ってから更新
yq -i '(.spec.template.spec.containers[] | select(.name == "web") | .image) = "nginx:1.27"' app.yaml
# キー追加
yq -i '.metadata.annotations.maintainer = "iigtn"' app.yaml
# キー削除
yq -i 'del(.metadata.labels.env)' app.yaml
# 配列要素追加
yq -i '.spec.template.spec.containers += [{"name":"sidecar","image":"busybox"}]' app.yaml
# マージ(既存に追記、配列は連結)
yq -i '. *= load("override.yaml")' base.yaml
# 全 file 一括(複数ファイル対象)
yq -i '.metadata.namespace = "prod"' k8s/*.yaml
3. multi-document YAML
k8s manifest は --- で複数ドキュメントを 1 ファイルに含めることが多い。yq は標準対応。
# すべての document を表示
yq 'select(documentIndex >= 0)' multi.yaml
# 特定 document のみ(0 始まり)
yq 'select(documentIndex == 0)' multi.yaml
# kind == Deployment の document だけ
yq 'select(.kind == "Deployment")' multi.yaml
# 全 document の name 一覧
yq '[.metadata.name]' multi.yaml # 各 document が個別出力
yq -o=json '.metadata.name' multi.yaml | jq -s
# 各 document に共通フィールド追加
yq -i '.metadata.labels.team = "platform"' multi.yaml
# document 結合 (multi → single 配列)
yq ea '[.]' multi.yaml # ea = eval-all
# 別ファイルの document を merge
yq ea '. as $item ireduce ({}; . * $item)' base.yaml override.yaml
4. YAML ↔ JSON 変換
# YAML → JSON
yq -o=json '.' app.yaml
yq -o=json '.' app.yaml > app.json
# JSON → YAML
yq -p=json '.' data.json
cat data.json | yq -p=json -o=yaml
# YAML → CSV / TSV / Properties
yq -o=csv '[.users[]]' data.yaml
yq -o=props '.config' app.yaml
# 入力フォーマット指定(拡張子が無い時)
cat foo | yq -p=yaml '.x'
cat foo | yq -p=json '.x'
cat foo | yq -p=xml '.x'
5. k8s / Compose / Actions レシピ
レシピ 1 — k8s Deployment の image を更新
yq -i '
(.spec.template.spec.containers[] | select(.name == "web") | .image) = "nginx:1.27"
' k8s/web-deployment.yaml
# ConfigMap の値を更新
yq -i '.data.LOG_LEVEL = "debug"' k8s/configmap.yaml
レシピ 2 — multi-document manifest の特定 kind だけ操作
# すべての Deployment の replicas を 5 に
yq -i 'select(.kind == "Deployment").spec.replicas = 5' k8s/all.yaml
# 特定 namespace を全 document に注入
yq -i '.metadata.namespace = "prod"' k8s/all.yaml
レシピ 3 — docker-compose の image tag を環境変数で書き換え
IMAGE_TAG=v1.2.3 yq -i '.services.web.image = "myapp:" + strenv(IMAGE_TAG)' compose.yaml
レシピ 4 — GitHub Actions YAML から workflow 名一覧
for f in .github/workflows/*.yml; do
echo "$f: $(yq -r '.name' $f)"
done
レシピ 5 — Helm values.yaml の値を上書き
# 配列内の対象要素を更新
yq -i '
(.deployments[] | select(.name == "api") | .replicas) = 4
' values.yaml
# 別ファイルとマージ
yq -i '. *= load("values-prod.yaml")' values.yaml
レシピ 6 — kubectl 出力を yq で整形
kubectl get pods -o yaml \
| yq '.items[] | {name: .metadata.name, status: .status.phase, ip: .status.podIP}'
# JSON 出力経由でもいい (jq でも処理可能)
kubectl get pods -o json | yq -p=json '.items[].metadata.name'
レシピ 7 — env ファイルの自動生成(YAML → .env)
# config.yaml: { app: { port: 8080, log_level: info } }
yq -r '.app | to_entries[] | "\(.key | upcase)=\(.value)"' config.yaml
# 出力: PORT=8080
# LOG_LEVEL=info
コマンド早見表
# 読取
yq '.x.y' file.yaml
yq -r '.metadata.name' file.yaml
# 更新 (in-place)
yq -i '.spec.replicas = 5' file.yaml
yq -i '.image = strenv(IMG)' file.yaml
yq -i 'del(.metadata.labels.env)' file.yaml
# 条件 + 更新
yq -i '(.spec.template.spec.containers[] | select(.name == "web") | .image) = "..."' file.yaml
# multi-document
yq 'select(.kind == "Deployment")' multi.yaml
yq ea '. as $i ireduce ({}; . * $i)' base.yaml override.yaml
# 変換
yq -o=json '.' file.yaml
yq -p=json '.' file.json
用語集
- yq (mikefarah)
- Go 製の YAML/JSON/XML 処理 CLI。jq とほぼ互換の式言語、ただし in-place 更新可能。最も普及。
- yq (kislyuk)
- Python 製、jq のラッパ。読み取り専用。mikefarah 版とは互換性なし。
yq --versionで見分ける。 - in-place 更新 (-i)
- ファイルを直接書き換える機能。コメントや書式を維持したまま値だけ更新。
- env() vs strenv()
- 環境変数の取り込み。env() は型推論あり(数値は number 化)、strenv() は強制 string。設定ファイルの version などは strenv 推奨。
- multi-document YAML
- 1 ファイルに
---で区切った複数 YAML ドキュメントを含める書式。k8s manifest の標準形。 - documentIndex
- multi-doc 時の各 document インデックス。
select(documentIndex == 0)で先頭だけ取れる。 - eval-all (ea)
- 全 document を 1 つのストリームとして処理するモード。複数 document 横断の集計に必要。
- load("file")
- 別 YAML/JSON ファイルを式の中で読み込む関数。merge やテンプレ展開に使う。
- マージ (*=)
- オブジェクトを再帰的にマージ。配列は要素を上書きせず連結する挙動(オプションで変更可)。
- -o / -p
- -o = output format(yaml/json/csv/props/xml)、-p = input format。拡張子が無い入力で必要。
- jq との違い
- jq は JSON 専用・read-only、yq は YAML/JSON/XML 対応・in-place 編集可能。jq 構文をほぼ流用できる。
- k8s manifest
- Kubernetes リソース定義 YAML。Deployment / Service / ConfigMap / Secret 等。multi-document で 1 ファイルにまとめることが多い。
- Helm values.yaml
- Helm Chart の設定ファイル。yq で環境別オーバーレイを生成・更新する用途で頻出。