Se você já copiou um bloco YAML de um lugar para outro dentro de um arquivo, você já enfrentou o problema que âncoras e aliases resolvem. Grandes configurações do Kubernetes, arquivos Docker Compose multi-ambiente e pipelines de CI complexos tendem a repetir os mesmos blocos — limites de recursos, variáveis de ambiente, montagens de volume — vezes e mais vezes. O YAML tem uma resposta embutida para isso, e a maioria dos desenvolvedores não sabe que ela existe.
Âncoras (&) e aliases (*) são o mecanismo do YAML para definir um valor uma vez e
referenciá-lo em qualquer outro lugar no mesmo arquivo. Pense em uma âncora como declarar uma variável e em um alias como usá-la.
A chave de mesclagem (<<) estende isso para mesclagem de objetos — semelhante ao operador spread do JavaScript.
Ambas as funcionalidades são definidas na seção de âncoras de nó da especificação YAML 1.2.
Sintaxe Básica de Âncora e Alias
A sintaxe é mínima. Prefixe um valor com &nome para criar uma âncora,
depois use *nome em qualquer lugar no documento para referenciá-la:
# Define the anchor once
default_timeout: &timeout 30
# Reference it multiple times
services:
api:
timeout: *timeout # → 30
worker:
timeout: *timeout # → 30
scheduler:
timeout: *timeout # → 30Quando um parser YAML lê isso, cada alias resolve para o mesmo valor exato da âncora. Mude a âncora e todos os aliases são atualizados. Sem necessidade de buscar e substituir.
Mesclando Objetos com a Chave <<
A reutilização de escalares é útil, mas o verdadeiro poder vem da mesclagem de blocos de mapeamento inteiros.
A chave de mesclagem << absorve todos os pares chave-valor da âncora referenciada no mapeamento atual:
# 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"]Chaves definidas diretamente no mapeamento substituem chaves da âncora mesclada.
Portanto, se base define restart: unless-stopped e o serviço também define
restart: no, o valor do nível do serviço prevalece.
Antes e Depois: Docker Compose no Mundo Real
Veja como um arquivo Docker Compose típico multi-serviço parece sem âncoras — cheio de repetição:
# 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:
- postgresAgora com âncoras e a chave de mesclagem — cada bloco repetido é definido exatamente uma vez:
# 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- em
campos de extensão
(como x-common) é uma convenção do Docker Compose que impede o Compose de tentar analisar o bloco como uma definição de serviço.
É ignorado pelo engine do Compose, mas totalmente utilizável como uma âncora YAML.GitHub Actions: Estratégia de Matrix com Âncoras
Configuração de CI é outro lugar onde as âncoras compensam. Aqui está um workflow do GitHub Actions que reutiliza configurações comuns de etapas em vários 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 buildNota: o parser YAML do GitHub Actions
suporta âncoras e aliases. No entanto, alguns sistemas de CI
(notavelmente o config.yml do CircleCI antes da versão 2.1) tinham sua própria sintaxe de extensão semelhante a âncoras.
Sempre verifique a documentação da ferramenta específica.
Kubernetes: Reutilizando Limites de Recursos
Em manifestos Kubernetes, limites de recursos e variáveis de ambiente são candidatos ideais para âncoras. Aqui está um padrão que uso regularmente:
# 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 profileMúltiplas Mesclagens e Prioridade de Substituição
Você pode mesclar de múltiplas âncoras em um único mapeamento. Forneça-as como uma lista sob <<.
Entradas anteriores na lista têm prioridade sobre as posteriores para chaves duplicadas:
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=widgetLimitações para Conhecer
- Somente no mesmo arquivo. Âncoras e aliases só funcionam dentro de um único fluxo de documento YAML. Você não pode referenciar uma âncora de um arquivo diferente. Para reutilização entre arquivos, você precisa do mecanismo próprio da sua ferramenta (ex.: templates do Helm, Kustomize ou processadores YAML como
ytt). - Sem valores computados. Aliases resolvem para cópias exatas do valor da âncora. Não há interpolação ou lógica de template — isso é para ferramentas como Helm ou Jinja2.
- A chave de mesclagem é uma extensão YAML. A chave de mesclagem
<<é definida em uma extensão YAML 1.1, não na especificação principal. A maioria dos parsers a suporta, mas parsers YAML 1.2 estritamente conformes podem não suportar. - Referências circulares quebram parsers. Não tente ancorar um nó e depois referenciá-lo dentro de si mesmo. É tecnicamente inválido.
- Aliases copiam, não referenciam. Modificar um valor de alias resolvido no seu código não altera a âncora ou outros aliases. São valores independentes após o parsing.
Conclusão
Âncoras e aliases YAML são um dos recursos menos utilizados do formato. Em qualquer arquivo YAML com mais de cerca de 50 linhas onde o mesmo bloco de configuração aparece mais de duas vezes, âncoras quase certamente devem estar lá. A diferença de manutenibilidade entre o antes e o depois é dramática — alterar um perfil de limite de recursos ou uma variável de ambiente compartilhada em vez de varrer o arquivo inteiro. Use o Formatador YAML para manter seus arquivos com âncoras organizados, e o Validador YAML para confirmar que suas referências de âncoras são resolvidas corretamente.