Quality of Service (QoS) no Kubernetes

Quando você coloca uma aplicação em produção no Kubernetes, uma das decisões mais importantes é como especificar os recursos que seus pods precisam. Essa escolha determina qual classe de Quality of Service (QoS) seu pod recebe — e isso impacta diretamente na sua estabilidade e custo. Neste post, vou explicar em detalhe os três níveis de QoS: Guaranteed, Burstable e BestEffort.

O que é QoS no Kubernetes?

QoS (Quality of Service) é um mecanismo que o Kubernetes usa para classificar e priorizar seus pods em relação ao uso de recursos. Quando o nó está sem memória ou CPU disponível, o Kubernetes usa a classe QoS para decidir qual pod será removido (evicted) ou compactado.

O Kubernetes define três classes de QoS:

  • BestEffort — mínima prioridade, primeira a ser removida
  • Burstable — prioridade média, removida após Guaranteed
  • Guaranteed — máxima prioridade, última a ser removida

Qual classe seu pod recebe depende de como você especifica os requests e limits de CPU e memória.

QoS BestEffort: Máxima Flexibilidade, Sem Garantias

Um pod é classificado como BestEffort quando:

  • Você não define requests nem limits de CPU ou memória
  • É a situação padrão quando você simplesmente não especifica nada
Leia mais »

O que é TinyGo?

Neste post, vou explicar o que é TinyGo, por que você deveria conhecer e como começar com um exemplo bem simples. Se você nunca ouviu falar em TinyGo ou simplesmente quer entender esse universo de programação para microcontroladores, esse post é para você.

O que é TinyGo?

TinyGo é um compilador Go otimizado para ambientes com recursos limitados. Enquanto a linguagem Go tradicional foi criada para sistemas desktop, como CLIs, e servidores, como aplicações cloud, o TinyGo permite que você escreva código Go para rodar em microcontroladores e pequenos dispositivos.

A ideia é simples: leve a simplicidade e a elegância do Go para o mundo do IoT (Internet das Coisas) e sistemas embarcados.

Leia mais »

Go 1.26.2: Patches de Segurança

Go 1.26.2 foi lançado em 7 de abril com patches críticos de segurança no compilador, crypto/tls, crypto/x509, html/template e os. Neste post, vamos entender por que essa atualização é importante e como você pode acompanhar esses advisories de forma proativa.

Por que atualizar para Go 1.26.2?

Atualizar rapidamente quando patches de segurança saem é uma das coisas mais importantes que você pode fazer como engenheiro. Não estou falando de features novas — estou falando de brechas de segurança que podem comprometer toda a sua infraestrutura.

Go publica patches de segurança em ciclos regulares, e quando saem, é porque uma vulnerabilidade real foi descoberta e já está documentada. Esperar “até o próximo ciclo” é arriscar demais.

Leia mais »
goroutine leaks no go 1.26

Detectando goroutine leaks no Go 1.26

Se você já trabalhou com Go em produção, provavelmente já enfrentou aquele cenário: goroutines que ficam presas para sempre, consumindo memória sem nunca terminar. O Go 1.26 trouxe uma ferramenta experimental que ataca esse problema direto na raiz: o goroutine leak profile.

O que são goroutine leaks?

Uma goroutine leak acontece quando uma goroutine fica bloqueada permanentemente — esperando em um channel, mutex ou condition variable que nunca vai ser desbloqueado. Na prática, é memória e recursos que ficam presos sem possibilidade de liberação.

O cenário mais clássico: você cria uma goroutine que escreve em um channel sem buffer, mas a função que deveria ler esse channel retorna antes por conta de um erro. A goroutine fica ali, bloqueada para sempre.

Leia mais »

In-Place Pod Resize — redimensionando sem restart

Se você trabalha com Kubernetes em produção, sabe que ajustar recursos de CPU e memória geralmente significa recriar os pods. Neste post, vamos explorar o In-Place Pod Resize, um recurso que permite redimensionar containers sem perder o uptime.

O que é In-Place Pod Resize?

In-Place Pod Resize é uma funcionalidade do Kubernetes que permite alterar os requests e limits de CPU e memória de um container enquanto o pod continua rodando. Não há reinicialização, sem downtime, sem interrupção de conexões.

Antes dessa feature, a única forma era deletar e recriar o pod com novos valores — algo impraticável em ambientes críticos.

Por que isso importa?

Imagine este cenário: você subiu uma aplicação com 256Mi de memória, achando que era suficiente. Alguns dias depois, monitoramento mostra que está usando 400Mi, próximo ao limite. Você precisa aumentar — e rápido.

Leia mais »

Entendendo o Green Tea GC do Go 1.26

Go 1.26 trouxe uma das maiores mudanças no runtime dos últimos anos: o Green Tea garbage collector agora vem habilitado por padrão. Nesse post, vamos entender o que mudou, por que isso importa e o que esperar na prática.

O que é o Green Tea GC?

O Green Tea GC é uma reformulação do garbage collector do Go. Ele mantém a mesma abordagem mark-sweep do GC anterior, mas muda fundamentalmente a forma como os objetos são rastreados e escaneados.

A diferença principal: em vez de operar objeto por objeto espalhado pelo heap, o Green Tea trabalha no nível de páginas de memória. Ele agrupa objetos em blocos contíguos de 8 KiB chamados spans e escaneia vários objetos de uma vez dentro do mesmo span.

Leia mais »

Como Go 1.25 e 1.26 reduzem a pressão no GC

Nesse post, vamos entender uma das otimizações mais interessantes das últimas versões do Go: a capacidade do compilador de alocar slices na stack em mais cenários — sem você precisar mudar uma linha de código.

O problema: heap allocation e o GC

Em Go, cada variável precisa ser alocada em algum lugar: na stack (pilha) ou na heap. A stack é rápida — alocar e liberar memória lá é praticamente gratuito. Já a heap é gerenciada pelo garbage collector, o que tem um custo: quanto mais você aloca no heap, mais trabalho o GC tem para fazer.

O compilador do Go usa uma técnica chamada escape analysis para decidir onde cada variável vai parar. Se ele consegue provar que uma variável não vai “escapar” do escopo da função, ele a coloca na stack. Caso contrário, ela vai para o heap.

O problema é que essa análise é conservadora: em muitos casos práticos, como acumular elementos em um slice dentro de um loop, o compilador não tinha certeza se o slice ia escapar ou não e alocava no heap por precaução.

Leia mais »

Atualizando seu código com go fix

O Go, desde suas primeiras versões, se preocupa com a evolução da linguagem sem quebrar código existente, e um dos comandos que ajuda muito nesse processo é o go fix.

Nesse post, vamos entender o que ele faz, quando utilizá-lo e como ele funciona na prática.

O que é o go fix?

O go fix é um comando da toolchain do Go que atualiza automaticamente o código-fonte para se adequar a mudanças de API introduzidas em novas versões da linguagem.

Ele funciona aplicando um conjunto de fixers — pequenas transformações automatizadas que identificam padrões de código antigos e os reescrevem para o equivalente moderno.

go fix ./...

Simples assim. O comando percorre todos os pacotes do módulo e aplica as correções necessárias.

Leia mais »

Como escolhemos nosso API Gateway

Nesse post quero compartilhar um pouco da experiência que tive na tomada de decisão técnica na hora de escolher um serviço/plataforma.

O caso que compartilharei aconteceu no segundo semestre de 2024, quando um dos OKRs da Unico era a implementação de um API Gateway.

O que descrevo aqui não é uma prática documentada e seguida à risca em todas as decisões tomadas na Unico, mas sim como fizemos para um caso específico. No entanto, há aprendizados e etapas que podem ser replicados para outros casos.

Passo 1: Qual problema precisamos resolver?

Quando decidimos refatorar toda a borda da empresa, a primeira coisa que fizemos foi entender o que, no modelo atual, não estava como queríamos. Identificamos complexidades, falhas processuais e de padronização na exposição de APIs públicas. Também levantamos alguns desejos que poderiam ser resolvidos na borda, como por exemplo, rate limit.

Com todos esses dados em mãos, para que a entrega não ficasse extremamente complexa (não que tenha sido simples) e, para ser possível ter algum resultado/impacto em menos de 6 meses, definimos algumas etapas para a implementação, onde, por exemplo, deixaríamos a implementação de rate limit para uma segunda fase.

Leia mais »

Como emitir certificados wildcard no GCP

Com o crescimento das aplicações na nuvem, garantir que elas estejam protegidas por SSL/TLS é uma prática essencial. O Google Cloud Platform (GCP) oferece diferentes formas de gerenciamento de certificados SSL, incluindo a possibilidade de emitir e vincular certificados a um Load Balancer. Uma abordagem moderna para isso é o uso de DNS Authorization para a validação dos certificados, e o uso de Certificate Maps para organizar e gerenciar vários certificados.

Neste post, vamos explorar como criar certificados com autorização via DNS, como configurar um Load Balancer e vinculá-lo ao certificado criado, usando a ferramenta de infraestrutura como código, Terraform. Além disso, vamos diferenciar entre certificados e Load Balancers clássicos e suas versões mais modernas no GCP.

Diferença entre Certificado e Certificado Clássico

No GCP, o certificado clássico refere-se à forma antiga, embora ainda válida, de gerenciar certificados SSL. Nesse processo, diferente da forma mais moderna, o certificado ficava ligado diretamente a um Load Balancer (LB), havendo uma limitação de 15 certs por LB.

Leia mais »