0Pricing
Linux Command Line & Bash Scripting Mastery · レッスン

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 --version

Kubernetes 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.yaml

GitHub 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.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

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

2つの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.yaml

YAMLの検証と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スクリプトを作成します。

このスクリプトでは、次の処理を行います。

  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"

理解度チェック:安全な複数ドキュメント編集

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. jqパイプラインによるJSONのフィルタリングと選択
  2. jqによるJSONオブジェクトの変換と構築
  3. curlとjqを組み合わせたREST APIの利用
  4. yqによるYAML設定ファイルの編集
← Linux Command Line & Bash Scripting Masteryに戻る