Clase 09 — Validación y Buenas Prácticas
Herramientas de validación
yamllint
# Instalar
pip install yamllint
# Validar un archivo
yamllint mi-config.yaml
# Validar con formato detallado
yamllint -f parsable mi-config.yaml
# Validar todos los archivos YAML de un directorio
yamllint .
Configurar yamllint
# .yamllint.yml
---
extends: default
rules:
line-length:
max: 120
level: warning
indentation:
spaces: 2
indent-sequences: true
comments:
min-spaces-from-content: 1
truthy:
allowed-values: ['true', 'false', 'yes', 'no']
document-start: disable
empty-lines:
max: 1
trailing-spaces: enable
new-line-at-end-of-file: enable
Validar con Python
#!/usr/bin/env python3
import yaml
import sys
try:
with open(sys.argv[1]) as f:
data = yaml.safe_load(f)
print(f"✅ YAML válido: {sys.argv[1]}")
print(f" Tipo raíz: {type(data).__name__}")
except yaml.YAMLError as e:
print(f"❌ YAML inválido: {e}")
sys.exit(1)
Validar Docker Compose
docker compose config # Validar sintaxis
docker compose config -q # Solo validar sin mostrar salida
docker compose config --format json # Configuración resuelta
Validar manifiestos de Kubernetes
kubectl apply -f deployment.yaml --dry-run=client # Dry-run cliente
kubectl apply -f deployment.yaml --dry-run=server # Dry-run servidor (más estricto)
kubeval deployment.yaml # Usando kubeval
kubeconform -strict deployment.yaml # Usando kubeconform (más moderno)
Errores comunes y cómo evitarlos
1. Tabs vs Espacios
# ❌ ERROR: Tab character
servicio:
nombre: api # Tab!
# ✅ CORRECTO: Espacios
servicio:
nombre: api # 2 espacios
2. Tipo de dato incorrecto
# ❌ PROBLEMA
version: 3.8 # → 3.8 (float)
puerto: 080 # → 80 (octal → decimal)
codigo: no # → false (boolean)
# ✅ SOLUCIÓN: Usar comillas
version: "3.8" # → "3.8" (string)
puerto: "080" # → "080" (string)
codigo: "no" # → "no" (string)
3. Caracteres especiales sin escapar
# ❌ PROBLEMA
titulo: Hola: Mundo # Error: : sin comillas
comando: echo "hola" # Las comillas internas
# ✅ SOLUCIÓN
titulo: "Hola: Mundo"
comando: 'echo "hola"'
4. Indentación inconsistente
# ❌ PROBLEMA: Mezclar 2 y 4 espacios
servicio:
nombre: api
config:
puerto: 8080 # 4 espacios en vez de 2
# ✅ CORRECTO: Consistente (2 espacios)
servicio:
nombre: api
config:
puerto: 8080
5. Duplicar claves
# ❌ PROBLEMA: Clave duplicada (la segunda sobrescribe)
servicio:
nombre: api
puerto: 8080
nombre: backend # Sobrescribe "api"
# ✅ CORRECTO: Claves únicas
servicio:
nombre: api
nombre_display: backend
puerto: 8080
Buenas prácticas
1. Indentación consistente de 2 espacios
services:
api:
image: mi-api:latest
ports:
- "8080:8080"
2. Siempre usar comillas en valores ambiguos
version: "3.8"
environment:
NODE_ENV: "production"
PORT: "8080"
DEBUG: "false"
3. Comentar secciones importantes
# ─── BASE DE DATOS ───
database:
host: postgres # Nombre del servicio en Docker/K8s
port: 5432
pool_size: 10 # Ajustar según carga esperada
# ─── CACHÉ ───
cache:
engine: redis
ttl: 3600 # 1 hora en segundos
4. Usar anclas para DRY
x-common: &common
restart: unless-stopped
logging:
driver: json-file
services:
api:
<<: *common
image: api:latest
worker:
<<: *common
image: worker:latest
5. Organizar archivos por responsabilidad
k8s/
├── base/
│ ├── namespace.yaml
│ ├── configmap.yaml
│ └── secret.yaml
├── deployments/
│ ├── api.yaml
│ └── frontend.yaml
├── services/
│ ├── api-svc.yaml
│ └── frontend-svc.yaml
└── ingress/
└── main-ingress.yaml
6. Usar variables de entorno para secretos
# docker-compose.yml - Nunca hardcodear secretos
services:
db:
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD} # Desde .env o sistema
7. Validar en CI/CD
# .github/workflows/lint.yml
name: YAML Lint
on: [push, pull_request]
jobs:
yamllint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Instalar yamllint
run: pip install yamllint
- name: Lint YAML
run: yamllint .
- name: Validar Docker Compose
run: docker compose config -q
- name: Validar K8s manifests
run: |
curl -sL https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz | tar xz
./kubeconform -strict k8s/
Cheat Sheet
# ── TIPOS DE DATOS ──
string: "texto"
entero: 42
flotante: 3.14
booleano: true
nulo: null
fecha: 2026-02-20
# ── LISTAS ──
lista_bloque:
- item1
- item2
lista_inline: [item1, item2]
# ── MAPAS ──
mapa_bloque:
clave1: valor1
clave2: valor2
mapa_inline: {clave1: valor1, clave2: valor2}
# ── MULTILÍNEA ──
literal: | # Mantiene \n
línea 1
línea 2
folded: > # Une en una línea
parte 1
parte 2
sin_newline: |- # Sin \n final
texto
# ── ANCLAS ──
base: &base
key: value
hijo:
<<: *base
otra_key: otro_valor
# ── MULTI-DOCUMENTO ──
---
documento: 1
---
documento: 2
Ejercicios
- Configurá
yamllinten tu proyecto y corregí todos los errores - Creá un workflow de GitHub Actions que valide todos los archivos YAML del repositorio
- Revisá un
docker-compose.ymlexistente y aplicá todas las buenas prácticas de esta clase - Creá una guía de estilo YAML para tu equipo basada en lo aprendido