Publique sites no Kubernetes com HTTPS automático: Ingress com Traefik, cert-manager e Let's Encrypt, redirecionamento e diagnóstico de certificados.

Para que serve

Este artigo mostra como publicar aplicações do cluster na internet com HTTPS automático usando um Ingress com Traefik e o cert-manager com Let's Encrypt no Kubernetes. O Ingress recebe as conexões nas portas 80 e 443 e encaminha cada domínio para o serviço certo; o cert-manager pede e renova os certificados sozinho. Os exemplos usam k3s, que já traz o Traefik instalado.

Sobre o ingress-nginx: o projeto comunitário ingress-nginx foi aposentado pelo Kubernetes; a manutenção terminou em março de 2026 e não há mais correções de segurança. Não o use em instalações novas. Se você já tem clusters com ele, planeje a troca para Traefik (que consegue ler boa parte das anotações do ingress-nginx), outro controlador mantido ou Gateway API.

Pré-requisitos

  • Cluster k3s funcionando (veja Como instalar o k3s em servidor dedicado) e kubectl e helm configurados (veja Helm na prática).
  • Um nome DNS (registro A/AAAA) apontando para o IP público que recebe o tráfego: o IP do nó ou um IP do bloco /28 entregue pelo MetalLB (veja Como usar MetalLB com os IPs públicos do bloco /28).
  • Portas 80 e 443 liberadas no firewall para esse IP. A porta 80 é obrigatória para o desafio HTTP-01 do Let's Encrypt.

Etapa 1: confirmar que o Traefik está ativo

kubectl -n kube-system get pods -l app.kubernetes.io/name=traefik
kubectl -n kube-system get svc traefik
kubectl get ingressclass

O serviço traefik deve ter um EXTERNAL-IP (o IP do nó, via ServiceLB do k3s, ou o IP do MetalLB) e deve existir a IngressClass traefik. O k3s atual vem com Traefik v3.

Etapa 2: redirecionar HTTP para HTTPS

No k3s, não edite o manifesto do Traefik diretamente: crie um HelmChartConfig, que é mesclado aos valores padrão e sobrevive às atualizações. No nó servidor:

cat > /var/lib/rancher/k3s/server/manifests/traefik-config.yaml <<'EOF'
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    additionalArguments:
      - "--entryPoints.web.http.redirections.entryPoint.to=websecure"
      - "--entryPoints.web.http.redirections.entryPoint.scheme=https"
      - "--entryPoints.web.http.redirections.entryPoint.permanent=true"
EOF

O k3s reaplica o chart em alguns segundos. Em cluster com vários servidores, basta criar o arquivo em um deles.

Etapa 3: instalar o cert-manager

helm install cert-manager oci://quay.io/jetstack/charts/cert-manager \
  --version v1.21.2 \
  --namespace cert-manager --create-namespace \
  --set crds.enabled=true

kubectl -n cert-manager get pods

Aguarde os três pods (cert-manager, cainjector e webhook) ficarem Running. Confira a versão mais recente na documentação do cert-manager antes de instalar.

Etapa 4: criar os emissores do Let's Encrypt

Crie dois ClusterIssuer: staging, para testar sem esbarrar nos limites de emissão, e produção. Salve como issuers.yaml, troque o e-mail e aplique com kubectl apply -f issuers.yaml:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: infra@seudominio.com.br
    privateKeySecretRef:
      name: letsencrypt-staging-conta
    solvers:
      - http01:
          ingress:
            ingressClassName: traefik
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: infra@seudominio.com.br
    privateKeySecretRef:
      name: letsencrypt-prod-conta
    solvers:
      - http01:
          ingress:
            ingressClassName: traefik

Verifique: kubectl get clusterissuer deve mostrar READY True nos dois.

Etapa 5: publicar uma aplicação com Ingress e certificado

kubectl create namespace site
kubectl -n site create deployment web --image=nginx:alpine
kubectl -n site expose deployment web --port=80

Crie ingress.yaml começando pelo emissor de staging:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  namespace: site
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-staging
spec:
  ingressClassName: traefik
  tls:
    - hosts:
        - app.seudominio.com.br
      secretName: web-tls
  rules:
    - host: app.seudominio.com.br
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

Aplique com kubectl apply -f ingress.yaml. Quando o certificado de staging sair, troque a anotação para letsencrypt-prod, apague o Secret de teste (kubectl -n site delete secret web-tls) e aplique de novo.

Como saber se funcionou

kubectl -n site get certificate
curl -I http://app.seudominio.com.br
curl -vI https://app.seudominio.com.br 2>&1 | grep -E "issuer|HTTP/"

O certificado deve estar READY True, o HTTP deve responder com redirecionamento 301/308 para HTTPS, e o emissor deve ser o Let's Encrypt (no staging aparece um emissor de teste, que o navegador não reconhece; isso é esperado). A renovação é automática, cerca de 30 dias antes do vencimento.

Problemas comuns

Certificado fica em READY False

Siga a cadeia de objetos até achar o erro:

kubectl -n site describe certificate web-tls
kubectl -n site get certificaterequest,order,challenge
kubectl -n site describe challenge

As causas mais frequentes são DNS ainda não propagado ou apontando para outro IP, porta 80 bloqueada no firewall ou um proxy (como o da Cloudflare em modo laranja) interceptando o desafio. Teste de fora: curl http://app.seudominio.com.br/.well-known/acme-challenge/teste deve chegar ao Traefik (resposta 404 do Traefik, não timeout).

Erro "too many certificates" ou limite de taxa

Você emitiu muitas vezes em produção para o mesmo domínio. Use o staging enquanto ajusta a configuração e aguarde o limite expirar.

Preciso de certificado curinga (*.dominio)

O desafio HTTP-01 não emite curingas. Use o desafio DNS-01 com o provedor do seu DNS (Cloudflare, Route 53 e outros têm suporte no cert-manager).

Quero usar outro controlador no lugar do Traefik

Inicie o k3s com disable: [traefik] no config.yaml de todos os servidores e instale o controlador escolhido. Ajuste o ingressClassName nos Ingress e nos ClusterIssuer.

Perguntas frequentes

O que é Gateway API?

É a evolução do Ingress no Kubernetes, com recursos como Gateway e HTTPRoute e regras mais expressivas. O Traefik v3 do k3s suporta Gateway API ativando o provedor kubernetesGateway no HelmChartConfig, e o cert-manager também emite certificados para Gateways.

O ingress-nginx para de funcionar depois da aposentadoria?

Ele continua rodando, mas sem correções de segurança. Expor um componente sem manutenção à internet é um risco crescente.

Preciso de um IP por site?

Não. O Ingress separa os sites pelo nome do host (SNI), então um único IP atende dezenas de domínios.

Leitura complementar

Precisa de ajuda?

Se o desafio do Let's Encrypt não chega ao servidor e você suspeita de bloqueio na rede, abra um ticket com o domínio, o IP e a saída de kubectl describe challenge.

Esta resposta lhe foi útil? 0 Usuários acharam útil (0 Votos)

Leia também