Om du någonsin har kopierat ett YAML-block från ett ställe i en fil till ett annat, har du redan stött på problemet som ankare och alias löser. Stora Kubernetes-konfigurationer, multi-miljö Docker Compose-filer och komplexa CI-pipelines tenderar att upprepa samma block — resursbegränsningar, miljövariabler, volymmonteringar — om och om igen. YAML har ett inbyggt svar på detta, och de flesta utvecklare vet inte att det finns.
Ankare (&) och alias (*) är YAMLs mekanism för att definiera ett värde en gång och
referera till det var som helst i samma fil. Tänk på ett ankare som att deklarera en variabel och ett alias som att använda den.
Sammanslagningsnyckeln (<<) utökar detta till objektsammanslagning — liknande JavaScripts spread-operator.
Båda funktionerna är definierade i YAML 1.2-specifikationens avsnitt om nodankare.
Grundläggande ankare- och alias-syntax
Syntaxen är minimal. Prefixera ett värde med &name för att skapa ett ankare,
använd sedan *name var som helst i dokumentet för att referera till det:
# Define the anchor once
default_timeout: &timeout 30
# Reference it multiple times
services:
api:
timeout: *timeout # → 30
worker:
timeout: *timeout # → 30
scheduler:
timeout: *timeout # → 30När en YAML-parser läser detta löser varje alias upp till exakt samma värde som ankaret. Ändra ankaret och alla alias uppdateras. Ingen söka-och-ersätta behövs.
Sammanslagning av objekt med nyckeln <<
Skalär-återanvändning är användbart, men den verkliga kraften kommer från att slå samman hela mappningsblock.
Sammanslagningsnyckeln << absorberar alla nyckel-värde-par från det refererade ankaret in i den aktuella mappningen:
# 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"]Nycklar definierade direkt i mappningen åsidosätter nycklar från det sammanslagna ankaret.
Så om base sätter restart: unless-stopped och tjänsten också sätter
restart: no, vinner värdet på tjänstenivå.
Före och efter: Docker Compose i verkligheten
Så här ser en typisk multi-tjänst Docker Compose-fil ut utan ankare — full av upprepningar:
# 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:
- postgresNu med ankare och sammanslagningsnyckeln — varje upprepat block är definierat exakt en gång:
# 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"]x- på
tilläggsfält
(som x-common) är en Docker Compose-konvention som förhindrar att Compose försöker tolka blocket som en tjänstedefinition.
Det ignoreras av Compose-motorn men är fullt användbart som ett YAML-ankare.GitHub Actions: Matrisstrategi med ankare
CI-konfiguration är ett annat ställe där ankare lönar sig. Här är ett GitHub Actions-arbetsflöde som återanvänder gemensam stegkonfiguration över flera jobb:
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 buildObservera: GitHub Actions' YAML-parser
stöder ankare och alias. Vissa CI-system
(framförallt CircleCIs config.yml före version 2.1) hade sin egen ankare-liknande tilläggssyntax.
Kontrollera alltid din specifika verktygets dokumentation.
Kubernetes: Återanvändning av resursbegränsningar
I Kubernetes-manifest är resursbegränsningar och miljövariabler utmärkta kandidater för ankare. Här är ett mönster jag använder regelbundet:
# 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 profileFlera sammanslagningar och åsidosättningsprioritet
Du kan slå samman från flera ankare i en enda mappning. Ange dem som en lista under <<.
Tidigare poster i listan har prioritet över senare poster för duplicerade nycklar:
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=widgetBegränsningar att känna till
- Endast samma fil. Ankare och alias fungerar bara inom ett enda YAML-dokumentflöde. Du kan inte referera till ett ankare från en annan fil. För återanvändning mellan filer behöver du ditt verktygs egna mekanism (t.ex. Helm-mallar, Kustomize, eller YAML-processorer som
ytt). - Inga beräknade värden. Alias löser upp till exakta kopior av ankarvärdet. Det finns ingen interpolation eller malllogik — det är för verktyg som Helm eller Jinja2.
- Sammanslagningsnyckeln är ett YAML-tillägg. Sammanslagningsnyckeln
<<är definierad i ett YAML 1.1-tillägg, inte i kärnspecifikationen. De flesta parsers stöder det, men strikt spec-kompatibla YAML 1.2-parsers kanske inte. - Cirkulära referenser bryter parsers. Försök inte ankra en nod och referera till den inifrån sig själv. Det är tekniskt ogiltigt.
- Alias kopierar, refererar inte. Att modifiera ett löst alias-värde i din kod ändrar inte ankaret eller andra alias. De är oberoende värden efter parsning.
Sammanfattning
YAML-ankare och alias är en av formatets mest underutnyttjade funktioner. I vilken YAML-fil som helst längre än ungefär 50 rader där samma konfigurationsblock förekommer mer än två gånger hör ankare nästan säkert hemma där. Skillnaden i underhållbarhet före/efter är dramatisk — att ändra en resursbegränsningsprofil eller en delad miljövariabel istället för att söka igenom hela filen. Använd YAML-formateraren för att hålla dina ankrade filer prydliga, och YAML-valideraren för att bekräfta att dina ankarreferenser löser upp korrekt.