Wenn Sie jemals einen Kubernetes-Cluster verwaltet, einen GitHub Actions-Workflow eingerichtet oder eine Docker Compose-Datei geschrieben haben, haben Sie bereits YAML geschrieben — wahrscheinlich jede Menge davon. YAML ist das Konfigurationsformat, das den Großteil der modernen DevOps-Tools antreibt. Aber obwohl es überall ist, ist es ein Format, das Menschen ständig überrascht. Ich habe mehr als meinen Anteil an YAML-Einrückungsfehlern um 23 Uhr debuggt, während ein Deployment blockiert war. Lassen Sie uns sicherstellen, dass Ihnen das nicht passiert.

YAML steht für YAML Ain't Markup Language — ja, es ist ein rekursives Akronym. Ursprünglich war es "Yet Another Markup Language", wurde aber umbenannt, um zu betonen, dass es ein Datenserialisierungsformat ist, keine Dokumenten-Markup-Sprache. Die YAML 1.2-Spezifikation ist der aktuelle Standard, obwohl viele Tools noch YAML 1.1 implementieren, das einige wirklich gefährliche Unterschiede hat, die wir weiter unten behandeln.

Die Grundlagen: YAML-Syntax auf einen Blick

YAML verwendet Einrückung (nur Leerzeichen — niemals Tabs), um Struktur auszudrücken. Ein YAML-Dokument ist ein Mapping (Schlüssel-Wert-Paare), eine Sequenz (eine Liste) oder ein Skalar (ein einzelner Wert). Hier ist eine echte Kubernetes-artige Konfiguration, die alle Grundlagen abdeckt:

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

Keine geschweiften Klammern, keine Anführungszeichen bei den meisten Strings, keine Kommas. Für eine Datei, die Menschen täglich bearbeiten, summiert sich diese Klarheit schnell. Aber YAML bezahlt diese Lesbarkeit mit Komplexität — unter der Haube passiert viel.

Skalartypen: Strings, Zahlen, Booleans, Null

YAML leitet Typen aus dem Erscheinungsbild des Werts ab. Das ist meistens praktisch und in einigen spezifischen Fällen still katastrophal.

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
Das Norwegen-Problem: In YAML 1.1 (verwendet von PyYAML, vielen älteren Tools) werden die nicht-angeführten Werte yes, no, on, off, true, false, y, n, Y, N — und ihre Großschreibvarianten — alle als Booleans geparst. Das bedeutet, dass der ISO-Ländercode NO (Norwegen) zu Boolean false wird. YAML 1.2 hat das behoben. Setzen Sie immer Anführungszeichen bei Strings, die wie Booleans aussehen. Siehe den Wikipedia-Eintrag zum Norwegen-Problem für die vollständige Hintergrundgeschichte.
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

Sequenzen: Listen in YAML

Listen verwenden ein Bindestrich-Leerzeichen-Präfix. Jedes Element kann ein Skalar, ein Mapping oder eine andere Sequenz sein:

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]

Mehrzeilige Strings: Literal-Block vs. Gefalteter Block

Hier übertrifft YAML JSON bei Konfigurationsdateien. Zwei spezielle Operatoren behandeln mehrzeilige Strings elegant:

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

Der |-Operator macht die mehrzeiligen run:-Skripte von GitHub Actions lesbar. Das yaml-multiline.info-Cheatsheet ist der schnellste Weg, sich zu merken, welcher Chomp-Modifikator was tut. Ohne diese Block-Skalare müssten Sie escapte Zeilenumbrüche in einen einzelnen String schreiben — was JSON von Ihnen verlangt.

Tabs vs. Leerzeichen — Die Kardinalregel

YAML verbietet Tabs für die Einrückung. Vollständig. Wenn Ihr Editor ein Tab-Zeichen in der Einrückung einer YAML-Datei einfügt, wird die Datei entweder nicht geparst oder — schlimmer — falsch geparst. Konfigurieren Sie Ihren Editor so, dass er Leerzeichen für .yml- und .yaml-Dateien verwendet. Zwei Leerzeichen ist die nahezu universelle Konvention.

Dies ist die häufigste Ursache für kryptische YAML-Fehler. Ein Tab sieht in den meisten Editoren identisch wie Leerzeichen aus. Aktivieren Sie "Leerzeichen anzeigen" in Ihrem Editor beim Debuggen von YAML, oder fügen Sie Ihre Datei in den YAML-Validator ein, um eine klare Fehlermeldung zu erhalten, die auf die genaue Zeile zeigt.

Echtes Beispiel: GitHub Actions-Workflow

Hier ist ein echter GitHub Actions-Workflow-Ausschnitt. Beachten Sie, wie der mehrzeilige run:-Block den Literal-Block-Skalar verwendet und wie Einrückung die Struktur bestimmt:

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

Echtes Beispiel: Kubernetes-Deployment-Manifest

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"

YAML in Python und JavaScript parsen

In Python ist die PyYAML-Bibliothek die Standardwahl. Verwenden Sie immer safe_load(), nicht load() — die unsichere Version kann beliebigen Python-Code aus einer YAML-Datei ausführen:

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)

In JavaScript/Node.js ist js-yaml die am weitesten verbreitete Bibliothek:

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);

Fazit

YAMLs einrückungsbasierte Syntax, Unterstützung für Kommentare und lesbare mehrzeilige Strings machen es zur richtigen Wahl für Konfigurationsdateien, die Menschen schreiben und pflegen. Aber es hat echte Fallstricke: das Norwegen-Problem, Tab/Leerzeichen-Verwirrung und implizite Typumwandlung durch YAML 1.1-Parser. Lernen Sie die Regeln, setzen Sie alles Mehrdeutige in Anführungszeichen, konfigurieren Sie Ihren Editor so, dass er Leerzeichen anzeigt, und verwenden Sie einen YAML-Formatierer, um Dateien konsistent zu halten. YAML ist ein mächtiges Werkzeug, wenn Sie verstehen, wo es zubeißt.