yqによるYAML設定ファイルの編集
yqを使ってKubernetesやCIのYAMLを構造やコメントを保ったまま、その場で読み取り、修正します。
「yqによるYAML設定ファイルの編集」はCoddyKit上の無料Linux Command Line & Bash Scripting Masteryレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLinux Command Line & Bash Scripting Mastery学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Linux Command Line & Bash Scripting Masteryコースには全4レッスンが含まれています。
yqとは何か、YAMLに使う理由
yqは、jqがJSONを扱うのと同じようにYAMLを処理できる、移植性の高いコマンドラインYAMLプロセッサです。PythonやRubyでスクリプトを書かなくても、YAMLファイルの読み取り、フィルタリング、編集ができます。
yqという名前の一般的なツールは2つあります。
- 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はバージョン3と式の構文が異なるため、バージョンが重要です。
# 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 --versionKubernetes Deployment YAMLから値を読み取る
何かを編集する前に、YAMLフィールドの読み取り方を学びましょう。KubernetesのDeploymentが与えられた場合、ドット記法のパスを使って、入れ子になった任意の値を抽出できます。
例: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(in-place、ファイルを直接編集)です。これを付けない場合、yqは結果を標準出力に表示するだけで、ファイルは変更しません。
構文:
- 読み取りのみ(標準出力):
yq '.spec.replicas' file.yaml - ファイルを直接編集:
yq -i '.spec.replicas = 5' file.yaml
代入演算子=で値を設定します。この式は完全なyqフィルターなので、読み取りと書き込みを1回の処理にまとめられます。
重要: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で非常によく行う作業の1つが、新しいイメージをビルドした後にKubernetesマニフェストのDockerイメージタグを更新することです。yqを使えば、これを1行で実行できます。
基本パターン:
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マニフェストでは、---で区切った複数のリソースを1つのファイルにまとめることがよくあります。デフォルトでは、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の値を名前にしたファイルを、ドキュメントごとに1つ書き出します。
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.yamlGitHub ActionsのCI YAMLをパッチする
CI設定ファイル(.github/workflows/*.yml、.gitlab-ci.yml)もYAMLです。同じyqコマンドを使えますが、パスが深く入れ子になっている場合があります。
CIでよく行うパッチ:
- Runnerのバージョンを固定する:すべてのジョブの
runs-onを更新します。 - Actionのバージョンを更新する:特定のActionを使っているステップを見つけ、
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.ymlyqの式で環境変数を使う
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.yamlreplicasのような数値フィールドを設定する場合は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.yaml2つのYAMLファイルをマージする
ベース設定にパッチファイル(小さな上書き用YAML)を適用する必要が生じることがあります。たとえば、Kustomize形式のワークフローで環境ごとの上書きを適用する場合です。
yqでは、*マージ演算子を使って2つのファイルをマージできます。
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.yamlYAMLの検証とJSONへの変換
パッチを適用したYAMLをクラスターに適用する前に、検証し、必要に応じて他のツール向けにJSONへ変換するのがよい習慣です。
構文を検証する:
yq '.' file.yaml && echo "Valid"— yqは解析エラー時に終了コード1を返すため、CIのゲートで利用できます。
YAMLをJSONに変換する:
yq -o=json '.' file.yaml— 整形済みJSONを出力します。- さらにJSONを処理するには
jqへパイプします。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 '.'CIデプロイ用の完全なパッチスクリプト
ここまでのテクニックをすべて組み合わせて、GitOpsパイプラインの一部としてKubernetesのDeploymentマニフェストにパッチを適用する実際のCIスクリプトを作成します。
このスクリプトでは、次の処理を行います。
- 入力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 == "...")を使って1つのリソースを対象にし、他のリソースには触れないようにします。 - CI変数:文字列には
strenv(VAR)を、型付きの値にはenv(VAR)を使用すると、シェルのクォートに関するバグを避けられます。 - マージ:
. *= load("patch.yaml")で上書きファイルをディープマージし、パッチに含まれないキーを失わずに済みます。 - 検証と変換:リントゲートには
yq '.'を使用し、形式変換には-o=jsonと-Pを使用します。
CIでYAMLにパッチを適用する際の基本パターンは、検証 → select → 代入 → 検証です。これにstrenv()とselect()を組み合わせれば、壊れやすいsedのワンライナーに頼る必要はもうありません。
よくある質問
「yqによるYAML設定ファイルの編集」レッスンは無料ですか?
はい。「yqによるYAML設定ファイルの編集」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Linux Command Line & Bash Scripting Masteryコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Linux Command Line & Bash Scripting Masteryコースには全4レッスンが含まれています。
「yqによるYAML設定ファイルの編集」で何を学びますか?
yqを使ってKubernetesやCIのYAMLを構造やコメントを保ったまま、その場で読み取り、修正します。 ブラウザで直接実行するハンズオンコードでLinux Command Line & Bash Scripting Masteryを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Linux Command Line & Bash Scripting Masteryを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLinux Command Line & Bash Scripting Masteryは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「yqによるYAML設定ファイルの編集」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLinux Command Line & Bash Scripting Masteryレッスンでコードを書いて実行できますか?
はい。すべてのLinux Command Line & Bash Scripting Masteryレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- jqパイプラインによるJSONのフィルタリングと選択
- jqによるJSONオブジェクトの変換と構築
- curlとjqを組み合わせたREST APIの利用
- yqによるYAML設定ファイルの編集