Kubernetes · cert-manager · TLS

Tu certificado de cert-manager se queda en pending y el reto HTTP-01 da 404

El Certificate sigue en READY False y el Challenge repite "wrong status code '404', expected '200'". Me pasó en mi propio clúster k3s con la página ya abriendo con candado, así que empiezo por lo que me engañó a mí.

1. Mira el estado real, no el candado del navegador

$ kubectl get certificate,order,challenge -A
$ kubectl describe challenge <nombre> -n <ns> | grep -A2 Reason
Reason: Waiting for HTTP-01 challenge propagation: wrong status code '404', expected '200'

Si el navegador muestra candado y aun así el Certificate está en False, el certificado que ves lo emitió otra cosa. Ese es el caso más traicionero, porque todo parece bien hasta el día de la renovación.

2. Pide tú mismo la URL del reto

$ kubectl get ingress -n <ns> | grep acme-http-solver
$ kubectl get ingress <solver> -n <ns> -o jsonpath='{.spec.rules[0].http.paths[0].path}'
$ curl -sI http://tu-dominio/.well-known/acme-challenge/<token>

Lo que responda esa petición te dice cuál de las cuatro causas tienes.

3. Las cuatro causas y cómo distinguirlas

Lo que vesCausaCorrección
404 y en los registros de Traefik: Cannot retrieve the ACME challengeOtro emisor ACME (el certResolver de Traefik) atiende /.well-known/acme-challenge de ese dominioDeja un solo emisor: o todo con cert-manager, o el Ingress con traefik.ingress.kubernetes.io/router.tls.certresolver y sin secretName
404 del backend por defectoLa ingressClassName del solucionador no es la de tu controladorFíjala en el emisor: solvers[].http01.ingress.ingressClassName
403 o 301Un middleware (lista de IP por país, autenticación, redirección a HTTPS) se aplica también al reto. Let's Encrypt valida desde varias regiones, así que un filtro por país lo rompeExcluye la ruta del reto del middleware o usa el reto DNS-01
Tiempo agotado o conexión rechazadaEl DNS no apunta al clúster o el puerto 80 está cerradodig +short tu-dominio y abre el 80 hacia el controlador

4. Mi caso: dos emisores para un mismo dominio

$ kubectl -n kube-system logs deploy/traefik | grep "ACME challenge"
ERR Cannot retrieve the ACME challenge for labs.ingeniumcodex.com (token "ImPlJ6...")

Una ruta de Traefik del mismo dominio usaba certResolver: letsencrypt. Traefik se quedó con el reto, emitió su propio certificado (el del candado) y cert-manager pasó nueve horas esperando un 200 que nunca iba a llegar. Como el resto de mi clúster ya usa el resolvedor de Traefik, cambié la anotación del Ingress, quité el secretName y borré el Certificate atascado:

metadata:
  annotations:
    traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
spec:
  tls:
    - hosts: [tu-dominio]

Verificación: kubectl get challenge -A ya no lista nada y openssl s_client -connect tu-dominio:443 -servername tu-dominio | openssl x509 -noout -issuer -enddate muestra el emisor y la fecha de vencimiento.

Practica Kubernetes en tu propio clúster, gratis

Te envío al correo dos laboratorios completos con su solución: el 01 (namespace y deployment) y el 08 (ResourceQuota). Cada uno termina con un comando de verificación, no con "parece que funcionó".

Quiero los 2 laboratorios gratis