Toutes les ressources

Guide pratique · cert-manager

cert-manager : certificat Ready, mais mauvais certificat sur l’Ingress

cert-manager indique Ready=True, mais le navigateur reçoit encore un certificat ancien ou inattendu. Comparez trois éléments : le certificat stocké dans le Secret, le Secret référencé par l’Ingress et le certificat reçu lors d’une nouvelle connexion TLS.

Ce guide concerne Kubernetes Ingress avec cert-manager, lorsque le contrôleur Ingress termine TLS. Adaptez le contexte, le namespace, les noms des ressources et le nom d’hôte avant d’exécuter les commandes de diagnostic en lecture seule. Elles supposent Bash sous Linux, kubectl, OpenSSL et les outils GNU coreutils. Gateway API et le TLS passthrough suivent d’autres chemins de configuration.

1. Lire l’état du Certificate dans le bon cluster

Définissez ces variables dans une session Bash et conservez cette session pour les commandes Kubernetes suivantes. Le contexte explicite évite d’envoyer les vérifications vers un autre cluster défini par défaut. Lisez les conditions, les événements, les dates de validité et la date de renouvellement dans la description du Certificate.

TLS_CONTEXT=your-context
TLS_NAMESPACE=apps
TLS_CERTIFICATE=site
TLS_INGRESS=site
kubectl --context "$TLS_CONTEXT" -n "$TLS_NAMESPACE" \
  get certificate "$TLS_CERTIFICATE"
kubectl --context "$TLS_CONTEXT" -n "$TLS_NAMESPACE" \
  describe certificate "$TLS_CERTIFICATE"

Ready=True décrit l’état connu de cert-manager pour ce Certificate. Ce n’est pas un test TLS externe. Si Ready vaut False ou est absent, partez du motif indiqué et examinez l’Issuer ou le ClusterIssuer référencé, puis le CertificateRequest. Les Orders et Challenges concernent les émetteurs ACME. Évitez de commencer le diagnostic en supprimant le Secret ou en forçant des émissions répétées.

2. Relever le certificat stocké dans le Secret

Lisez spec.secretName dans le Certificate pour retrouver le Secret exact. La commande suivante affiche l’empreinte, l’émetteur, les dates et les SAN du certificat public terminal. La lecture d’un Secret exige les droits Kubernetes correspondants ; ne copiez pas un export complet du Secret dans des journaux ou un ticket de support.

set -o pipefail
TLS_SECRET=$(kubectl --context "$TLS_CONTEXT" -n "$TLS_NAMESPACE" \
  get certificate "$TLS_CERTIFICATE" -o jsonpath='{.spec.secretName}')
if [ -n "$TLS_SECRET" ]; then
  kubectl --context "$TLS_CONTEXT" -n "$TLS_NAMESPACE" \
    get secret "$TLS_SECRET" -o jsonpath='{.data.tls\.crt}' |
    base64 --decode |
    openssl x509 -noout -sha256 -fingerprint \
      -issuer -dates -ext subjectAltName
fi

Conservez l’empreinte SHA-256 comme valeur attendue. Un certificat couvrant example.com peut être différent de celui que vous souhaitiez déployer. Les dates et les noms aident au diagnostic, mais l’empreinte identifie le certificat comparé.

3. Vérifier le Secret référencé par l’Ingress

Examinez spec.tls[].secretName, spec.tls[].hosts, les hôtes des règles de routage et ingressClassName. Le Secret TLS doit se trouver dans le même namespace que l’Ingress. Son certificat doit couvrir le nom d’hôte. Vérifiez que le contrôleur prévu prend en charge cette classe d’Ingress et peut lire le Secret.

kubectl --context "$TLS_CONTEXT" -n "$TLS_NAMESPACE" \
  get ingress "$TLS_INGRESS" -o yaml
kubectl --context "$TLS_CONTEXT" -n "$TLS_NAMESPACE" \
  describe ingress "$TLS_INGRESS"

Comparez cette référence avec spec.secretName du Certificate. Si l’écart n’est pas voulu, corrigez le manifeste, les valeurs Helm ou la source GitOps qui gère l’Ingress. Avec un Ingress annoté, ingress-shim crée les ressources Certificate à partir de cette configuration ; examinez les annotations avant d’ajouter un second Certificate pour le même Secret. Si les références sont correctes, recherchez des erreurs de chargement ou de droits dans les événements et les journaux du contrôleur Ingress.

4. Comparer avec une nouvelle connexion TLS

Lancez cette commande depuis l’extérieur du réseau d’hébergement, sur un service que vous administrez ou êtes autorisé à examiner. Redéfinissez le nom d’hôte si vous utilisez un autre shell. Le SNI indique au serveur le nom demandé. Comparez l’empreinte affichée à celle du Secret.

set -o pipefail
TLS_HOST=example.com
timeout 10 openssl s_client -connect "$TLS_HOST:443" \
  -servername "$TLS_HOST" </dev/null |
  openssl x509 -noout -sha256 -fingerprint \
    -issuer -dates -ext subjectAltName

La commande affiche le certificat présenté. Elle ne valide ni la confiance dans sa chaîne ni la correspondance du nom d’hôte. Un CDN ou un load balancer qui termine TLS avant l’Ingress peut légitimement servir un autre certificat. Vérifiez ce composant, puis l’origine séparément si elle est accessible. Pour cibler une adresse, remplacez la destination de -connect par IP:443, ou [IPv6]:443, en conservant -servername. Répétez le contrôle pour les adresses et les réplicas du contrôleur concernés.

5. Reproduire l’écart dans un cluster temporaire

Le script crée un cluster kind dédié, installe cert-manager et utilise Traefik comme contrôleur Ingress. Un Issuer SelfSigned crée site-tls pour renewal.test. Le Certificate devient Ready, mais l’Ingress référence stale-tls, qui contient un autre certificat valide pour le même nom. Remplacer cette référence par site-tls change le certificat reçu lors du test TLS.

Télécharger et examiner la démonstration cert-manager

Prérequis : un moteur Docker local, kind, kubectl, curl, Bash, OpenSSL et GNU coreutils sous Linux. Prévoyez plusieurs Gio de mémoire et d’espace disque pour le cluster et les images téléchargées. Testé avec kind 0.33.0, Kubernetes et kubectl 1.35.8, cert-manager 1.21.3 et Traefik 3.7.16.

Lisez le script, puis lancez bash cert-manager-ingress-check.sh. Il utilise un kubeconfig privé, un port-forward sur la boucle locale et supprime son cluster et ses fichiers temporaires à la sortie. Les images téléchargées sur l’hôte restent en cache.

READY reste True ; BEFORE diffère de EXPECTED ; AFTER correspond à EXPECTED. Des assertions vérifient ces valeurs. Le test couvre une émission réelle par cert-manager et le chargement côté Ingress avec des certificats autosignés, pas la validation ACME, le renouvellement ou la confiance des navigateurs publics.

6. Vérifier le résultat, puis configurer les alertes d’expiration

Après correction, répétez le test externe et relevez l’adresse, le SNI, l’heure d’observation et l’empreinte. Si le certificat attendu est servi mais que le navigateur le refuse encore, examinez la chaîne, les noms couverts et la confiance dans l’émetteur. Un nouveau renouvellement ne résout pas toutes les erreurs TLS.

Nocert observe périodiquement les certificats servis par les points de terminaison TLS accessibles et évalue les règles d’alerte d’expiration selon un cycle quotidien. Vérifiez le point de terminaison et l’heure d’observation, puis configurez les destinataires. Ce suivi complète le contrôle immédiat après déploiement. Nocert ne modifie ni votre Secret Kubernetes ni votre Ingress, ne renouvelle pas le certificat et ne garantit pas que tous les visiteurs reçoivent le même certificat.

Sources techniques