Cert-Manager sur Kubernetes : Guide complet de configuration pour la gestion automatisée des certificats TLS
Cert-Manager est un contrôleur Kubernetes open-source qui automatise entièrement le cycle de vie des certificats TLS — de l’émission initiale à la validation et au renouvellement — en s’intégrant directement avec des autorités de certification telles que Let’s Encrypt, HashiCorp Vault et les systèmes PKI privés. Il élimine les workflows manuels de certificats en traitant les certificats comme des ressources Kubernetes natives, gérées de manière déclarative via des Custom Resource Definitions (CRDs).
Pour tout cluster Kubernetes en production, les certificats TLS expirés ou mal configurés sont l’une des causes les plus fréquentes d’interruptions non planifiées. Cert-Manager résout ce problème en réconciliant continuellement l’état des certificats, en renouvelant automatiquement les identifiants avant leur expiration, et en stockant le matériel de clé résultant dans des Secrets Kubernetes que les contrôleurs Ingress et les charges de travail peuvent consommer immédiatement.
Pourquoi Cert-Manager est la référence pour l’automatisation TLS Kubernetes
Avant que Cert-Manager ne devienne la solution de facto, les équipes scriptaient soit les renouvellements certbot sur des nœuds individuels, faisaient pivoter manuellement les certificats entre les namespaces, ou s’appuyaient sur des intégrations spécifiques aux fournisseurs cloud qui créaient une dépendance fournisseur. Cert-Manager unifie toutes ces approches sous un seul plan de contrôle natif Kubernetes.
Principaux avantages par rapport aux approches ad hoc :
- Gestion déclarative : L’intention du certificat est exprimée sous forme de manifeste YAML, versionné aux côtés du code applicatif.
- Réconciliation automatique : La boucle du contrôleur détecte les écarts entre l’état souhaité et l’état réel du certificat et les corrige sans intervention humaine.
- Support multi-émetteurs : Un seul cluster peut simultanément utiliser Let’s Encrypt pour les services publics, une CA interne pour le mTLS de service mesh, et HashiCorp Vault pour les charges de travail sensibles aux secrets.
- Piste d’audit : Chaque objet
CertificateRequestest persisté dans l’API Kubernetes, vous donnant un historique complet des émissions.
Exécuter Kubernetes sur une plateforme d’hébergement VPS avec stockage NVMe et accès root complet vous donne le contrôle nécessaire pour configurer des résolveurs DNS personnalisés, gérer les règles de pare-feu pour les challenges ACME HTTP-01, et installer des CRDs au niveau du cluster sans restriction — tous prérequis pour un déploiement Cert-Manager de qualité production.
Architecture principale : fonctionnement interne de Cert-Manager
Comprendre l’architecture interne de Cert-Manager permet d’éviter les mauvaises configurations et de déboguer rapidement les échecs d’émission.
La machine à états du cycle de vie des certificats
Cert-Manager gère les certificats via une machine à états déterministe. Chaque ressource Certificate passe par les états suivants :
- En attente (Pending) — L’objet
Certificateexiste mais aucunCertificateRequestvalide n’a été satisfait. - En cours d’émission (Issuing) — Un
CertificateRequesta été créé et soumis à l’émetteur configuré. - Prêt (Ready) — Un certificat valide et non expiré est stocké dans le
SecretKubernetes référencé. - Renouvellement en attente (Renewal Pending) — Le certificat se trouve dans la fenêtre
renewBefore(par défaut : 30 jours avant expiration) et un nouveauCertificateRequestest en cours de traitement.
Le contrôleur surveille tous les objets Certificate à l’échelle du cluster et réconcilie continuellement leur état. Si un Secret est supprimé manuellement, Cert-Manager détecte la ressource manquante et déclenche immédiatement une réémission — un comportement d’auto-guérison critique qui prévient les pannes accidentelles.
Composants CRD principaux
| Ressource | Portée | Objectif |
|---|---|---|
| — | — | — |
| `Issuer` | Namespace | Définit une configuration CA pour un seul namespace |
| `ClusterIssuer` | À l’échelle du cluster | Définit une configuration CA utilisable par tous les namespaces |
| `Certificate` | Namespace | Déclare le certificat TLS souhaité et ses propriétés |
| `CertificateRequest` | Namespace | Suit une demande de signature de certificat ponctuelle |
| `Order` | Namespace | Représente une commande ACME auprès d’une CA (ex. : Let’s Encrypt) |
| `Challenge` | Namespace | Suit un seul challenge ACME (HTTP-01 ou DNS-01) |
Les ressources Order et Challenge sont créées automatiquement par l’émetteur ACME — vous interagissez rarement directement avec elles, mais leur inspection est la principale voie de débogage lorsque l’émission est bloquée.
Stockage des certificats et format des Secrets
Une fois émis, Cert-Manager écrit trois clés de données dans le Secret Kubernetes cible :
tls.crt— La chaîne de certificats complète (feuille + intermédiaires), encodée en PEM.tls.key— La clé privée, encodée en PEM.ca.crt— Le certificat CA émetteur (renseigné pour les CA internes ; peut être vide pour les émetteurs ACME).
Les contrôleurs Ingress, les service meshes et les pods applicatifs montent ce Secret directement. Le format est compatible avec NGINX, Traefik, Istio, Linkerd et la plupart des autres consommateurs TLS natifs Kubernetes.
Émetteurs supportés et quand utiliser chacun
ACME (Let’s Encrypt et alternatives)
Le protocole ACME est le chemin d’émission le plus courant. Cert-Manager implémente le client ACME RFC 8555 complet, supportant les endpoints de staging et de production.
Challenge HTTP-01 : Cert-Manager sert temporairement un jeton à http://<domain>/.well-known/acme-challenge/<token>. Cela nécessite que le domaine résolve vers une IP publiquement accessible sur le port 80. Cela fonctionne pour les certificats mono-domaine et SAN mais ne peut pas émettre de certificats wildcard.
Challenge DNS-01 : Cert-Manager crée un enregistrement TXT _acme-challenge.<domain> via une API de fournisseur DNS. Cela fonctionne derrière des pare-feux, supporte les certificats wildcard (*.example.com), et est requis pour tout cluster non directement exposé à internet. Les fournisseurs DNS supportés incluent Cloudflare, Route53, Google Cloud DNS, Azure DNS, et bien d’autres via des solvers webhook.
HashiCorp Vault
L’émetteur Vault s’intègre avec le moteur de secrets PKI de Vault. C’est le choix préféré pour :
- Le mTLS de microservices internes où les certificats doivent être de courte durée (heures, pas mois).
- Les environnements avec des exigences strictes de garde des clés où les clés privées ne doivent jamais quitter Vault.
- La rotation automatisée des certificats liée au système de renouvellement de bail de Vault.
Émetteurs auto-signés et CA
L’émetteur SelfSigned génère des certificats signés par la propre clé privée du certificat — utile pour amorcer une CA racine au sein du cluster. L’émetteur CA utilise un Secret Kubernetes contenant une paire de clés CA pour signer des certificats, ce qui le rend adapté aux environnements de développement internes et au PKI de service mesh.
Venafi
L’intégration Venafi cible les environnements d’entreprise avec application centralisée des politiques de certificats, audit de conformité, et intégration avec des modules de sécurité matériels (HSMs).
Cert-Manager vs. approches alternatives d’automatisation TLS
| Approche | Support Wildcard | Natif Kubernetes | Multi-CA | Renouvellement auto | Complexité |
|---|---|---|---|---|---|
| — | — | — | — | — | — |
| Cert-Manager | Oui (DNS-01) | Oui (CRDs) | Oui | Oui | Moyenne |
| Certbot manuel | Non (HTTP-01 uniquement) | Non | Limité | Scripté | Faible–Moyenne |
| Terminaison TLS Cloud LB | Variable | Non | Non | Oui | Faible |
| Istio / CA Service Mesh | Interne uniquement | Oui | Non | Oui | Élevée |
| HashiCorp Vault (autonome) | Oui | Non | Oui | Manuel | Élevée |
Pour les équipes exécutant Kubernetes sur un Serveur Dédié ou VPS, Cert-Manager est la seule approche qui est simultanément native Kubernetes, supporte toutes les principales CAs, et ne nécessite aucune intervention manuelle continue.
Installation de Cert-Manager : configuration prête pour la production
Prérequis
- Kubernetes 1.22+ (1.26+ recommandé pour une stabilité complète des CRDs)
kubectlconfiguré avec les privilèges cluster-admin- Helm 3.x installé
- Un domaine enregistré avec accès à la gestion DNS (pour DNS-01) ou une IP d’ingress publiquement accessible (pour HTTP-01)
Si vous gérez votre propre domaine, l’enregistrement de domaine via un fournisseur qui expose une API est fortement recommandé — cela permet une résolution entièrement automatisée des challenges DNS-01 sans intervention manuelle.
Étape 1 : Installer les CRDs et le contrôleur Cert-Manager
La méthode d’installation en production recommandée utilise Helm avec les CRDs gérés séparément pour éviter les conflits de mise à niveau Helm :
# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
helm repo update
# Install Cert-Manager with CRDs included
helm install cert-manager jetstack/cert-manager
--namespace cert-manager
--create-namespace
--version v1.14.5
--set installCRDs=true
--set global.leaderElection.namespace=cert-managerVérifiez que les trois pods principaux sont en cours d’exécution avant de continuer :
kubectl get pods --namespace cert-managerRésultat attendu :
NAME READY STATUS RESTARTS AGE
cert-manager-xxxxxxxxx-xxxxx 1/1 Running 0 60s
cert-manager-cainjector-xxxxxxxxx-xxxxx 1/1 Running 0 60s
cert-manager-webhook-xxxxxxxxx-xxxxx 1/1 Running 0 60sLe cainjector injecte les données du bundle CA dans les configurations webhook. Le webhook valide et mute les objets CRD Cert-Manager — s’il ne fonctionne pas, toutes les opérations kubectl apply sur les ressources Cert-Manager échoueront.
Étape 2 : Configurer un ClusterIssuer pour Let’s Encrypt
Commencez toujours par l’environnement de staging de Let’s Encrypt pour éviter d’atteindre les limites de débit de production (50 certificats par domaine enregistré par semaine) :
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: ops@example.com
privateKeySecretRef:
name: letsencrypt-staging-account-key
solvers:
- http01:
ingress:
class: nginxUne fois que les certificats de staging sont émis avec succès, créez l’émetteur de production :
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@example.com
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginxAppliquez les deux manifestes :
kubectl apply -f clusterissuer-staging.yaml
kubectl apply -f clusterissuer-prod.yamlVérifiez la disponibilité de l’émetteur :
kubectl describe clusterissuer letsencrypt-prodLe champ Status.Conditions doit afficher Ready: True. S’il affiche False, l’enregistrement du compte ACME a échoué — vérifiez l’adresse e-mail et la connectivité réseau depuis le pod cert-manager.
Étape 3 : Demander un certificat explicitement
Vous pouvez demander des certificats soit en créant directement une ressource Certificate, soit en annotant une ressource Ingress. L’approche explicite Certificate vous donne plus de contrôle :
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com-tls
namespace: production
spec:
secretName: example-com-tls-secret
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
commonName: example.com
dnsNames:
- example.com
- www.example.com
duration: 2160h # 90 days (Let's Encrypt default)
renewBefore: 720h # Renew 30 days before expiryAppliquez et surveillez l’émission :
kubectl apply -f certificate.yaml
kubectl describe certificate example-com-tls -n productionSurveillez les objets CertificateRequest et Order pour un statut détaillé :
kubectl get certificaterequest -n production
kubectl describe order -n productionÉtape 4 : Méthode d’annotation Ingress (simplifiée)
Pour les équipes utilisant NGINX Ingress Controller, Cert-Manager peut être déclenché automatiquement via une annotation — aucun manifeste Certificate séparé n’est requis :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: production
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
- www.example.com
secretName: example-com-tls-secret
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80Cert-Manager détecte l’annotation et crée automatiquement la ressource Certificate correspondante. C’est le modèle le plus courant dans les workflows GitOps.
Modèles de configuration avancés
Certificats wildcard avec DNS-01 (exemple Cloudflare)
Les certificats wildcard nécessitent une validation DNS-01. Commencez par créer un Secret contenant votre jeton API Cloudflare :
kubectl create secret generic cloudflare-api-token
--from-literal=api-token=<YOUR_CLOUDFLARE_API_TOKEN>
--namespace cert-managerConfigurez le ClusterIssuer avec un solver DNS-01 :
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod-dns
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@example.com
privateKeySecretRef:
name: letsencrypt-prod-dns-account-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-tokenDemandez le certificat wildcard :
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-example-com
namespace: production
spec:
secretName: wildcard-example-com-tls
issuerRef:
name: letsencrypt-prod-dns
kind: ClusterIssuer
dnsNames:
- "*.example.com"
- example.comPiège critique : Le Secret contenant les identifiants du fournisseur DNS doit résider dans le namespace cert-manager lorsqu’il est référencé par un ClusterIssuer. Si vous le placez dans un autre namespace, le contrôleur ne peut pas le lire et l’émission échouera silencieusement. Vérifiez les logs du contrôleur cert-manager avec kubectl logs -n cert-manager deploy/cert-manager si les challenges sont bloqués.
PKI interne avec un émetteur CA
Pour le mTLS service-à-service au sein d’un cluster, un émetteur CA adossé à une racine auto-signée est plus approprié qu’ACME :
# Step 1: Create a self-signed root CA certificate
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-root
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: internal-root-ca
namespace: cert-manager
spec:
isCA: true
commonName: internal-root-ca
secretName: internal-root-ca-secret
issuerRef:
name: selfsigned-root
kind: ClusterIssuer
---
# Step 2: Create a CA issuer backed by the root certificate
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: internal-ca-issuer
spec:
ca:
secretName: internal-root-ca-secretLes services peuvent désormais demander des certificats de courte durée à internal-ca-issuer pour le mTLS sans aucune dépendance à une CA externe.
Configuration de renewBefore pour les environnements haute sécurité
La valeur par défaut renewBefore de 30 jours est appropriée pour les certificats Let’s Encrypt de 90 jours. Pour les certificats internes de courte durée (ex. : validité de 24 heures), définissez renewBefore à une fraction de la durée totale :
spec:
duration: 24h
renewBefore: 8hCert-Manager commencera le renouvellement 8 heures avant l’expiration, donnant au contrôleur trois fenêtres de renouvellement dans une durée de vie de certificat de 24 heures — une marge de sécurité critique si le cluster connaît une indisponibilité transitoire du serveur API.
Débogage des échecs courants de Cert-Manager
Certificat bloqué en état « Issuing »
# Check the Certificate status
kubectl describe certificate <name> -n <namespace>
# Check the associated CertificateRequest
kubectl describe certificaterequest -n <namespace>
# Check the ACME Order
kubectl describe order -n <namespace>
# Check the Challenge
kubectl describe challenge -n <namespace>
# Check controller logs
kubectl logs -n cert-manager deploy/cert-manager --tail=100Causes racines courantes :
- Échec HTTP-01 : Le contrôleur Ingress ne route pas correctement le trafic
/.well-known/acme-challenge/. Vérifiez que l’objetIngressdu challenge a été créé et que le port 80 est accessible depuis internet. Les pare-feux sur l’hôte doivent autoriser le TCP/80 entrant. - Échec DNS-01 : Le jeton API du fournisseur DNS a des permissions insuffisantes, ou la propagation DNS n’est pas terminée. Les serveurs de validation de Let’s Encrypt peuvent interroger des résolveurs différents de votre DNS local — des délais de propagation de 60 à 120 secondes sont normaux.
- Limite de débit dépassée : Let’s Encrypt impose 5 tentatives de validation échouées par domaine par heure. Après avoir atteint cette limite, vous devez attendre avant de réessayer. Testez toujours avec l’endpoint de staging en premier.
- Webhook non prêt : Si le pod webhook cert-manager ne fonctionne pas, toutes les opérations CRD échoueront avec une erreur de connexion refusée. Assurez-vous que le service webhook a un endpoint valide.
Vérification d’un certificat déployé
# Check the Secret contents
kubectl get secret example-com-tls-secret -n production -o jsonpath='{.data.tls.crt}' | base64 -d | openssl x509 -noout -text
# Check expiry date specifically
kubectl get secret example-com-tls-secret -n production -o jsonpath='{.data.tls.crt}' | base64 -d | openssl x509 -noout -enddateListe de contrôle de durcissement pour la production
Déployer Cert-Manager dans un environnement de production nécessite plus qu’une installation Helm par défaut. Appliquez ces mesures de durcissement avant la mise en production :
- Limites de ressources : Définissez les
requestsetlimitsCPU et mémoire sur les trois pods Cert-Manager pour éviter la contention de ressources sur les nœuds partagés. - Audit RBAC : Cert-Manager nécessite de larges permissions RBAC. Examinez les objets
ClusterRoleinstallés et restreignez-les au minimum nécessaire pour vos types d’émetteurs. - Namespace séparé : Déployez toujours Cert-Manager dans son propre namespace
cert-manager, isolé des charges de travail applicatives. - Surveillance : Exposez l’endpoint de métriques Prometheus de Cert-Manager (
--metrics-listen-address) et alertez surcertmanager_certificate_expiration_timestamp_secondspour détecter les échecs de renouvellement avant qu’ils n’impactent les services. - Sauvegarde de l’état CRD : Incluez les objets
Certificate,ClusterIssueretIssuerdans votre stratégie de sauvegarde du cluster. Perdre ces manifestes après un événement de reprise après sinistre signifie recréer manuellement toutes les configurations de certificats. - Validation en staging : N’émettez jamais votre premier certificat contre un endpoint ACME de production. Les violations de limite de débit peuvent bloquer votre domaine jusqu’à une semaine.
Si vous exécutez plusieurs clusters Kubernetes — par exemple, en séparant les charges de travail de staging et de production — les panneaux de contrôle VPS peuvent simplifier la gestion du cycle de vie des clusters et vous donner une interface unifiée pour provisionner l’infrastructure sous-jacente sur laquelle chaque cluster s’exécute.
Pour les charges de travail nécessitant une inférence accélérée par GPU ou un service ML derrière des endpoints à terminaison TLS, les mêmes modèles Cert-Manager s’appliquent sur l’infrastructure d’hébergement GPU, où la gestion automatisée des certificats est tout aussi critique pour sécuriser les endpoints API des modèles.
Matrice de décision pratique : choisir le bon émetteur
| Scénario | Émetteur recommandé | Type de challenge | Wildcard |
|---|---|---|---|
| — | — | — | — |
| Application web publique, domaine unique | `letsencrypt-prod` | HTTP-01 | Non |
| Application web publique, plusieurs sous-domaines | `letsencrypt-prod` | DNS-01 | Oui |
| Cluster isolé / privé | `CA` ou `Vault` | N/A (interne) | Oui |
| Entreprise avec exigences de conformité | `Venafi` | N/A | Oui |
| mTLS de service mesh (certificats de courte durée) | `Vault` ou `CA` | N/A (interne) | Oui |
| Développement / cluster local | `SelfSigned` ou `CA` | N/A | Oui |
Points clés à retenir
- Installez Cert-Manager avec Helm en utilisant
installCRDs=trueet validez toujours contre l’endpoint ACME de staging avant de passer en production. - Utilisez
ClusterIssuerpour les clusters multi-namespaces ; utilisezIssuerà portée de namespace uniquement lorsque vous avez besoin d’une isolation CA par équipe. - DNS-01 est strictement requis pour les certificats wildcard et pour les clusters non directement accessibles depuis internet sur le port 80.
- Le champ
renewBeforen’est pas optionnel en production — définissez-le à au moins un tiers dudurationtotal du certificat. - Lorsque l’émission est bloquée, le chemin de débogage est toujours :
Certificate→CertificateRequest→Order→Challenge→ logs du contrôleur. - Les identifiants API du fournisseur DNS référencés par un
ClusterIssuerdoivent résider dans le namespacecert-manager, pas dans les namespaces applicatifs. - Surveillez
certmanager_certificate_expiration_timestamp_secondsdans Prometheus et alertez dessus — les échecs de renouvellement silencieux sont le mode de défaillance le plus dangereux. - Sauvegardez vos manifestes
CertificateetClusterIssuerdans le cadre de votre plan de reprise après sinistre.
Questions fréquemment posées
Quelle est la différence entre un Issuer et un ClusterIssuer dans Cert-Manager ?
Un Issuer est à portée de namespace et ne peut émettre des certificats que dans le namespace où il est défini. Un ClusterIssuer est à l’échelle du cluster et peut être référencé par des ressources Certificate dans n’importe quel namespace. Pour la plupart des clusters en production, ClusterIssuer est le bon choix, sauf si vous avez besoin d’une isolation CA stricte au niveau du namespace.
Pourquoi mon certificat Cert-Manager est-il bloqué en état « Issuing » ?
Inspectez les objets Order et Challenge dans le même namespace en utilisant kubectl describe. Les causes les plus courantes sont : le port 80 bloqué par un pare-feu (HTTP-01), des identifiants API DNS incorrects ou un délai de propagation (DNS-01), les limites de débit de Let’s Encrypt dépassées, ou le pod webhook cert-manager non fonctionnel. Vérifiez toujours les logs du contrôleur avec kubectl logs -n cert-manager deploy/cert-manager.
Cert-Manager peut-il émettre des certificats wildcard depuis Let’s Encrypt ?
Oui, mais uniquement en utilisant le type de challenge DNS-01. HTTP-01 ne peut pas valider les domaines wildcard. Vous devez configurer une intégration de fournisseur DNS (Cloudflare, Route53, etc.) dans la configuration de votre solver ClusterIssuer et vous assurer que les identifiants API ont la permission de créer des enregistrements TXT sur le domaine cible.
Comment Cert-Manager gère-t-il automatiquement le renouvellement des certificats ?
Le contrôleur de Cert-Manager compare continuellement l’expiration de chaque objet Certificate avec l’heure actuelle. Lorsque la validité restante tombe en dessous du seuil renewBefore (par défaut : 30 jours), le contrôleur crée un nouveau CertificateRequest, complète le challenge ACME, et remplace atomiquement le contenu du Secret cible — le tout sans redémarrer les pods consommant le certificat. Les pods qui montent le Secret en tant que volume verront le certificat mis à jour au prochain cycle de synchronisation kubelet.
Cert-Manager est-il adapté pour sécuriser la communication interne service-à-service, pas seulement le HTTPS public ?
Oui. En utilisant l’émetteur CA ou l’émetteur HashiCorp Vault, Cert-Manager peut émettre des certificats de courte durée pour le mTLS interne entre microservices. C’est un modèle courant dans les déploiements de service mesh où chaque charge de travail a besoin d’un certificat d’identité unique. Les champs duration et renewBefore permettent aux certificats d’avoir une durée de vie aussi courte que quelques minutes, avec une rotation entièrement automatisée.
