Bir YAML bloğunu dosyanın bir yerinden başka bir yerine kopyaladıysanız, anchor'ların ve alias'ların çözdüğü sorunla zaten karşılaşmışsınızdır. Büyük Kubernetes yapılandırmaları, çok ortamlı Docker Compose dosyaları ve karmaşık CI pipeline'ları aynı blokları — kaynak sınırları, ortam değişkenleri, birim bağlamaları — defalarca tekrar etme eğilimindedir. YAML'ın bunun için yerleşik bir çözümü var ve çoğu geliştirici bunun varlığından habersiz.

Anchor'lar (&) ve alias'lar (*), YAML'ın bir değeri bir kez tanımlayıp aynı dosyanın herhangi bir yerinde referans almak için kullandığı mekanizmadır. Anchor'ı değişken bildirmek, alias'ı ise kullanmak olarak düşünebilirsiniz. Merge key (<<) bunu nesne birleştirmeye genişletir — JavaScript'in spread operatörüne benzer. Her iki özellik de YAML 1.2 spesifikasyonunun node anchor bölümünde tanımlanmıştır.

Temel Anchor ve Alias Sözdizimi

Sözdizimi minimalisttir. Bir anchor oluşturmak için değerin önüne &ad ekleyin, ardından belgenin herhangi bir yerinde referans almak için *ad kullanın:

yaml
# Define the anchor once
default_timeout: &timeout 30

# Reference it multiple times
services:
  api:
    timeout: *timeout      # → 30
  worker:
    timeout: *timeout      # → 30
  scheduler:
    timeout: *timeout      # → 30

YAML ayrıştırıcısı bunu okuduğunda her alias, anchor ile aynı değere çözümlenir. Anchor'ı değiştirin ve tüm alias'lar güncellenir. Arama-değiştirme gerekmez.

<< Anahtarıyla Nesne Birleştirme

Skalar yeniden kullanım faydalıdır, ancak gerçek güç tüm mapping bloklarının birleştirilmesinden gelir. << merge key, başvurulan anchor'daki tüm anahtar-değer çiftlerini mevcut mapping'e alır:

yaml
# Define a base configuration block
base_service: &base
  restart: unless-stopped
  logging:
    driver: json-file
    options:
      max-size: "10m"
      max-file: "3"
  networks:
    - app-network

# Merge it into specific services
services:
  api:
    <<: *base              # merge all keys from base_service
    image: my-api:latest
    ports:
      - "8080:8080"

  worker:
    <<: *base              # same base config
    image: my-worker:latest
    command: ["node", "worker.js"]

  scheduler:
    <<: *base              # and again
    image: my-scheduler:latest
    command: ["node", "cron.js"]

Mapping'de doğrudan tanımlanan anahtarlar, birleştirilen anchor'dan gelen anahtarları geçersiz kılar. Yani base restart: unless-stopped ayarlıyor ve servis de restart: no ayarlıyorsa, servis düzeyindeki değer kazanır.

Öncesi ve Sonrası: Gerçek Dünyada Docker Compose

Tipik bir çok servisli Docker Compose dosyasının anchor olmadan nasıl göründüğü — tekrarlarla dolu:

yaml
# BEFORE — repetitive and hard to maintain
version: "3.9"
services:
  api:
    restart: unless-stopped
    env_file: .env
    networks: [app-network]
    logging:
      driver: json-file
      options:
        max-size: "10m"
    depends_on:
      - postgres

  worker:
    restart: unless-stopped
    env_file: .env
    networks: [app-network]
    logging:
      driver: json-file
      options:
        max-size: "10m"
    depends_on:
      - postgres

  mailer:
    restart: unless-stopped
    env_file: .env
    networks: [app-network]
    logging:
      driver: json-file
      options:
        max-size: "10m"
    depends_on:
      - postgres

Şimdi anchor'lar ve merge key ile — her tekrar eden blok tam olarak bir kez tanımlanır:

yaml
# AFTER — DRY and easy to maintain
version: "3.9"

x-common: &common
  restart: unless-stopped
  env_file: .env
  networks: [app-network]
  logging:
    driver: json-file
    options:
      max-size: "10m"
  depends_on:
    - postgres

services:
  api:
    <<: *common
    image: my-api:2.4.1
    ports:
      - "8080:8080"

  worker:
    <<: *common
    image: my-worker:2.4.1
    command: ["node", "worker.js"]

  mailer:
    <<: *common
    image: my-mailer:2.4.1
    command: ["node", "mailer.js"]
İpucu: x-common gibi genişletme alanlarındaki x- öneki, Compose'un bloğu bir servis tanımı olarak ayrıştırmaya çalışmasını önleyen bir Docker Compose kuralıdır. Compose motoru tarafından görmezden gelinir ancak YAML anchor olarak tam anlamıyla kullanılabilir.

GitHub Actions: Anchor'larla Matrix Strategy

CI yapılandırması da anchor'ların işe yaradığı bir alandır. Birden fazla job üzerinde ortak adım yapılandırmasını yeniden kullanan bir GitHub Actions iş akışı:

yaml
name: Build and Test

on: [push, pull_request]

# Shared setup steps
x-setup-steps: &setup-steps
  - uses: actions/checkout@v4
  - uses: actions/setup-node@v4
    with:
      node-version: "20"
      cache: npm
  - run: npm ci

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - *setup-steps
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - *setup-steps
      - run: npm test -- --coverage

  build:
    runs-on: ubuntu-latest
    steps:
      - *setup-steps
      - run: npm run build

Not: GitHub Actions'ın YAML ayrıştırıcısı anchor'ları ve alias'ları destekler. Ancak bazı CI sistemleri (özellikle sürüm 2.1 öncesi CircleCI'ın config.yml'i) kendi anchor benzeri uzantı sözdizimine sahipti. Her zaman kullandığınız aracın belgelerini kontrol edin.

Kubernetes: Kaynak Sınırlarını Yeniden Kullanma

Kubernetes manifestlerinde kaynak sınırları ve ortam değişkenleri, anchor için birincil adaylardır. Düzenli olarak kullandığım bir kalıp:

yaml
# Anchors at the top of the file (or in a shared ConfigMap generator)
x-resources:
  small: &resources-small
    requests:
      memory: "64Mi"
      cpu: "50m"
    limits:
      memory: "256Mi"
      cpu: "200m"
  large: &resources-large
    requests:
      memory: "256Mi"
      cpu: "200m"
    limits:
      memory: "1Gi"
      cpu: "1000m"

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  template:
    spec:
      containers:
        - name: frontend
          image: frontend:latest
          resources: *resources-small    # reuse small profile

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  template:
    spec:
      containers:
        - name: api
          image: api:latest
          resources: *resources-large    # reuse large profile

Çoklu Birleştirme ve Geçersiz Kılma Önceliği

Tek bir mapping'de birden fazla anchor'dan birleştirme yapabilirsiniz. Bunları << altında liste olarak sağlayın. Listede önceki girişler, yinelenen anahtarlar için sonraki girişlere göre öncelik taşır:

yaml
defaults: &defaults
  color: blue
  size: medium
  weight: light

overrides: &overrides
  color: red          # will override defaults.color
  weight: heavy       # will override defaults.weight

result:
  <<: [*overrides, *defaults]    # overrides takes priority
  name: widget
# Result: color=red, size=medium, weight=heavy, name=widget

Bilmeniz Gereken Sınırlamalar

  • Yalnızca aynı dosya. Anchor'lar ve alias'lar yalnızca tek bir YAML belge akışı içinde çalışır. Farklı bir dosyadan anchor'a referans veremezsiniz. Dosyalar arası yeniden kullanım için araçınızın kendi mekanizmasına ihtiyacınız vardır (örn. Helm şablonları, Kustomize veya ytt gibi YAML işlemcileri).
  • Hesaplanmış değer yok. Alias'lar, anchor'ın değerinin tam kopyalarına çözümlenir. Enterpolasyon veya şablon mantığı yoktur — bunun için Helm veya Jinja2 gibi araçlar gerekir.
  • Merge key bir YAML uzantısıdır. << merge key, temel spesifikasyonda değil bir YAML 1.1 uzantısında tanımlanmıştır. Çoğu ayrıştırıcı destekler, ancak katı şekilde spesifikasyona uyan YAML 1.2 ayrıştırıcıları desteklemeyebilir.
  • Döngüsel referanslar ayrıştırıcıları çökertir. Bir düğümü anchor yapmaya ve ardından içinden referans almaya çalışmayın. Teknik olarak geçersizdir.
  • Alias'lar kopyalar, referans almaz. Kodunuzdaki çözümlenmiş bir alias değerini değiştirmek anchor'ı veya diğer alias'ları değiştirmez. Ayrıştırma sonrası bağımsız değerlerdir.

Özet

YAML anchor'ları ve alias'ları, biçimin en az kullanılan özelliklerinden biridir. Aynı yapılandırma bloğunun ikiden fazla göründüğü, 50 satırdan uzun herhangi bir YAML dosyasında anchor'lar neredeyse kesinlikle yere aittir. Bakım kolaylığı açısından öncesi/sonrası farkı çarpıcıdır — tüm dosyayı taramak yerine bir kaynak sınırı profilini veya paylaşılan bir ortam değişkenini tek bir yerden değiştirmek. Anchor'lı dosyalarınızı düzenli tutmak için YAML Formatter'ı, anchor referanslarınızın doğru çözümlendiğini doğrulamak için YAML Validator'ı kullanın.