Bir Kubernetes kümesi yönettiyseniz, bir GitHub Actions iş akışı kurduysanız ya da bir Docker Compose dosyası yazdıysanız, zaten YAML yazmışsınızdır — muhtemelen çok fazla. YAML, modern DevOps araçlarının büyük bölümüne güç veren yapılandırma biçimidir. Ancak her yerde olmasına rağmen insanları sürekli şaşırtan bir biçimdir. Bir deploy bloke olmuşken gece 11'de YAML girinti hatalarını ayıkladığım sayısız anı vardır. Sizin de böyle bir durumla karşılaşmamanız için buradayız.

YAML, YAML Ain't Markup Language (YAML İşaretleme Dili Değildir) ifadesinin kısaltmasıdır — evet, özyinelemeli bir kısaltma. Başlangıçta "Yet Another Markup Language" (Bir Başka İşaretleme Dili) idi ancak bir belge işaretleme dili değil, veri serileştirme biçimi olduğunu vurgulamak için yeniden adlandırıldı. YAML 1.2 spesifikasyonu güncel standarttır; ancak pek çok araç hâlâ YAML 1.1 uygulamaktadır ve bu sürümün aşağıda ele alacağımız bazı gerçekten tehlikeli farklılıkları vardır.

Temel Bilgiler: YAML Sözdizimi Bir Bakışta

YAML, yapıyı ifade etmek için girinti kullanır (yalnızca boşluk — asla sekme). YAML belgesi bir mapping (anahtar-değer çiftleri), bir sequence (liste) ya da scalar (tek bir değer) olabilir. Tüm temel unsurları kapsayan Kubernetes tarzı gerçek bir yapılandırma örneği:

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

Süslü parantez yok, çoğu dizede tırnak yok, virgül yok. Her gün insanların düzenlediği bir dosya için bu açıklık büyük fark yaratır. Ancak YAML bu okunabilirliği karmaşıklıkla öder — arka planda pek çok şey döner.

Skalar Türler: Dizeler, Sayılar, Booleanlar, Null

YAML, türleri değerin görünümünden çıkarır. Bu çoğu zaman kullanışlıdır ve bazı özel durumlarda sessizce felakete yol açar.

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
Norveç Sorunu: YAML 1.1'de (PyYAML ve pek çok eski araç tarafından kullanılır), tırnaksız değerler olan yes, no, on, off, true, false, y, n, Y, N — ve büyük harf varyantları — hepsi boolean olarak ayrıştırılır. Bu, ISO ülke kodu NO'nun (Norveç) boolean false'a dönüştüğü anlamına gelir. YAML 1.2 bunu düzeltti. Boolean gibi görünen dizeleri her zaman tırnakla belirtin. Tam hikayeyi Norveç Sorunu hakkındaki Wikipedia makalesinde okuyabilirsiniz.
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

Sequence'lar: YAML'de Listeler

Listeler kısa çizgi-boşluk öneki kullanır. Her öğe bir skalar, bir mapping veya başka bir sequence olabilir:

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]

Çok Satırlı Dizeler: Literal Block ve Folded

Yapılandırma dosyaları söz konusu olduğunda YAML burada JSON'ı geride bırakır. İki özel operatör çok satırlı dizeleri zarif biçimde işler:

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

| operatörü, GitHub Actions'ın çok satırlı run: betiklerini okunabilir kılan şeydir. yaml-multiline.info hile sayfası, hangi chomp değiştiricisinin ne işe yaradığını hatırlamanın en hızlı yoludur. Bu blok skalalar olmadan, tek bir dizeye kaçış karakterli yeni satırlar yazmanız gerekirdi — JSON'ın sizi buna zorladığı gibi.

Sekme ve Boşluk — Temel Kural

YAML, girinti için sekme kullanımını tamamen yasaklar. Editörünüz bir YAML dosyasının girintisine herhangi bir sekme karakteri eklerse, dosya ya ayrıştırılamaz ya da — daha kötüsü — yanlış ayrıştırılır. Editörünüzü .yml ve .yaml dosyaları için boşluk kullanacak şekilde yapılandırın. İki boşluk, neredeyse evrensel bir kuraldır.

Bu, şifreli YAML hatalarının 1 numaralı nedenidir. Çoğu editörde sekme, boşluklarla aynı görünür. YAML'da hata ayıklarken editörünüzde "boşluk karakterlerini göster" seçeneğini etkinleştirin ya da dosyanızı YAML Validator'a yapıştırarak tam satırı gösteren net bir hata mesajı alın.

Gerçek Örnek: GitHub Actions İş Akışı

İşte gerçek bir GitHub Actions iş akışı parçacığı. Çok satırlı run: bloğunun literal block scalar kullandığına ve girintinin yapıyı nasıl belirlediğine dikkat edin:

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

Gerçek Örnek: Kubernetes Deployment Manifesti

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 ve JavaScript'te YAML Ayrıştırma

Python'da, PyYAML kütüphanesi standart tercihtir. Her zaman load() yerine safe_load() kullanın — güvensiz sürüm bir YAML dosyasından rastgele Python kodu çalıştırabilir:

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'de, js-yaml en yaygın kullanılan kütüphanedir:

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

Özet

YAML'ın girintiye dayalı sözdizimi, yorum desteği ve okunabilir çok satırlı dizeleri, onu insanların yazdığı ve bakımını yaptığı yapılandırma dosyaları için doğru seçim haline getirir. Ancak gerçek tuzakları da beraberinde getirir: Norveç Sorunu, sekme/boşluk karışıklığı ve YAML 1.1 ayrıştırıcılarının örtük tür zorlaması. Kuralları bilin, belirsiz olan her şeyi tırnakla belirtin, editörünüzü boşlukları gösterecek şekilde yapılandırın ve dosyaları tutarlı tutmak için YAML Formatter kullanın. Nerede ısırdığını anladıktan sonra YAML güçlü bir araçtır.