Si vous avez déjà copié un bloc YAML d'un endroit à un autre dans un fichier, vous avez déjà rencontré le problème que les ancres et les alias résolvent. Les grandes configurations Kubernetes, les fichiers Docker Compose multi-environnements, et les pipelines CI complexes ont tendance à répéter les mêmes blocs — limites de ressources, variables d'environnement, montages de volumes — encore et encore. YAML a une réponse native à ce problème, et la plupart des développeurs ne savent pas qu'elle existe.
Les ancres (&) et les alias (*) sont le mécanisme de YAML pour définir une valeur une seule fois et
la référencer n'importe où ailleurs dans le même fichier. Pensez à une ancre comme à la déclaration d'une variable et à un alias comme à son utilisation.
La clé de fusion (<<) étend cela à la fusion d'objets — similaire à l'opérateur de décomposition de JavaScript.
Ces deux fonctionnalités sont définies dans la section sur les ancres de nœuds de la spécification YAML 1.2.
Syntaxe de base des ancres et alias
La syntaxe est minimale. Préfixez une valeur avec &nom pour créer une ancre,
puis utilisez *nom n'importe où dans le document pour la référencer :
# Define the anchor once
default_timeout: &timeout 30
# Reference it multiple times
services:
api:
timeout: *timeout # → 30
worker:
timeout: *timeout # → 30
scheduler:
timeout: *timeout # → 30Quand un parseur YAML lit ceci, chaque alias se résout à la même valeur exacte que l'ancre. Changez l'ancre et tous les alias se mettent à jour. Pas besoin de rechercher-remplacer.
Fusion d'objets avec la clé <<
La réutilisation de scalaires est utile, mais la vraie puissance vient de la fusion de blocs de mapping entiers.
La clé de fusion << absorbe toutes les paires clé-valeur de l'ancre référencée dans le mapping courant :
# 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"]Les clés définies directement dans le mapping surchargent les clés de l'ancre fusionnée.
Donc si base définit restart: unless-stopped et que le service définit aussi
restart: no, c'est la valeur au niveau du service qui prévaut.
Avant et après : Docker Compose dans le monde réel
Voici à quoi ressemble un fichier Docker Compose multi-service typique sans ancres — plein de répétitions :
# 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:
- postgresMaintenant avec les ancres et la clé de fusion — chaque bloc répété est défini exactement une fois :
# 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- sur les
champs d'extension
(comme x-common) est une convention Docker Compose qui empêche Compose d'essayer d'analyser le bloc comme une définition de service.
Il est ignoré par le moteur Compose mais entièrement utilisable comme ancre YAML.GitHub Actions : stratégie matrix avec des ancres
La configuration CI est un autre endroit où les ancres sont payantes. Voici un workflow GitHub Actions qui réutilise la configuration commune des étapes sur plusieurs jobs :
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 buildRemarque : le parseur YAML de GitHub Actions supporte bien les ancres et les alias. Cependant, certains systèmes CI (notamment CircleCI avant la version 2.1) avaient leur propre syntaxe d'extension similaire aux ancres. Vérifiez toujours la documentation de votre outil spécifique.
Kubernetes : réutiliser les limites de ressources
Dans les manifestes Kubernetes, les limites de ressources et les variables d'environnement sont des candidats idéaux pour les ancres. Voici un schéma que j'utilise régulièrement :
# 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 profileFusions multiples et priorité de surcharge
Vous pouvez fusionner depuis plusieurs ancres dans un seul mapping. Fournissez-les sous forme de liste sous <<.
Les entrées antérieures dans la liste ont la priorité sur les entrées ultérieures pour les clés en double :
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=widgetLimitations à connaître
- Fichier unique uniquement. Les ancres et alias ne fonctionnent que dans un seul flux de document YAML. Vous ne pouvez pas référencer une ancre depuis un fichier différent. Pour la réutilisation entre fichiers, vous avez besoin du mécanisme propre à votre outil (par exemple, templates Helm, Kustomize, ou des processeurs YAML comme
ytt). - Pas de valeurs calculées. Les alias se résolvent en copies exactes de la valeur de l'ancre. Il n'y a pas d'interpolation ou de logique de template — c'est pour des outils comme Helm ou Jinja2.
- La clé de fusion est une extension YAML. La clé de fusion
<<est définie dans une extension YAML 1.1, pas dans la spécification principale. La plupart des parseurs la supportent, mais les parseurs YAML 1.2 strictement conformes à la spécification peuvent ne pas la supporter. - Les références circulaires cassent les parseurs. N'essayez pas d'ancrer un nœud et de le référencer depuis l'intérieur de lui-même. C'est techniquement invalide.
- Les alias copient, ne référencent pas. Modifier la valeur d'un alias résolu dans votre code ne change pas l'ancre ni les autres alias. Ce sont des valeurs indépendantes après l'analyse.
Conclusion
Les ancres et les alias YAML sont l'une des fonctionnalités les plus sous-utilisées du format. Dans tout fichier YAML de plus d'environ 50 lignes où le même bloc de configuration apparaît plus de deux fois, les ancres y ont presque certainement leur place. La différence avant/après en termes de maintenabilité est dramatique — changer un profil de limite de ressource ou une variable d'environnement partagée plutôt que de les chercher dans tout le fichier. Utilisez le Formateur YAML pour garder vos fichiers avec ancres bien ordonnés, et le Validateur YAML pour confirmer que vos références d'ancre se résolvent correctement.