- Em ambientes como o Kubernetes, onde o número de alvos de configuração cresce, a abordagem de simplesmente aumentar a quantidade de arquivos YAML logo atinge seu limite, e uma abordagem de gerar dados de configuração passa a ser mais adequada do que usar templates de YAML
- Helm chart injeta valores com
values.yaml e templates Go, mas no momento em que entram em cena campos opcionais, arrays e mapas, o peso de condicionais e indentação aumenta bastante
- O YAML tem regras rígidas de espaços em branco, mas o parser de templates do Helm não entende a estrutura do YAML, então a combinação de
toYaml e indent facilmente leva a uma geração frágil de configuração
- Como YAML é um superconjunto de JSON, a conversão entre os dois é simples, e o Jsonnet lida com geração de objetos de configuração como código, usando variáveis externas, campos condicionais, combinação de mapas e mesclagem de objetos
- O kr8 usa um fluxo baseado em Jsonnet para criar e manipular configurações de vários clusters Kubernetes, optando por gerar e transformar objetos diretamente em vez de montar strings YAML complexas
A complexidade da configuração começa quando o número de arquivos YAML aumenta
- Quando aplicações e infraestrutura passam de uma certa escala, a complexidade da configuração cresce rapidamente
- Se há apenas 1 ou 2 alvos de deploy, escrever arquivos de configuração YAML manualmente ainda pode ser suficiente, mas quando isso aumenta, é preciso gerenciar a configuração de forma sistemática
- O motivo de precisar de vários arquivos de configuração normalmente é que, mesmo para o mesmo alvo, alguns valores diferem entre si
- Deploy por ambiente como
dev, stg, prod
- Deploy por região como Europa, América do Norte
- Nem toda configuração é diferente, mas se as diferenças forem grandes o bastante, é preciso separar e gerenciar em comum o que é compartilhado e o que muda
- A área de gerenciamento de configuração lida com esse tipo de problema há muito tempo, e várias ferramentas vêm usando YAML à sua maneira
- O hiera, incluído no Puppet, permite consultar variáveis de forma hierárquica, sendo poderoso e flexível, e reduz bastante a necessidade de fazer templates do próprio YAML
Os problemas de templates de YAML que aparecem em Helm chart
- Com computação em nuvem e Kubernetes, os alvos de configuração se expandiram para camadas acima do sistema operacional, e surgiram ferramentas como CloudFormation e Helm
- Helm chart pode receber parâmetros externos definidos em
values.yaml para renderização
- Valores simples em forma de string são relativamente fáceis
image: "{{ .Values.image }}"
- Se você definir o valor de
image em values.yaml, esse valor entra no template
- Os problemas crescem quando se começa a lidar com configurações mais complexas, como campos opcionais
{{- with .resourceGroup }}
resourceGroup: {{ . }}
{{- end }}
- Como valores opcionais não podem simplesmente ser deixados em branco, são necessários condicionais e loops, e o template fica facilmente confuso
- Ao inserir arrays ou mapas, é preciso combinar
toYaml com indent
{{- with .Values.podAnnotations }}
annotations:
{{ toYaml . | indent 8 }}
{{- end }}
- A chamada de função que converte YAML em YAML de novo com
toYaml já soa estranha, mas o problema maior é o tratamento de espaços em branco
O choque entre as regras de espaços do YAML e o mecanismo de templates
- O YAML tem regras rígidas de indentação e espaços em branco
- O exemplo abaixo não é um YAML válido ou completo
something: nothing
hello: goodbye
- Se uma pessoa estiver escrevendo isso manualmente, pode corrigir apertando backspace algumas vezes, mas ao gerar YAML com um sistema de templates isso não é tão simples
- Quando o número de arquivos de configuração passa de 5 a 10, torna-se necessário gerar configuração em vez de escrever tudo manualmente
- Para colocar o valor de
.Values.podAnnotations sob annotations, que já está indentado, o próprio valor também precisa estar indentado exatamente no nível correto
- Como o parser de templates Go não entende YAML, problemas aparecem mesmo quando se tenta indentar a sintaxe do template para deixá-la visualmente mais bonita
{{- with .Values.podAnnotations }}
annotations:
{{ toYaml . | indent 6 }}
{{- end }}
- Quando um sistema de templates lida com espaços e condicionais sem conhecer a estrutura do YAML, gerar configurações complexas vai ficando cada vez mais difícil
- Escrever JSON diretamente também não é uma boa opção por causa da ausência de comentários e de problemas como esquecer vírgulas, e foi justamente por esse desconforto que o YAML passou a ser usado
Jsonnet é uma linguagem de templates de dados para gerar configuração JSON
- Como YAML é um superconjunto de JSON, a conversão entre JSON e YAML é simples
- Várias aplicações e linguagens de programação conseguem fazer parsing ou conversão de JSON e YAML nativamente
- Em Python também é possível ler YAML e imprimir JSON
python -c 'import json, sys, yaml ; y=yaml.safe_load(sys.stdin.read()) ; print(json.dumps(y))'
- O Jsonnet se define como uma linguagem de templates de dados, e seu objetivo central é gerar configuração JSON
- O contexto de design do Jsonnet pode ser visto no design rationale
Variáveis externas e tratamento de campos opcionais
- O Jsonnet pode usar variáveis externas para injetar valores de configuração
{
image: std.extVar('image'),
}
- Ao passar uma variável externa pela CLI, é gerado o resultado em JSON
jsonnet image.jsonnet -V image="my-image"
{
"image": "my-image"
}
- Campos opcionais podem ser expressos como condições no código, sem enfiar condicionais de template dentro de strings
// define a variable - yes, jsonnet also has comments
local rg = null;
{
image: std.extVar('image'),
// if the variable is null, this will be blank
[if rg != null then 'resourceGroup']: rg,
}
- Se
rg for null, o campo resourceGroup não será incluído no resultado
- Se um valor for definido, esse campo será exibido
Manipular mapas e objetos é mais simples do que lidar com indentação em YAML
- Quando se coloca um mapa na configuração, como no caso de anotações de pod no Kubernetes, no Jsonnet é possível definir o valor como uma variável e depois posicioná-lo no objeto
local annotations = {
'nginx.ingress.kubernetes.io/app-root': '/',
'nginx.ingress.kubernetes.io/enable-cors': true,
};
{
metadata: { // annotations are nested under the metadata of a pod
annotations: annotations,
},
}
- Essa abordagem é muito mais simples do que tentar acertar a indentação em templates YAML
- O resultado gerado é um objeto JSON com o mapa de anotações dentro de
metadata.annotations
{
"metadata": {
"annotations": {
"nginx.ingress.kubernetes.io/app-root": "/",
"nginx.ingress.kubernetes.io/enable-cors": true
}
}
}
- Em Jsonnet, a tarefa de adicionar anotações a um objeto existente também pode ser feita com o operador
+
local annotations = {
'nginx.ingress.kubernetes.io/app-root': '/',
'nginx.ingress.kubernetes.io/enable-cors': true,
};
{
metadata: {
annotations: annotations,
},
} + { // this adds another JSON object
metadata+: { // I'm using the + operator, so we'll append to the existing metadata
annotations+: { // same as above
something: 'nothing',
},
},
}
- No objeto resultante,
something: "nothing" é adicionado às anotações existentes
{
"metadata": {
"annotations": {
"nginx.ingress.kubernetes.io/app-root": "/",
"nginx.ingress.kubernetes.io/enable-cors": true,
"something": "nothing"
}
}
}
- Em exemplos simples, o código pode até parecer mais longo, mas conforme a configuração fica mais complexa, essa forma de manipular objetos se torna útil
O kr8 lida com configurações de Kubernetes no estilo Jsonnet
- O kr8 usa esses métodos para criar e manipular de forma fácil e simples as configurações de vários clusters Kubernetes
- O fluxo central é, em vez de montar templates YAML com espaços e condicionais, gerar objetos de configuração JSON e transformá-los da maneira necessária
1 comentários
Comentários do Hacker News
Já estou completamente de saco cheio de configurações escritas em YAML. É a parte que mais odeio no GitHub Actions, e é pior até do que questões de confiabilidade
Quando vejo uma ferramenta legal exigindo um arquivo YAML para configuração, já fico apreensivo na hora. O mesmo vale para linguagens proprietárias de configuração como o HCL do Terraform e o ASL do AWS Step Functions
Não tem problema querer uma API declarativa, mas eu queria que ela permitisse gerar essa declaração por meio de programação. Configurações declaradas e geradas em código sempre foram uma experiência muito melhor, e o AWS CDK fez isso muito bem
Você pode definir a infraestrutura de nuvem em uma linguagem com segurança de tipos e bom suporte de IDE, sem depender de um plugin que não recebe atualização há 2 anos
deno fmttem formatador de JSON, mas não tem formatador de YAMLO formatador de JSON é um binário único que roda em milissegundos, enquanto a autoformatação de YAML na prática exige usar o Prettier, e o Prettier depende de metade do NPM e leva uns 2 segundos para iniciar e rodar
Então converti para JSON todos os arquivos YAML do repositório da empresa que podiam ser trocados, e pelo menos eu estou muito mais satisfeito. Ninguém reclamou
Vários editores também suportam a tag
$schemado JSON. Adicionei esse recurso ao produto, e é ótimo poder criar arquivos de configuração só apertando Tab, sem precisar ler a documentaçãoYAML também consegue isso com o YAML language server, mas como a tecla Tab também é necessária para indentação, a usabilidade fica ruim. JSON também não é perfeito, mas pelo menos o texto
"no"não vira verdadeiroNão daria para só colocar um filtro que removesse os comentários antes de ler a configuração? Não parece que isso seria mais difícil do que trocar tudo para YAML
Também não entendo muito bem a ideia de que YAML é mais fácil de ler. A dor de lidar com configuração não vem de economizar alguns segundos ao interpretar chaves e colchetes, mas sim da dificuldade de descobrir o que está errado por causa de um espaço ou tab faltando em meio a centenas de linhas de configuração
O Ansible comete o mesmo erro, e inúmeras outras ferramentas também
Não sei ao certo se o CDK funciona dessa forma. Quando mexi um pouco nele, pareceu bem diferente da experiência de “gerar CloudFormation” que eu tinha criado, e acabei não entendendo direito qual era a grande vantagem do CDK
Parecia trocar o problema de YAML/templates por um problema de herança/mágica. Gostaria de ouvir mais experiências de quem já usou AWS CDK, Terraform CDK e Pulumi
https://github.com/actions/runner/issues/1182
Concordo que templates YAML são uma ideia meio maluca, mas nunca entendi por que não paramos de usar linguagens falsas e passamos a usar uma linguagem de programação de verdade
Se você precisa de lógica complexa, basta gerar YAML/JSON/o que for com uma linguagem de programação. Ruby, Python ou qualquer outra já oferecem o que é necessário sem precisar de pseudolinguagens esquisitas como Jsonnet ou templates Go
Basta escrever código, e você sofre muito menos com problemas estranhos e opacos de engines de template. Qualquer linguagem de verdade fica muito melhor
Já usei Chef em trabalhos parecidos, e era bom por ser Ruby, então dava para definir facilmente a lógica desejada e usar loops e variáveis de verdade
Entendo que o Ansible foi projetado para não programadores, mas para alguém acostumado ao básico de programação, não há inferno pior do que enfiar playbooks do Ansible cheios de condicionais e repetições dentro da sintaxe verbosa dos templates Jinja
Hoje, porém, o normal é pegar um parser de JSON/TOML/YAML e criar uma função
readConfig, inclusive em casos em que um interpretador embutido seria mais adequadoDo ponto de vista do desenvolvedor, é mais fácil adicionar complexidade ao formato de configuração do que oferecer uma incorporação completa de linguagem e bindings da aplicação. Então parece que esqueceram esse caminho, ou nem consideram que ele seja possível
Na época de Chef/Puppet, muitos lugares começaram a colocar lógica em IaC e isso virou uma bagunça gigantesca impossível de atualizar ou manter. O modelo Chef/Pulumi também funciona, mas exige alguém muito rigoroso com estilo e manutenção
Para equipes grandes e manutenção de longo prazo, acho o modelo Terraform/Puppet melhor. HCL é irritante e usar Python/TypeScript etc. dá uma sensação de liberdade, mas código puramente declarativo evita muito espaguete
Eles querem colocar os elementos de design de linguagem que estão na moda, querem self-hosting e também querem que dê para escrever um servidor web multithread rápido, então tudo fica conceitualmente complexo
Precisamos de uma linguagem brinquedo simples, tipo Logo, para engenheiros de sistemas/DevOps. Originalmente ela deveria ser explicável em um livro do tamanho do K&R C
Precisaria de tipagem dinâmica, estruturas de controle que se aprendem em um fim de semana, sem threading nem concorrência, sem orientação a objetos nem herança, com design funcional/modular e um modelo de FFI que possa ser facilmente chamado e chamar outras linguagens e frameworks
O problema é que os fanáticos por linguagens não conseguem se controlar e continuam adicionando recursos, e isso acaba entrando na biblioteca padrão e no guia de estilo, de modo que até iniciantes precisam aprender tudo
Eu mesmo ficaria tentado a adicionar funções do tipo
each/mapa arrays/hash maps e incluir funções de primeira classe e closures, mas isso talvez fosse um erro. Já existem linguagens funcionais imutáveis para configuração, mas mais de 95% de quem usa YAML com templates não quer aprender a programar desse jeito, então é difícil isso se popularizarIsso simplifica a configuração, facilita o consumo e também a documentação. Mas, ao escrever arquivos de configuração, deveria-se usar uma linguagem de programação e, de preferência, uma linguagem estaticamente tipada que ofereça verificação de erros, autocompletar e documentação inline
O AWS CDK é um bom exemplo. Escrever CloudFormation puro é doloroso, mas o CDK não adiciona recursos de programação ao CloudFormation; ele gera CloudFormation. A entrada que a AWS consome continua sendo o CloudFormation relativamente simples e estável
Assim que vi o título, achei que seria sobre Kubernetes
A API do Kubernetes é bastante intuitiva e tem um esquema JSON bem definido. A maior parte do tempo gasto aprendendo k8s deveria ser usada para entender como usar a API, mas na prática acaba sendo gasta para descobrir como usar charts do Helm
Não acho que Jsonnet, Ksonnet, Nu e CUE tenham ficado tão populares assim. Parece que a maioria usa Kustomize, porque é relativamente intuitivo e vem embutido no
kubectlA ferramenta ideal deveria oferecer ao autor das definições verificação de tipos com base no esquema do k8s, validação e alertas de descontinuação de versões, dar ao usuário um único artefato de saída fácil de inspecionar, falhar atomicamente se o cluster não oferecer suporte a algum objeto/versão e estar embutida na cadeia de ferramentas padrão
Um script TypeScript para Bun ou Deno que exporte uma função que receba argumentos e retorne uma lista de definições provavelmente combinaria bem com algo como
deno compile, mas falha no requisito de estar embutido na cadeia de ferramentas padrãoIsso protege dos detalhes de baixo nível, mas quando algo dá errado você precisa lidar com uma enorme pilha de abstrações que dificulta diagnóstico e depuração
Fica muito mais difícil descobrir o que realmente está acontecendo, e você acaba dependente da camada de abstração, assumindo também as atualizações que o fornecedor lançar e outros problemas no grafo de dependências
Ela faz quase tudo de que precisamos sem problemas, é multiplataforma e pode ser usada em várias linguagens. Já a embuti em executáveis C++, .NET e JVM
A configuração final em JSON pode ser usada com um conjunto enorme de ferramentas que é difícil encontrar em alternativas como toml/yaml/hocon/ini etc. Tentei usar HOCON em linguagens que não eram da JVM, mas sempre esbarrava em algum caso de borda
Mas quando você realmente vai administrar um sistema grande, no fim não dá para evitar as vantagens dos templates
É engraçado ver como os desenvolvedores pensam tão pouco em como lidar direito com configuração
Parece só um conjunto de chaves e valores armazenado em arquivo ou gerado por código, mas na verdade isso é tudo. É a própria programação
Tudo é configuração, e todo argumento de função também é um tipo de configuração. Toda configuração em arquivo externo acaba virando argumento de função de algum jeito
O problema é a representação em texto simples do código. Arquivos de configuração declarativos parecem bons porque você consegue ver tudo em um só lugar, mas quando a configuração vira programa fica difícil achar onde mudar as coisas
Não seria um problema se o código rodasse em tempo real mostrando a representação da configuração final e permitindo rastrear como cada valor final foi gerado. Essa funcionalidade é bem simples, mas não existem sistemas projetados assim. Configuração é sempre algo pensado depois
Expandindo essa ideia para a programação como um todo, você deveria conseguir ver todo o código que depende de um valor de configuração específico e todas as suas transformações
Além disso, a maior parte das configurações é relacional/em grafo, então talvez fosse melhor mantê-la em um banco de dados central. Valores de configuração diferentes se relacionam entre si. Então a configuração deveria ser visualizada em um editor de banco de dados/grafo
Quando se sai do texto puro, as coisas começam a ficar bem mais simples, mas as funcionalidades de linguagem mencionadas antes ainda seriam necessárias
As configurações estão tentando usar convenções de nomes para agrupar variáveis relacionadas
Querem uma estrutura de dados realmente aninhada, provavelmente gostariam de migrar para JSON, mas os engenheiros não querem escrever código de jeito nenhum, então configuração como código é inviável. E também há as desvantagens mencionadas antes
A próxima ideia é que deve haver uma forma melhor de visualizar e editar a configuração. Pensei em uma UI visual que permita explorar a representação do produto final, selecionar peças e ajustar parâmetros dessa forma
Queria saber se essa direção faz sentido. Se não, gostaria de uma explicação um pouco melhor. O núcleo dessa aplicação é configuração
Pior ainda é que, em lugares como CI/CD, YAML quase vira uma linguagem de programação. E uma muito verbosa, nada intuitiva, com especificação ruim e diferente conforme o fornecedor
Havia DTD e validação de XML, mas com aquela característica familiar de falhar tarde e emitir mensagens de erro difíceis de interpretar
Naquela época muita frustração era direcionada ao XML, mas ao ver o inferno do YAML em meados dos anos 2020, fica claro que o problema não era a linguagem de marcação em si
Eu realmente detesto enfiar lógica em algum canto de um template YAML
[0] https://tanzu.vmware.com/developer/guides/ytt-gs/
É realmente triste que o Helm tenha vencido. Trabalho com coisas open source relacionadas a k8s na empresa, e 100% dos usuários pedem que a gente crie charts do Helm, então no fim precisamos fazer isso.
É miserável trabalhar com isso. O nome do arquivo é algo como
foo.yaml, mas na prática não é YAML, então o editor não consegue ajudar. Você precisa passar todos os dados porindent 4para acertar a identação do YAMLO mais deprimente é ter que reexpor todos os recursos do Kubernetes do seu próprio jeito. Se alguém quiser adicionar
deployment.spec.template.spec.fooBars, você precisa adicionardeploymentFooBarsemvalues.yamle conectar tudo. Isso se repete para cada recursoÉ realmente um caso de “o ruim é bom” dando errado. Eu também já fiz horrores como tentar implementar templates com
sed -e s/$FOO/foo/g, e imagino que o Helm também tenha começado assim. O resultado é um desastrePessoalmente, eu usava Kustomize desde antes de entrar no
kubectle sempre fiquei bastante satisfeito. Tem muitas esquisitices, mas pelo menos ele entende o significado dos objetos que gera e economiza tempoJsonnet é muito melhor. Como parte do nosso app de k8s, também distribuímos um deployment do Envoy para roteamento de tráfego complexo, e a configuração do Envoy é verbosa, mas fácil de lidar com Jsonnet: https://github.com/pachyderm/pachyderm/blob/master/etc/gener...
Estou considerando seriamente transpilar jsonnet para a linguagem de templates do Go e implementar tudo em Jsonnet. Pelo menos seria um pouco mais sustentável, e como
helm installsimplesmente funcionaria, ninguém perceberiaMas acho que o Helm vai ser o fim do Kubernetes. Se alguma ferramenta concorrente de alocação de computação/execução de contêineres aparecer com uma linguagem decente para configuração, todo mundo migra de um dia para o outro
sed -e s/$FOO/foo/g, vale a pena olhar uma solução um pouco mais padrão e melhor: envsubstSe o assunto for gerar templates ou modificar charts do Helm com jsonnet, o Tanka também pode ajudar: https://tanka.dev/helm
Só que os lugares onde trabalhei ainda têm tanto medo de mudança que continuam usando tf/hcl e helm do mesmo jeito. Pelo menos em projetos pessoais dá para respirar um pouco
Acho que existe um problema aqui. Só não sei se o tipo de pessoa que escolhe YAML como linguagem de configuração vê isso como problema
Existe um conflito direto entre representação de dados centrada em humanos e representação de dados centrada em máquinas. Máquinas gostam de algo parecido com Lisp, pessoas gostam de algo parecido com Python
Quem quer manipular configuração do Kubernetes por computador provavelmente vai se irritar discretamente com o fato de o Kubernetes usar YAML. Mas a comunidade de Kubernetes parece ser majoritariamente do lado do YAML, então imagino que não se importem muito com o fato de que, quando entra lógica de programação, trabalhar com arquivos de configuração vira um pesadelo
Essa situação é justamente o ponto fraco do YAML, e acho que as pessoas de k8s em geral são inteligentes o bastante para esperar algo assim
A afirmação “YAML é um superconjunto de JSON”, não importa o que o autor da especificação escreva na documentação, não me parece verdadeira na prática. Se você convertesse toda a configuração YAML em JSON, o time de DevOps ficaria irritado
Os dois formatos de dados podem ter a mesma capacidade de expressar significado, mas o mesmo vale para todas as linguagens que compilam para a mesma arquitetura de CPU. JSON e YAML são coisas distintas no trabalho real, e misturar os dois não é uma boa ideia
Claro que as pessoas acabaram escrevendo na mão, e quando isso ficou insuportável começaram a colocar templates por cima. Parece que as coisas sempre acabam seguindo esse caminho
Texto escrito à mão não é substituído por texto serializado de configuração gerada por máquina; em vez disso, acaba sendo substituído por texto ainda escrito à mão, só que agora com templates por cima
Meu princípio pessoal é que não se deve usar interpolação de strings para gerar código legível por máquina. Linguagens de template são apenas uma interpolação de strings sofisticada
Já vimos as consequências de injeção de SQL e cross-site scripting. Enquanto continuarmos jogando texto arbitrário em interpretadores, esse tipo de coisa vai continuar acontecendo
Por isso também acho que não se deve usar arquivos de template para gerar HTML
Como alternativas a linguagens de template para HTML, existem o Haml do Ruby e o Pug do JavaScript. Essas linguagens oferecem uma forma definida de especificar a árvore completa de tags, atributos e nós de texto
Se você não gosta da indentação significativa ao estilo Python, no JavaScript existe o JSX. As partes com aparência de HTML no JSX são compiladas em expressões
createElementque constroem uma árvore de documento web, e essa árvore pode ser emitida como HTML se necessárioHaml, Pug e JSX não são linguagens de template, mesmo podendo produzir HTML. Da mesma forma,
JSON.stringify(myObj)não é uma linguagem de template para JSONCódigo legível por máquina deve, sempre que possível, ser gerado por ferramentas que entendam e aproveitem a estrutura conhecida da linguagem de destino
Haml é um sistema de templates para evitar código inline em documentos web e deixar o HTML mais limpo, e Pug é um mecanismo de templates rico em recursos para Node.js
Posso concordar que JSX, estritamente falando, não é uma linguagem de template
No fim, todos eles compilam para HTML. Só que, em vez de interpolação de strings, são analisados em árvores sintáticas e renderizados em HTML com base em um entendimento interno de estruturas válidas
Templates de YAML são interpolação de strings sofisticada, e não uma linguagem de template, ou pelo menos uma linguagem de template pessimamente implementada
Minha regra pessoal é que, sempre que um valor entra em uma string, ele deve ser codificado corretamente
Escrevi sobre esse tema no passado: https://kevincox.ca/2022/02/08/escape-everything/
Em resumo, toda string tem um formato a ser respeitado, seja HTML, SQL ou saída de terminal legível por humanos. Sempre que você coloca um valor em uma string, precisa codificá-lo corretamente para esse formato, mas quase nunca fazemos isso
Estamos migrando para cuelang [1]. Pessoalmente, acho o design melhor do que o do Jsonette
O Kubernetes já tem reconciliação de estado, então nesta configuração só faltava a exclusão, mas agora isso pode ser resolvido com o recurso de prune [2]
[1] https://cuelang.org/docs/integrations/k8s/
[2] https://kubernetes.io/blog/2023/05/09/introducing-kubectl-ap...
Algumas mensagens de erro são um pouco difíceis de interpretar, mas ele detecta tanta coisa de antemão que isso é aceitável. Agora, as poucas vezes em que preciso escrever yaml diretamente parecem incrivelmente tediosas em comparação
Nessas horas eu normalmente entro com um “você já ouviu falar do nosso salvador CUELang?”: https://cuelang.org/
Ainda não é Turing-completo, mas é expressivo o suficiente para eliminar duplicação, permite definir schema e dados na mesma linguagem, no mesmo arquivo ou em arquivos separados, e também tem union types
Ele pode gerar YAML ou JSON, e pode validar a si próprio ou arquivos YAML/JSON
A maior desvantagem é que a implementação atual só existe em Go, então pode ser necessário usar subprocessos ou FFI
Depois disso, ele cria arquivos JSON para cada aplicação, alguma ferramenta gera definições XML, essas definições são aplicadas a uma planilha XLS mantida pelos arquitetos, e dali sai o YAML aplicado aos charts Helm
Os charts implantam o cliente k8s, e esse cliente interage com o cluster principal em JSON via API
Demorou um pouco, mas estamos usando a melhor ferramenta para cada tarefa