cert-manager: Certificados TLS Automáticos no Kubernetes Sem Renovar na Mão
Como o cert-manager emite e renova certificados TLS via ACME e Let's Encrypt: Issuers, Certificates, desafios HTTP-01 e DNS-01, e as armadilhas comuns.
Neste artigo
Existe um tipo de incidente que quase toda equipe de infraestrutura vive pelo menos uma vez: o certificado TLS que venceu num domingo de madrugada. O site cai, os navegadores gritam "sua conexão não é segura", as integrações via API param porque validam certificado, e alguém acorda para descobrir que a renovação — que dependia de uma pessoa lembrar de rodar um comando a cada noventa dias — simplesmente não aconteceu. Certificado é uma bomba-relógio silenciosa: funciona perfeitamente até o segundo em que expira, e então falha de forma total e simultânea.
A resposta madura para isso é nunca deixar um humano no caminho crítico da renovação. Certificados devem ser emitidos, entregues e renovados por automação, com folga, sem intervenção. No Kubernetes, a ferramenta padrão para isso é o cert-manager: um operator que transforma certificado em um recurso declarativo, do mesmo jeito que você declara um Deployment. Você diz "quero um certificado válido para este domínio", e o cert-manager cuida de obtê-lo, guardá-lo e trocá-lo antes que expire — para sempre, sem você tocar mais no assunto.
Neste guia você vai entender o que o cert-manager faz por baixo, como o protocolo ACME prova que você controla um domínio, a diferença entre os objetos Issuer e Certificate, quando escolher o desafio HTTP-01 versus o DNS-01, como a integração com o Ingress emite certificados automaticamente, e as armadilhas que travam a emissão na prática — a começar pelos rate limits do Let's Encrypt, que já arruinaram muitos ambientes de teste.
O que é o cert-manager
O cert-manager é um controller que roda no cluster e trata certificados como estado desejado. Ele estende a API do Kubernetes com recursos próprios (CRDs) e opera no mesmo loop de reconciliação de tudo no Kubernetes: você declara o que quer, ele compara com o que existe e age para fechar a diferença. Se você pede um Certificate para loja.exemplo.com, o cert-manager verifica se já existe um certificado válido; se não existe, ele emite; se está perto de expirar, ele renova. O resultado final vive num Secret do tipo TLS, contendo a chave privada e o certificado, pronto para o Ingress ou o Gateway consumir.
O valor central está na renovação automática. Certificados emitidos por autoridades gratuitas como o Let's Encrypt têm vida curta — noventa dias —, justamente para forçar a automação. O cert-manager renova bem antes do vencimento (por volta de trinta dias antes, por padrão), o que dá uma janela enorme de segurança: mesmo que algo falhe numa tentativa, há semanas para tentar de novo antes que o certificado realmente expire. Você deixa de pensar em datas de validade e passa a confiar num sistema que trabalha com margem.
ACME e Let's Encrypt: provando que o domínio é seu
Antes de qualquer autoridade certificadora emitir um certificado para loja.exemplo.com, ela precisa ter certeza de que quem pede realmente controla esse domínio — caso contrário, qualquer um pediria certificado para domínios alheios. O ACME (Automatic Certificate Management Environment) é o protocolo que automatiza essa prova de controle. Em vez de um processo manual e demorado, a CA lança um desafio: ela pede que você demonstre controle do domínio realizando uma ação que só o dono conseguiria fazer, e o cliente ACME — no nosso caso, o cert-manager — cumpre esse desafio automaticamente.
O Let's Encrypt é a autoridade ACME mais conhecida, gratuita e amplamente confiada pelos navegadores, e é a razão de o HTTPS ter se tornado universal. Mas gratuito não significa ilimitado: o Let's Encrypt impõe rate limits — limites de quantos certificados você pode emitir por domínio por semana, por exemplo. Estourar esses limites bloqueia novas emissões por dias, o que é doloroso em produção e desastroso em testes. Por isso o Let's Encrypt mantém um ambiente de staging, com limites folgados e certificados não confiados pelos navegadores, feito exatamente para você validar sua configuração sem queimar a cota de produção. A regra de ouro: teste sempre no staging primeiro, e só aponte para produção quando a emissão funcionar de ponta a ponta.
Os objetos: Issuer, Certificate e o que roda por baixo
O cert-manager organiza o trabalho em alguns recursos que vale entender. O Issuer representa uma autoridade emissora e como falar com ela — por exemplo, "o Let's Encrypt de produção, usando este e-mail de contato e este método de desafio". O Issuer tem escopo de namespace: ele só serve os certificados do namespace onde vive. Quando você quer uma emissora compartilhada por todo o cluster, usa o ClusterIssuer, que é idêntico em função mas com escopo global — muito mais comum na prática, porque evita duplicar a configuração de emissora em cada namespace.
O Certificate é onde você declara o que quer: os domínios (incluindo wildcards, se aplicável), qual Issuer usar, e o nome do Secret onde o resultado deve ser gravado. A partir dele, o cert-manager cria objetos internos que executam o protocolo: um CertificateRequest (o pedido concreto à CA), um Order (a ordem ACME) e um ou mais Challenge (os desafios que precisam ser cumpridos). Você raramente cria esses últimos à mão, mas conhecê-los é essencial para diagnóstico: quando um certificado não sai, é olhando o estado do Order e do Challenge que você descobre por que a prova de controle do domínio falhou.
HTTP-01 versus DNS-01: escolhendo o desafio
O coração operacional do cert-manager é o tipo de desafio ACME que você escolhe, porque cada um prova controle do domínio de um jeito diferente, com implicações práticas distintas.
O desafio HTTP-01 funciona servindo um token secreto num caminho específico do seu site: http://loja.exemplo.com/.well-known/acme-challenge/<token>. A CA acessa essa URL pela internet pública e, se encontra o token esperado, conclui que você controla o domínio — afinal, só quem controla o servidor daquele host poderia colocar o arquivo ali. O cert-manager integra isso com o Ingress, criando temporariamente as rotas necessárias para servir o token. É simples de configurar e não exige credenciais de DNS, mas tem duas limitações importantes: exige que a porta 80 esteja acessível publicamente naquele domínio, e não consegue emitir certificados wildcard (*.exemplo.com), porque não há um host único e público para servir o token de todos os subdomínios.
O desafio DNS-01 prova controle de outra forma: o cert-manager cria um registro TXT específico na zona DNS do domínio, e a CA consulta esse registro para confirmar. Como só quem administra o DNS do domínio consegue criar aquele TXT, a prova é válida. Isso destrava o grande diferencial: o DNS-01 permite certificados wildcard, porque a prova é sobre a zona inteira, não sobre um host servido por HTTP. Também funciona para serviços internos que não estão expostos na porta 80. A contrapartida é que o cert-manager precisa de credenciais de API do seu provedor de DNS (Route 53, Cloud DNS, Cloudflare e afins) para criar e remover o registro automaticamente, o que adiciona uma dependência e uma superfície de segurança a gerenciar.
A regra prática: use HTTP-01 para certificados de hosts públicos individuais quando a porta 80 está disponível; use DNS-01 quando precisar de wildcard, quando o serviço não é público, ou quando expor a porta 80 é indesejável.
Integração com o Ingress e outros emissores
Na prática cotidiana, você raramente escreve um objeto Certificate à mão. O caminho mais comum é anotar o próprio Ingress com algo como cert-manager.io/cluster-issuer: letsencrypt-prod e declarar o host no bloco de TLS. O cert-manager observa o Ingress, entende que aquele host precisa de certificado, cria o Certificate correspondente sozinho, cumpre o desafio, grava o Secret e o Ingress passa a servir HTTPS. É o fluxo "anote e esqueça": você configura a emissora uma vez, e cada novo Ingress ganha TLS automaticamente. O mesmo se aplica, de forma equivalente, à Gateway API moderna.
Vale lembrar que o cert-manager não serve só ao Let's Encrypt. Ele suporta outros tipos de Issuer para cenários diferentes: uma CA interna (ou self-signed) para emitir certificados de uso interno, como o mTLS entre serviços de um mesh, onde você não precisa de confiança pública mas quer criptografia e identidade; integração com o Vault como autoridade emissora; e provedores comerciais como o Venafi em ambientes corporativos. A distinção mental importante é entre certificados públicos (confiados pelos navegadores, para o tráfego externo) e certificados internos (confiados apenas dentro da sua fronteira, para comunicação serviço a serviço) — o cert-manager cobre os dois mundos com o mesmo modelo declarativo.
Armadilhas comuns e diagnóstico
Alguns problemas aparecem com frequência suficiente para valer um aviso. O rate limit do Let's Encrypt é o campeão: configurar contra produção, errar, tentar de novo várias vezes, e de repente estar bloqueado por dias — por isso, teste no staging. No DNS-01, a propagação lenta do registro TXT pode fazer a CA consultar antes do registro estar visível globalmente; o cert-manager reintenta, mas configurações agressivas de timeout ou zonas com TTL alto atrasam a emissão. Ainda no DNS-01, credenciais do provedor com permissão insuficiente (ou um RBAC mal configurado no cluster) impedem a criação do TXT silenciosamente. No HTTP-01, um firewall ou um redirect forçado de HTTP para HTTPS pode impedir a CA de acessar o caminho do token na porta 80.
Um detalhe subestimado é o relógio do cluster: certificados são sensíveis a tempo, e um nó com horário dessincronizado pode rejeitar certificados válidos ou aceitar expirados. E há o clássico esquecimento de que o Secret gerado vive no etcd — vale garantir criptografia em repouso e RBAC restrito sobre quem pode ler esse Secret.
Para diagnosticar, o caminho é seguir a cadeia de objetos de trás para frente. Um kubectl describe certificate mostra se ele está Ready e, se não, aponta para o CertificateRequest. Descrevendo o Order e o Challenge, você vê exatamente onde a prova de controle emperrou — token não servido, TXT não encontrado, CA inacessível. Noventa por cento dos problemas se revelam nessa leitura.
Por onde começar
Comece instalando o cert-manager e configurando dois ClusterIssuers: um apontando para o staging do Let's Encrypt e outro para produção. Faça todos os seus primeiros testes contra o staging — os certificados não serão confiados pelos navegadores, mas você valida o fluxo inteiro sem risco de rate limit. Só depois que a emissão funcionar de ponta a ponta, troque a anotação do Ingress para o issuer de produção.
Escolha o desafio pela sua necessidade: se você só precisa de certificados para hosts públicos individuais e a porta 80 está disponível, o HTTP-01 é o caminho mais simples. Se precisa de wildcard ou de certificados para serviços não públicos, invista na configuração do DNS-01 com as credenciais do seu provedor de DNS bem escopadas. Anote seus Ingress com o issuer, deixe o cert-manager criar os certificados sozinho, e monitore o estado dos objetos Certificate como parte da sua observabilidade — um certificado que não fica Ready é um alerta que você quer receber semanas antes de qualquer expiração, não no domingo de madrugada.