Hvis du nogensinde har administreret et Kubernetes-kluster, konfigureret et GitHub Actions-workflow, eller skrevet en Docker Compose-fil, har du allerede skrevet YAML — sandsynligvis meget af det. YAML er konfigurationsformatet, der driver det meste af moderne DevOps-værktøj. Men på trods af at det er overalt, er det et format, der konstant overrasker folk. Jeg har fejlsøgt mere end min del af YAML-indrykningsfejl kl. 23 med en blokeret udrulning. Lad os sørge for, at du ikke behøver det.

YAML står for YAML Ain't Markup Language — ja, det er et rekursivt akronym. Det hed oprindeligt "Yet Another Markup Language", men blev omdøbt for at understrege, at det er et dataserialiserings-format, ikke et dokumentopmærkningssprog. YAML 1.2-specifikationen er den nuværende standard, selvom mange værktøjer stadig implementerer YAML 1.1, som har nogle virkelig farlige forskelle, vi dækker nedenfor.

Grundlaget: YAML-syntaks i korte træk

YAML bruger indrykning (kun mellemrum — aldrig tabulator) til at udtrykke struktur. Et YAML-dokument er en mapping (nøgle-værdi-par), en sekvens (en liste) eller en skalar (en enkelt værdi). Her er en virkelig Kubernetes-lignende konfiguration, der dækker det hele:

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

Ingen klammer, ingen anførselstegn på de fleste strenge, ingen kommaer. For en fil, som mennesker redigerer hver dag, summerer den klarhed hurtigt. Men YAML betaler for den læsbarhed med kompleksitet — der sker en del under motorhjelmen.

Skalærtyper: Strenge, tal, booleaner, null

YAML udleder typer fra værdiens udseende. Det er praktisk det meste af tiden og stille katastrofalt i et par specifikke tilfælde.

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
Norge-problemet: I YAML 1.1 (bruges af PyYAML og mange ældre værktøjer) fortolkes de uciterede værdier yes, no, on, off, true, false, y, n, Y, N — og deres store varianter — alle som booleaner. Det betyder, at ISO-landkoden NO (Norge) bliver booleanen false. YAML 1.2 rettede dette. Citér altid strenge, der ligner booleaner. Se Wikipedias artikel om Norge-problemet for hele historien.
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

Sekvenser: Lister i YAML

Lister bruger et bindestreg-mellemrum-præfiks. Hvert element kan være en skalar, en mapping eller en anden sekvens:

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]

Flerlinjestrenge: Bogstavelig blok vs. foldet

Her er YAML foran JSON for konfigurationsfiler. To specielle operatorer håndterer flerlinjestrenge 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

Operatoren | er det, der gør GitHub Actions' flerlinjede run:-scripts læsbare. Cheat-sheetet yaml-multiline.info er den hurtigste måde at huske, hvilken chomp-modifikator der gør hvad. Uden disse blokkede skalarer ville du skrive escapede linjeskift i en enkelt streng — hvilket er, hvad JSON tvinger dig til.

Tabulatorer vs. mellemrum — Den kardinale regel

YAML forbyder tabulatorer til indrykning. Fuldstændigt. Hvis din editor indsætter et tabulatortegn et sted i en YAML-fils indrykning, vil filen enten mislykkes at analysere eller — værre — analysere forkert. Konfigurér din editor til at bruge mellemrum for .yml- og .yaml-filer. To mellemrum er næsten universel konvention.

Dette er årsag nummer et til kryptiske YAML-fejl. En tabulatortast ser identisk ud som mellemrum i de fleste editorer. Aktivér "vis tegn for blanktegn" i din editor, når du fejlsøger YAML, eller indsæt din fil i YAML-validatoren for at få en tydelig fejlmeddelelse, der peger på den nøjagtige linje.

Virkeligt eksempel: GitHub Actions-workflow

Her er et virkeligt GitHub Actions-workflow-uddrag. Bemærk, hvordan den flerlinjede run:-blok bruger den bogstavelige blokskalar, og hvordan indrykning bestemmer strukturen:

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

Virkeligt eksempel: 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"

Parsning af YAML i Python og JavaScript

I Python er biblioteket PyYAML standardvalget. Brug altid safe_load(), ikke load() — den usikre version kan køre vilkårlig Python-kode fra en YAML-fil:

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)

I JavaScript/Node.js er js-yaml det mest udbredt anvendte bibliotek:

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

Afslutning

YAMLs indrykningsbaserede syntaks, understøttelse af kommentarer og læsbare flerlinjestrenge gør det til det rette valg for konfigurationsfiler, som mennesker skriver og vedligeholder. Men det kommer med virkelige faldgruber: Norge-problemet, forvirring med tabulatorer/mellemrum og implicit typetvang fra YAML 1.1-parsere. Kend reglerne, citér alt tvetydigt, konfigurér din editor til at vise blanktegn, og brug en YAML-formatering til at holde filer konsistente. YAML er et kraftfuldt værktøj, når du forstår, hvor det bider.