Introduction
Chaque cluster Kubernetes qui sert du trafic TLS finit par rencontrer un problème de certificat. Un pod ne peut pas prouver son identité, un kubelet ne peut pas rejoindre le cluster, ou un contrôleur personnalisé refuse de démarrer parce que son certificat de service est manquant. L'erreur pointe généralement vers une demande de signature de certificat (Certificate Signing Request, CSR) bloquée en Pending, refusée, ou qui n'a pas atteint le bon signataire.
Cet article explique l'architecture des demandes de signature de certificat Kubernetes du point de vue d'un opérateur. Vous apprendrez comment une CSR passe d'une clé privée à un certificat signé, quels composants sont impliqués, comment approuver ou refuser les demandes en toute sécurité, et comment diagnostiquer les échecs sans deviner. Tous les exemples utilisent kubectl et conviennent d'abord à un cluster de développement ou de test. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de vrais secrets lorsque c'est possible, vérifier le résultat, et savoir comment récupérer si l'état attendu n'est pas atteint.
Les CSR Kubernetes sont utiles pour les développeurs, les consultants DevOps et les équipes techniques de startups qui gèrent leurs propres clusters ou construisent des contrôleurs d'admission personnalisés. À la fin de cet article, vous serez en mesure de créer une CSR, de l'inspecter, de l'approuver et de résoudre les modes de défaillance courants avec confiance.
Inventaire de la version et de l'environnement
Avant de toucher à une CSR, vous devez connaître votre version de Kubernetes, le signataire de certificat que vous prévoyez d'utiliser, et la portée du namespace ou du cluster où la demande vivra. Les CSR sont des ressources à portée de cluster ; elles ne sont pas liées à un namespace. La version de l'API pour les CSR a changé au fil du temps, donc un manifeste qui fonctionne sur Kubernetes 1.19 peut ne pas fonctionner sur 1.29 sans ajustement.
Commencez par un inventaire en lecture seule :
kubectl version --short
kubectl get csr
kubectl get nodes -o wide
La première commande affiche les versions du client et du serveur. La deuxième montre les CSR existantes et leur statut. La troisième montre les certificats du kubelet et les états des nœuds ; si un nœud est NotReady parce que son certificat client kubelet a expiré, c'est un problème lié aux CSR.
Prérequis pour créer et approuver des CSR :
- Un cluster Kubernetes en cours d'exécution où vous avez la permission de créer des objets CertificateSigningRequest
certificates.k8s.io/v1. Par défaut,system:node-bootstrapperpeut créer des CSR pour les certificats clients de nœud, mais d'autres utilisateurs peuvent avoir besoin de RBAC. openssloucfsslinstallé localement pour générer une clé privée et une demande de certificat.- Un signataire auquel le cluster fait confiance. Kubernetes a des signataires intégrés :
kubernetes.io/kube-apiserver-client,kubernetes.io/kube-apiserver-client-kubelet,kubernetes.io/kubelet-servingetkubernetes.io/legacy-unknown. Le nom du signataire est critique : si vous demandez un signataire que le gestionnaire de contrôleurs ne reconnaît pas, la CSR resteraPendingpour toujours.
Observation avant intervention :
kubectl get csr -o custom-columns=NAME:.metadata.name,AGE:.metadata.creationTimestamp,SIGNER:.spec.signerName,REQUESTOR:.spec.username,CONDITION:.status.conditions[0].type
Cette commande avec colonnes personnalisées évite de vider le YAML complet lorsque vous n'avez besoin que des champs clés. Cherchez la colonne CONDITION ; une CSR saine peut être Approved ou Issued, mais Pending signifie qu'aucun contrôleur n'a encore agi.
Exemple : Dans un cluster exécutant Kubernetes 1.27, la commande suivante crée et affiche une CSR :
openssl genrsa -out myuser.key 2048
openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser/O=dev-team"
cat myuser.csr | base64 | tr -d '\n' > myuser.csr.b64
Ensuite, créez le manifeste de CSR myuser-csr.yaml :
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: myuser
spec:
request: <BASE64_ENCODED_CSR>
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
Remplacez <BASE64_ENCODED_CSR> par le contenu de myuser.csr.b64. Appliquez-le :
kubectl apply -f myuser-csr.yaml
kubectl get csr myuser
Sortie attendue :
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
myuser 5s kubernetes.io/kube-apiserver-client admin <none> Pending
Le demandeur est admin parce que nous avons utilisé les identifiants de cluster-admin. Dans un scénario réel d'amorçage, le demandeur serait system:node:node-name ou system:serviceaccount:....
Gardez le test local petit : avant de créer une CSR pour un service de production, testez le flux de travail avec un utilisateur factice ou un seul nœud dans un cluster de développement. Utilisez kubectl apply --dry-run=client -f myuser-csr.yaml pour valider le manifeste sans le persister.
Chemin de configuration sûr
Le chemin de configuration sûr pour les CSR signifie :
- Générez une clé privée localement et protégez-la. Ne stockez pas la clé privée dans l'objet CSR ; la CSR ne contient que la clé publique et l'identité demandée.
- Utilisez le bon
signerNameet les bonsusagespour votre cas d'utilisation. Pour un certificat client pour un utilisateur ou un compte de service, utilisezkubernetes.io/kube-apiserver-clientavec l'usageclient auth. Pour un certificat client kubelet, utilisezkubernetes.io/kube-apiserver-client-kubelet. Pour un certificat de service pour un pod ou un service, utilisezkubernetes.io/kubelet-servingavec l'usageserver auth. Les signataires mal configurés sont la cause la plus courante de CSR bloquées. - N'approuvez les CSR qu'après avoir vérifié l'identité de la demande et le contenu de la CSR. Utilisez
kubectl get csr <name> -o yamlet vérifiezspec.username,spec.groupsetspec.request(la CSR décodée en base64) par rapport à vos enregistrements. - Définissez une durée d'expiration si votre cluster le prend en charge (Kubernetes 1.22+). Vous pouvez spécifier
spec.expirationSecondspour limiter la durée de vie du certificat. C'est important pour la sécurité ; un certificat qui n'expire jamais est un passif.
Flux de travail d'approbation sûr :
# Décoder et inspecter le sujet et la clé publique de la CSR
kubectl get csr myuser -o jsonpath='{.spec.request}' | base64 -d | openssl req -noout -text
# Approuver la CSR
kubectl certificate approve myuser
# Vérifier le statut
kubectl get csr myuser
kubectl get csr myuser -o jsonpath='{.status.certificate}' | base64 -d | openssl x509 -noout -text
Sortie attendue après approbation :
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
myuser 10s kubernetes.io/kube-apiserver-client admin <none> Approved,Issued
La condition Issued signifie que le certificat a été signé et stocké dans status.certificate. Vous pouvez ensuite l'extraire et l'utiliser pour l'authentification.
Refuser en toute sécurité : Si vous voyez une CSR inattendue, refusez-la avec kubectl certificate deny <name>. Cela ajoute une condition Denied et empêche l'émission du certificat. Par exemple, si vous voyez une CSR d'un utilisateur inconnu ou avec un sujet suspect, refusez-la immédiatement et enquêtez. Vous pouvez ensuite supprimer la CSR avec kubectl delete csr <name>.
Approbation automatisée : Pour les grands clusters, vous pouvez écrire un contrôleur qui surveille les CSR et les approuve en fonction de règles. La documentation Kubernetes fournit un exemple utilisant un ClusterRole et un ClusterRoleBinding pour permettre à un compte de service d'approuver les CSR. Limitez toujours les permissions au minimum nécessaire : un contrôleur qui approuve n'importe quelle CSR est dangereux.
Exemple YAML pour approuver les CSR avec RBAC :
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests"]
verbs: ["get", "list", "watch"]
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/approval"]
verbs: ["update"]
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/status"]
verbs: ["patch"]
Ce rôle permet au compte de service lié d'approuver les CSR mais pas de les créer ni de les supprimer. Utilisez ce modèle pour les contrôleurs d'amorçage.
Vérification et diagnostics
Après l'approbation d'une CSR, vous devez vérifier que le certificat fonctionne pour l'usage prévu. La vérification dépend du cas d'utilisation :
- Certificat client utilisateur : Configurez
kubectlavec le certificat signé et la clé, et testez l'accès :
kubectl config set-credentials myuser --client-certificate=myuser.crt --client-key=myuser.key --embed-certs=true
kubectl config set-context myuser-context --cluster=my-cluster --user=myuser
kubectl --context=myuser-context get pods
Si les permissions RBAC sont correctes, vous devriez voir la liste des pods. Si vous voyez Error from server (Forbidden), vérifiez les rôles liés à l'utilisateur et les usages dans la CSR.
- Certificat client kubelet : Après avoir approuvé la CSR d'un nœud, le kubelet devrait automatiquement renouveler son certificat client et devenir
Ready. Vérifiez avec :
kubectl get nodes
kubectl describe node <node-name>
Cherchez la condition KubeletReady. Si le nœud reste NotReady, inspectez les journaux du kubelet pour les erreurs de certificat.
- Certificat de service pour un pod : Si vous utilisez une CSR pour obtenir un certificat de service pour un webhook ou un point de terminaison de métriques, vous devez monter le certificat signé dans le pod et configurer le serveur pour l'utiliser. Utilisez un
Secretpour stocker le certificat et la clé, et montez-le comme volume.
Diagnostics pour les CSR bloquées :
Si une CSR reste Pending pendant plus de quelques minutes, vérifiez :
kubectl get csr <name> -o yamlet cherchezstatus.conditionsavec un messagePending. Le message indique souvent qu'aucun signataire n'est configuré.kubectl get clusterrolebinding system:node-bootstrapperpour vous assurer que le rôle d'amorçage existe.kubectl -n kube-system logs kube-controller-manager-<control-plane-node>et cherchezcsroucertificate. Le journal du gestionnaire de contrôleurs peut afficher une erreur commeno signer found for signerName.- Si le signataire est personnalisé, assurez-vous que le contrôleur qui implémente le signataire est en cours d'exécution et dispose du RBAC nécessaire.
- Vérifiez
spec.signerNamepar rapport à la liste des signataires connus. Les fautes de frappe sont courantes, par exemplekubernetes.io/kube-apiserver-client-kubeletvskubernetes.io/kube-apiserver-client-kubelet. Copiez-collez le nom exact de la documentation.
Messages d'erreur courants et leur signification :
the CSR is Pending— Aucun contrôleur ne l'a approuvée ; soit vous devez approuver manuellement, soit le mécanisme d'approbation automatique est cassé.failed to find signer— LesignerNamen'est pas enregistré ; vérifiez l'orthographe et la configuration du gestionnaire de contrôleurs.certificate request is not allowed— Le signataire ne permet pas les usages demandés ou le sujet est invalide.x509: certificate signed by unknown authority— Le client ne fait pas confiance à l'autorité de certification qui a signé le certificat ; assurez-vous d'utiliser le bon bundle CA.
Vérifier le contenu du certificat :
kubectl get csr myuser -o jsonpath='{.status.certificate}' | base64 -d | openssl x509 -noout -subject -issuer -dates
Cela affiche le sujet, l'émetteur et la période de validité. Comparez le sujet avec la demande CSR ; il doit correspondre aux champs CN et O.
Modes de défaillance et récupération
Même avec une configuration soignée, les flux de travail CSR peuvent échouer. Voici les modes de défaillance les plus courants et les étapes de récupération.
Défaillance 1 : CSR refusée par erreur
Si vous refusez accidentellement une CSR, vous ne pouvez pas l'annuler. Vous devez créer une nouvelle CSR avec la même clé privée et la soumettre à nouveau. La clé privée est toujours valide ; vous avez juste besoin d'une nouvelle demande CSR.
Récupération :
# Générer une nouvelle CSR à partir de la clé privée existante
openssl req -new -key myuser.key -out myuser-new.csr -subj "/CN=myuser/O=dev-team"
# Encoder et créer un nouvel objet CSR avec un nom différent
kubectl apply -f myuser-new-csr.yaml
kubectl certificate approve myuser-new
Défaillance 2 : Certificat expiré
Si un certificat a expiré, la CSR affichera toujours Issued mais le certificat dans status.certificate est expiré. Vous devez créer une nouvelle CSR et l'approuver avant que l'ancien certificat n'expire. Pour les certificats clients kubelet, le kubelet les renouvelle automatiquement si l'approbateur CSR fonctionne. Pour les certificats utilisateur, vous devez renouveler manuellement.
Vérifiez l'expiration :
kubectl get csr myuser -o jsonpath='{.status.certificate}' | base64 -d | openssl x509 -noout -enddate
Défaillance 3 : Clé privée perdue
Si vous perdez la clé privée, le certificat signé est inutile. Vous devez générer une nouvelle paire de clés et soumettre une nouvelle CSR. Pour les certificats kubelet, cela peut signifier rejoindre le nœud au cluster. Pour les certificats utilisateur, révoquez l'ancien certificat si possible et émettez-en un nouveau.
Défaillance 4 : CSR jamais émise à cause d'usages manquants
Certains signataires exigent des usages spécifiques. Par exemple, le signataire kubernetes.io/kube-apiserver-client peut exiger l'usage client auth. Si vous l'omettez, la CSR peut être approuvée mais le certificat n'est pas émis. Ajoutez les bons usages et soumettez à nouveau.
Défaillance 5 : Gestionnaire de contrôleurs en panne
Si le gestionnaire de contrôleurs n'est pas en cours d'exécution, aucune CSR ne peut être approuvée ou signée. Vérifiez le statut du pod du gestionnaire de contrôleurs :
kubectl -n kube-system get pods -l component=kube-controller-manager
kubectl -n kube-system logs <controller-manager-pod> | grep -i csr
Si le gestionnaire de contrôleurs est en panne, redémarrez-le. Sur les clusters gérés, contactez votre fournisseur. Sur les clusters auto-gérés, assurez-vous que le manifeste du pod statique est correct et que le kubelet fonctionne.
Meilleures pratiques de récupération :
- Gardez toujours une copie de la clé privée dans un endroit sécurisé (par exemple, un gestionnaire de secrets). Ne la stockez pas dans le cluster.
- Définissez
spec.expirationSecondsà une valeur raisonnable (par exemple, 8760h pour un an) pour éviter les certificats indéfinis. - Utilisez la surveillance et les alertes pour détecter les CSR qui sont
Pendingdepuis plus de quelques minutes. Vous pouvez écrire un script simple ou une alerte Prometheus pour surveiller les métriqueskube_certificatesigningrequest_createdetkube_certificatesigningrequest_condition. - Documentez votre flux de travail d'approbation et assurez-vous que seuls les utilisateurs autorisés peuvent approuver les CSR. Utilisez RBAC pour limiter
certificatesigningrequests/approvalà un petit groupe.
Liste de contrôle des opérations
Utilisez cette liste de contrôle pour chaque tâche liée aux CSR.
Avant de créer une CSR :
- [ ] Confirmez la version de Kubernetes et le groupe d'API :
kubectl api-versions | grep certificates. - [ ] Identifiez le nom du signataire pour votre cas d'utilisation. Vérifiez
kubectl get clusterrolebindinget les drapeaux du gestionnaire de contrôleurs pour les signataires existants. - [ ] Générez une clé privée forte (RSA 2048 ou ECDSA P-256) et stockez-la en toute sécurité.
- [ ] Préparez la CSR avec le bon sujet (CN, O) et les usages.
- [ ] Validez le manifeste avec
kubectl apply --dry-run=client.
Après avoir créé une CSR :
- [ ] Vérifiez le statut :
kubectl get csr <name>; il devrait êtrePending. - [ ] Inspectez la demande CSR : décodez et vérifiez le sujet et la clé publique.
- [ ] N'approuvez que si la demande correspond à une identité attendue.
- [ ] Observez le changement de statut vers
Approved,Issued. - [ ] Extrayez le certificat et vérifiez sa validité avec
openssl x509.
Lors du renouvellement :
- [ ] Vérifiez l'expiration du certificat actuel.
- [ ] Générez une nouvelle CSR avec la même ou une nouvelle clé.
- [ ] Soumettez et approuvez.
- [ ] Mettez à jour tous les endroits qui utilisent le certificat (kubeconfig, maillage de services, ingress).
- [ ] Testez l'accès avant de supprimer l'ancien certificat.
En cas d'échec :
- [ ] Collectez les journaux : gestionnaire de contrôleurs, kubelet, serveur API.
- [ ] Vérifiez les problèmes RBAC :
kubectl auth can-i create certificatesigningrequests. - [ ] Examinez la configuration du signataire et les usages.
- [ ] En cas de refus, créez une nouvelle CSR et documentez pourquoi le refus est survenu.
- [ ] Si le cluster est dans un mauvais état, envisagez de mettre le nœud en maintenance ou de réduire le service jusqu'à ce que le certificat soit corrigé.
Exemple de script pour surveiller les CSR en attente :
#!/bin/bash
# Alerte si une CSR est en attente depuis plus de 10 minutes
PENDING=$(kubectl get csr -o json | jq '[.items[] | select(.status.conditions[]?.type=="Pending")] | length')
if [ "$PENDING" -gt 0 ]; then
echo "Avertissement : $PENDING CSR en attente"
kubectl get csr
fi
Exécutez ce script périodiquement via cron ou un CronJob Kubernetes pour détecter les CSR bloquées tôt.
Conclusion
L'architecture des demandes de signature de certificat Kubernetes n'est pas seulement une fonctionnalité ; c'est un flux de travail qui touche à la sécurité, à l'automatisation et aux opérations. Lorsque vous comprenez comment une CSR passe d'une clé privée à un certificat signé, vous pouvez résoudre les échecs rapidement et éviter les failles de sécurité.
En suivant l'inventaire de la version et de l'environnement, le chemin de configuration sûr, la vérification et les diagnostics, les modes de défaillance et la récupération, et la liste de contrôle des opérations, vous créez un processus reproductible. Chaque étape est observable, réversible lorsque c'est possible, et limitée en rayon d'impact.
Comme prochaine étape, choisissez une vérification à faible risque dans votre propre cluster. Créez une CSR de test pour un utilisateur factice, approuvez-la, extrayez le certificat et utilisez-la pour accéder au cluster. Ensuite, testez un refus et une récupération. Enregistrez vos constatations et mettez à jour le runbook de votre équipe.
Un flux de travail technique fiable rend les échecs visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision. Avec ce guide, vous avez les commandes et les exemples pour gérer les CSR Kubernetes avec confiance.