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スタイルの設定です:
# 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は値の見た目から型を推論します。これはほとんどの場合便利ですが、 いくつかの特定のケースでは静かに壊滅的な結果をもたらします。
# 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 YAMLyes、no、on、off、true、false、
y、n、Y、N—および大文字バリアント—はすべてブール値として解析されます。
つまりISOの国コードNO(ノルウェー)がブール値falseになってしまいます。YAML 1.2はこれを修正しました。
ブール値のように見える文字列は常に引用符で囲んでください。詳細は
ノルウェー問題に関するWikipediaの記事
をご覧ください。# 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のリスト
リストはハイフンスペースのプレフィックスを使います。各アイテムはスカラー、マッピング、または別のシーケンスにできます:
# 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つの特別な演算子が複数行文字列を優雅に処理します:
# 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 スペース — 基本ルール
.ymlおよび.yamlファイルにスペースを使用するようにエディタを設定してください。2スペースが
ほぼ普遍的な慣習です。これがYAMLの不可解なエラーの最大の原因です。ほとんどのエディタではタブとスペースが見た目上同一です。 YAMLをデバッグする際はエディタで「空白文字を表示」を有効にするか、ファイルを YAML バリデータに貼り付けて正確な行を指摘する明確なエラーメッセージを確認してください。
実例:GitHub Actionsワークフロー
実際のGitHub Actionsワークフローのスニペットです。マルチラインのrun:
ブロックがリテラルブロックスカラーを使用し、インデントが構造を決定していることに注目してください:
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デプロイメントマニフェスト
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コードを実行できます:
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 が最も広く使われているライブラリです:
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はどこで噛みつくかを理解すれば強力なツールです。