Kubernetesクラスターを管理したり、GitHub Actionsワークフローを設定したり、Docker Composeファイルを書いたりしたことがあれば、 すでにYAMLを書いています—おそらくかなりの量を。YAMLは現代のDevOpsツールの大部分を支える設定フォーマットです。 しかし、どこにでも存在するにもかかわらず、常に人々を驚かせるフォーマットです。私もリリースがブロックされた深夜11時に YAMLのインデントエラーを何度もデバッグしてきました。同じ目に遭わないようにしましょう。

YAMLはYAML Ain't Markup Languageの略—そう、再帰的な頭字語です。元々は 「Yet Another Markup Language」でしたが、ドキュメントマークアップ言語ではなくデータシリアライズ形式であることを強調するために改名されました。 YAML 1.2仕様が現在の標準ですが、 多くのツールはまだYAML 1.1を実装しており、以下で説明する本当に危険な違いがあります。

基本:YAML構文の概観

YAMLはインデント(スペースのみ—タブは絶対に使わない)を使って構造を表現します。YAMLドキュメントはマッピング(キーと値のペア)、 シーケンス(リスト)、またはスカラー(単一の値)です。以下は必要なものすべてをカバーした実際のKubernetesスタイルの設定です:

yaml
# This is a comment — YAML supports them, JSON does not
app:
  name: payment-service
  version: "2.1.0"         # quoted to keep it a string
  port: 8080
  debug: false
  timeout: 30.5
  tags:
    - payments
    - backend
    - critical
  database:
    host: postgres.internal
    port: 5432
    ssl: true
    password: null          # explicitly no value

中括弧なし、ほとんどの文字列に引用符なし、カンマなし。毎日人間が編集するファイルにとって、その明快さは積み重なります。 ただしYAMLはその読みやすさの代償として複雑さを抱えています—内部ではかなりのことが起きています。

スカラー型:文字列、数値、ブール値、null

YAMLは値の見た目から型を推論します。これはほとんどの場合便利ですが、 いくつかの特定のケースでは静かに壊滅的な結果をもたらします。

yaml
# Strings — quotes are optional unless value is ambiguous
name: Alice
greeting: "Hello, world"
message: 'single quotes work too'
path: /usr/local/bin           # unquoted — still a string

# Numbers
integer: 42
negative: -7
float: 3.14159
scientific: 6.022e23

# Booleans
ssl_enabled: true
verbose: false

# Null
api_key: null
legacy_field: ~               # tilde is also null in YAML
ノルウェー問題: YAML 1.1(PyYAMLや多くの古いツールが使用)では、引用符なしの値 yesnoonofftruefalseynYN—および大文字バリアント—はすべてブール値として解析されます。 つまりISOの国コードNO(ノルウェー)がブール値falseになってしまいます。YAML 1.2はこれを修正しました。 ブール値のように見える文字列は常に引用符で囲んでください。詳細は ノルウェー問題に関するWikipediaの記事 をご覧ください。
yaml
# YAML 1.1 implicit type coercion — these silently become booleans:
country: NO       # → false  (Norway Problem!)
enabled: yes      # → true
toggle: on        # → true

# The fix: always quote when there's any ambiguity
country: "NO"
enabled: "yes"
version: "1.0"    # also quote version numbers — 1.0 would be a float

シーケンス:YAMLのリスト

リストはハイフンスペースのプレフィックスを使います。各アイテムはスカラー、マッピング、または別のシーケンスにできます:

yaml
# Simple list
languages:
  - Python
  - Go
  - TypeScript

# List of objects (common in Kubernetes)
containers:
  - name: api
    image: my-api:latest
    port: 8080
  - name: sidecar
    image: envoy:v1.28
    port: 9901

# Inline flow style (valid YAML, less readable)
tags: [payments, backend, v2]

複数行文字列:リテラルブロックとフォールデッドブロック

ここでYAMLが設定ファイルにおいてJSONより優れている点があります。2つの特別な演算子が複数行文字列を優雅に処理します:

yaml
# Literal block scalar (|) — preserves newlines exactly
startup_script: |
  #!/bin/bash
  set -e
  echo "Starting service..."
  npm start

# Folded scalar (>) — folds newlines into spaces (good for long descriptions)
description: >
  This service handles payment processing
  for all regions. It connects to Stripe
  and falls back to PayPal.
# Result: "This service handles payment processing for all regions. It connects to Stripe and falls back to PayPal."

# Chomp modifiers
keep_trailing: |+
  line one
  line two

strip_trailing: |-
  line one
  line two

|演算子はGitHub ActionsのマルチラインのRun:スクリプトを読みやすくするものです。 yaml-multiline.infoのチートシートは どのチョンプ修飾子が何をするかを素早く確認するのに最適です。これらのブロックスカラーがなければ、 1つの文字列にエスケープされた改行を書くことになります—JSONがそうさせるように。

タブ vs スペース — 基本ルール

YAMLはインデントにタブを禁止しています。 完全に。YAMLファイルのインデントのどこかにタブ文字が挿入されると、 ファイルのパースが失敗するか—最悪の場合—誤ってパースされます。 .ymlおよび.yamlファイルにスペースを使用するようにエディタを設定してください。2スペースが ほぼ普遍的な慣習です。

これがYAMLの不可解なエラーの最大の原因です。ほとんどのエディタではタブとスペースが見た目上同一です。 YAMLをデバッグする際はエディタで「空白文字を表示」を有効にするか、ファイルを YAML バリデータに貼り付けて正確な行を指摘する明確なエラーメッセージを確認してください。

実例:GitHub Actionsワークフロー

実際のGitHub Actionsワークフローのスニペットです。マルチラインのrun: ブロックがリテラルブロックスカラーを使用し、インデントが構造を決定していることに注目してください:

yaml
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: |
          npm run lint
          npm run test -- --coverage
          npm run build

実例:Kubernetesデプロイメントマニフェスト

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-api
  namespace: production
  labels:
    app: payment-api
    version: "2.1.0"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payment-api
  template:
    metadata:
      labels:
        app: payment-api
    spec:
      containers:
        - name: api
          image: payment-api:2.1.0
          ports:
            - containerPort: 8080
          env:
            - name: NODE_ENV
              value: production
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: password
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"

PythonとJavaScriptでYAMLを解析する

Pythonでは、PyYAMLライブラリが 標準的な選択肢です。常にsafe_load()を使用し、load()は使わないでください— 安全でないバージョンはYAMLファイルから任意のPythonコードを実行できます:

python
import yaml

# Reading a YAML config file
with open('config.yaml', 'r') as f:
    config = yaml.safe_load(f)

print(config['app']['name'])        # payment-service
print(config['app']['port'])        # 8080 (integer, not string)
print(config['app']['tags'])        # ['payments', 'backend', 'critical']

# Writing Python data to YAML
data = {
    'service': 'auth-api',
    'replicas': 2,
    'endpoints': ['/login', '/logout', '/refresh']
}
with open('output.yaml', 'w') as f:
    yaml.dump(data, f, default_flow_style=False)

JavaScript/Node.jsでは、js-yaml が最も広く使われているライブラリです:

js
import yaml from 'js-yaml';
import fs from 'fs';

// Parse YAML string
const raw = fs.readFileSync('config.yaml', 'utf8');
const config = yaml.load(raw);

console.log(config.app.name);     // payment-service
console.log(config.app.tags);     // ['payments', 'backend', 'critical']

// Dump an object to YAML string
const output = yaml.dump({
  name: 'my-service',
  port: 3000,
  tags: ['api', 'public']
});
console.log(output);

まとめ

YAMLのインデントベースの構文、コメントのサポート、読みやすい複数行文字列は、 人間が書いて管理する設定ファイルに最適な選択肢です。ただし本当の落とし穴があります: ノルウェー問題、タブとスペースの混乱、YAML 1.1パーサーによる暗黙的な型変換。 ルールを知り、あいまいなものはすべて引用符で囲み、エディタで空白文字を表示するように設定し、 YAML フォーマッターでファイルの一貫性を保ちましょう。 YAMLはどこで噛みつくかを理解すれば強力なツールです。