Por que estamos modelando YAML? (2019)
Os engenheiros argumentam que modelar YAML para infraestrutura e configurações do Kubernetes virou um antipadrão: arquivos declarativos antes simples acumularam loops, condicionais e DSLs específicas de fornecedor, transformando-se em sistemas frágeis de “yaml-como-linguagem-de-programação” que são difíceis de validar, depurar e proteger. Muitos preferem gerar JSON/YAML a partir de linguagens de programação reais (TypeScript, Python, Ruby) ou de linguagens de configuração criadas para esse fim (Jsonnet, CUE, Dhall, Nix), muitas vezes combinadas com ferramentas como CDK, Pulumi ou Tanka, para que a lógica fique em código testado enquanto o cluster ainda recebe manifests simples. Por baixo disso, há uma preocupação mais ampla de que cada novo formato de configuração e mecanismo de template repete o mesmo erro — reinventar uma linguagem restrita em vez de aproveitar as existentes e o ferramental adequado para tipos, esquemas e composição.
Por que YAML é usado e depois modelado
- Os comentaristas concordam que o YAML domina em grande parte por inércia e familiaridade: exemplos e ferramentas estão em toda parte, especialmente em Kubernetes e CI.
- As pessoas começam com “apenas um YAML simples”, depois adicionam algumas variáveis, depois condicionais/loops, e acabam com uma linguagem de programação de fato.
- Copiar e colar trechos de documentação e blogs é uma grande razão para as pessoas continuarem com YAML bruto/modelado em vez de ferramentas de nível mais alto.
Críticas ao próprio YAML
- Muitos veem o YAML como enganadoramente “amigável para humanos”: a indentação é frágil, o contexto é fácil de perder em arquivos longos e a especificação é complexa.
- O sistema de tipos e as conversões implícitas (por exemplo,
no→ falso / problema da “Noruega”, diferenças entre 1.1 e 1.2) são reclamações recorrentes. - YAML modelado é descrito como “programação tipada por string”: difícil de validar, depurar e raciocinar, com semântica específica de fornecedor.
- Alguns defendem o YAML para configs pequenas a moderadamente complexas e para não programadores (por exemplo, front-matter, simple docker-compose), especialmente com validação de esquema e linters.
Modelagem vs geração com linguagens reais
- Corrente forte: parem de inventar DSLs de template meia-boca; usem uma linguagem real (TypeScript, Python, Ruby, Go, etc.) para construir estruturas de dados e emitir JSON/YAML.
- Benefícios citados: reutilização de bibliotecas e ferramentas, verificação de tipos, testes unitários, refatoração mais fácil, separação mais clara entre “dados burros” e lógica.
- Contra-argumentos:
- Permitir que linguagens arbitrárias rodem em CI/IaC aumenta a superfície de ataque e a complexidade.
- A configuração deve ser declarativa e restrita; poder Turing-completo total convida à bagunça e dificulta a política/validação.
Linguagens/sistemas alternativos de configuração
- Frequentemente mencionados: Jsonnet, Dhall, CUE, Nix, Nickel, ferramentas baseadas em Starlark (ytt, Bazel/Starlark, Kurtosis), CDK8s, AWS CDK, Pulumi, Tanka, Kustomize.
- As opiniões divergem: alguns adoram Jsonnet/CUE/Nix/Dhall por serem funcionais, totais ou seguros por tipos; outros os acham muito nichados, difíceis de aprender ou sem bibliotecas.
- Vários sugerem “configuração como código com tipos”, mais um formato de dados simples e validado como artefato compilado (frequentemente JSON, opcionalmente renderizado para YAML).
Kubernetes, Helm, CI e operators
- Charts do Helm são amplamente chamados de dolorosos: substituição de texto, malabarismo com indentação, mensagens de erro ruins e necessidade de reexpor recursos do Kubernetes via
values.yaml. - Alguns preferem Kustomize ou manifests puros; outros argumentam que operators ou CDKs de nível mais alto são uma abstração melhor do que ainda mais modelagem de YAML.
- Para CI (GitHub Actions, etc.), muitos recomendam YAML mínimo que apenas
execs scripts reais, evitando lógica complexa em arquivos de configuração.
Filosofia mais profunda de configuração
- Tema recorrente: “toda configuração deriva em completude de Turing”.
- O debate gira em torno de onde a lógica deve viver, quão poder a configuração deve ter e como manter sistemas observáveis, testáveis e mantíveis à medida que a complexidade cresce.