O que era o bug do kyaml no Kubernetes
O Kubernetes 1.37 trouxe uma correção crítica para um bug que existia ha vários anos: o output do kyaml podia silenciosamente apagar campos de recursos YAML durante a execução do kubectl apply. O problema estava na forma como o kyaml serializava e desserializava objetos YAML com determinadas estruturas de dados.
O bug se manifestava em cenários específicos, mas era perigoso justamente porque não gerava erro nenhum. O kubectl reportava sucesso, o recurso era atualizado, mas alguns campos eram simplesmente removidos. Para equipes sem uma rotina rigorosa de auditoria de estado do cluster, isso podia passar despercebido por dias ou semanas.
Com o Kubernetes 1.37, esse comportamento foi corrigido no nível da biblioteca kyaml, que é a base para toda a manipulação de YAML no ecossistema de ferramentas do Kubernetes. A correção afeta o kubectl, kustomize e outros toolings que dependem dessa biblioteca.
Como o bug funcionava
O kyaml e uma biblioteca Go que o Kubernetes usa para ler, escrever e transformar recursos YAML. Ela foi projetada especificamente para preservar comentários, ordem de campos e outros detalhes de formatação importantes para workflows GitOps.
O bug estava na fase de merge de campos durante o apply. Quando o kubectl apply compara o estado desejado (o YAML local) com o estado atual do cluster, ele precisa mesclar as diferenças. Em certos tipos de campos aninhados, o algoritmo de merge descartava campos que não estavam presentes no manifesto local mas que tinham sido adicionados por outros processos, como controllers ou admission webhooks.
O resultado era que campos gerenciados por outros sistemas podiam ser apagados a cada apply, quebrando integrações e causando comportamentos imprevistos. Em clusters de produção com vários controladores e operadores rodando, esse tipo de perda de dados causava outages sutis e difíceis de diagnosticar.
Versões do Kubernetes anteriores a 1.37 ainda são vulneráveis a esse bug. Se você usa kubectl apply com frequência em clusters de produção, verifique a versão e considere atualizar.
Principais mudanças no Kubernetes 1.37
Além da correção do kyaml, o Kubernetes 1.37 inclui outras melhorias relevantes para o dia a dia das equipes:
- Correção do kyaml output: o bug de perda de dados no apply foi corrigido na base da biblioteca, afetando kubectl, kustomize e todos os toolings dependentes.
- Server-Side Apply mais estável: melhorias no mecanismo de Server-Side Apply, que é a abordagem recomendada para evitar conflitos de gerenciamento de campos.
- Melhorias no kubelet: redução de memoria usada pelo kubelet em nodes com muitos pods e containers.
- Gateway API avançada: a Gateway API, sucessora do Ingress para casos de uso mais complexos, avançou em maturidade no 1.37.
- Atualizações de segurança: correções de CVEs e melhorias no mecanismo de auditoria de acesso a API.
O foco da versão 1.37 foi estabilidade e correção de bugs acumulados, mais do que adicionar grandes funcionalidades novas.
Como verificar e atualizar seu cluster
Para verificar a versão atual do Kubernetes no seu cluster, rode o comando abaixo e compare com a versão 1.37:
kubectl version --shortPara atualizar o kubectl para a versão 1.37 no Linux:
curl -LO https://dl.k8s.io/release/v1.37.0/bin/Linux/amd64/kubectlPara ver o diff antes de aplicar mudanças, use o dry-run no servidor. Isso mostra exatamente o que vai mudar no cluster antes de confirmar:
kubectl apply --dry-run=server -f seu-recurso.yamlAntes de atualizar o cluster em produção, sempre atualize o kubectl local para a nova versão e teste em um cluster de staging primeiro.
Exemplo prático: o bug em ação
Imagine que você tem um Deployment e um admission webhook que adiciona automaticamente anotações a todos os recursos. O webhook adiciona managed-by: meu-operator no momento da criação do recurso.
Seu manifesto local não tem essa anotação, porque ela é gerenciada pelo webhook. Em versões anteriores ao 1.37, cada vez que você rodava kubectl apply com seu manifesto local, a anotação managed-by era removida, porque o kyaml a entendia como um campo que deveria ser deletado.
Com o fix do Kubernetes 1.37, o algoritmo de merge respeita campos que não estavam no manifesto original, preservando o que foi adicionado por outros sistemas. E exatamente o comportamento esperado que o Server-Side Apply já fazia certo, mas agora o Client-Side Apply também faz.
Client-Side Apply vs Server-Side Apply
Esse bug reforça uma discussão que a comunidade Kubernetes já tem ha anos sobre as duas abordagens de apply:
- Client-Side Apply: o kubectl calcula o merge localmente, usando a annotation
kubectl.Kubernetes.io/last-applied-configurationcomo referência. Mais simples, mas historicamente mais propenso a bugs de merge como esse do kyaml. - Server-Side Apply (SSA): o servidor e quem calcula o merge, com controle granular por campo sobre qual controller possui cada parte do recurso. Mais robusto para ambientes com múltiplos controladores.
Para ambientes de produção com operadores e controllers, o SSA continua sendo a recomendação. Mas a correção do 1.37 melhora bastante a segurança do Client-Side Apply para quem ainda o usa ou que não pode migrar tudo de uma vez.
Pontos positivos e limitações
Pontos positivos da atualização: correção de um bug real que causava perda silenciosa de dados, melhor compatibilidade entre Client-Side Apply e recursos gerenciados por controllers, redução de memoria no kubelet beneficia todos os nodes do cluster.
Limitações e considerações: atualizar um cluster Kubernetes não e trivial, especialmente em produção. Mesmo com a correção, o Server-Side Apply ainda e a abordagem mais robusta para ambientes complexos. A correção não volta atrás campos que já foram apagados por versões anteriores.
Se você suspeita que campos foram apagados por esse bug em versões anteriores, compare o estado atual do cluster com a fonte de verdade no seu repositório Git antes de atualizar.
Quem e mais afetado pelo bug
Os cenários que mais sofriam com esse problema eram:
- Times com muitos operadores instalados: cada operador que adiciona campos em recursos existentes estava sujeito a ver esses campos apagados no próximo apply manual.
- GitOps com Argo CD ou Flux: workflows onde o estado do cluster e sempre reconciliado com o Git podiam ter conflitos silenciosos entre o que o Git tem e o que os controllers adicionam.
- Desenvolvimento com admission webhooks: ambientes de dev que simulam webhooks de produção, como Istio ou OPA Gatekeeper, podiam ter comportamentos diferentes entre dev e prod.
- Helm com hooks: charts com hooks que modificam recursos após a criação podiam ter essas modificações removidas no próximo helm upgrade.
Dicas e boas práticas para quem usa kubectl apply
Use sempre --dry-run=server antes de aplicar mudanças em produção. Assim você ve exatamente o que vai mudar no cluster antes de confirmar.
Migre gradualmente para Server-Side Apply usando a flag --server-side no kubectl apply. Comece por recursos menos críticos e va expandindo conforme ganha confiança.
Configure seu cluster para auditar todas as modificações de recursos via Audit Log do Kubernetes API Server. Isso facilita muito diagnosticar perdas de dados silenciosas como essa.
Vale a pena atualizar para o 1.37?
Para equipes que usam kubectl apply frequentemente em produção, especialmente com operadores e admission webhooks, a resposta e sim. A correção do kyaml resolve um problema real que podia causar incidentes difíceis de diagnosticar.
Para quem já usa Server-Side Apply como padrão, o impacto e menor mas as outras melhorias de estabilidade e segurança ainda justificam a atualização planejada.
O próximo passo: cheque a versão atual do seu cluster com kubectl version --short e consulte o changelog do Kubernetes 1.37 no GitHub para ver a lista completa de mudanças antes de planejar a atualização.
Comentários