## Introduction

Les certificats Kubernetes sécurisent chaque composant du plan de contrôle et des nœuds worker. Lorsque les certificats expirent ou sont mal configurés, le cluster peut devenir partiellement ou totalement indisponible. Cet article explique les concepts avancés de certificats avec des commandes concrètes, des sorties attendues et des étapes de récupération. Vous apprendrez à inspecter les certificats, approuver et signer des demandes de signature de certificat (CSR, Certificate Signing Request), configurer la rotation des certificats clients kubelet, mettre en place le TLS mutuel (mTLS) pour les charges de travail et dépanner les échecs courants. L'accent est mis sur la sécurité opérationnelle : observer avant de changer, limiter le rayon d'impact et vérifier chaque étape.

Ce guide s'adresse aux développeurs, ingénieurs DevOps et équipes techniques de startups exécutant Kubernetes en production ou s'y préparant. Vous devez avoir une familiarité de base avec kubectl et l'architecture du cluster. Tous les exemples utilisent Kubernetes v1.28 et OpenSSL 3.x, mais les concepts s'appliquent aux versions récentes.

## Inventaire de la version et de l'environnement

Avant de toucher aux certificats, rassemblez la version exacte du cluster, les emplacements des certificats et les dates d'expiration. Cet inventaire en lecture seule évite les modifications accidentelles et vous donne une base de référence pour la récupération.

Exécutez les commandes suivantes et enregistrez la sortie :

```bash
kubectl version --short
# Client Version: v1.28.2
# Server Version: v1.28.2
```

Listez tous les certificats utilisés par le plan de contrôle sur un cluster kubeadm (chemins par défaut) :

```bash
sudo ls -l /etc/kubernetes/pki/
# ca.crt, ca.key, apiserver.crt, apiserver.key, etc.
```

Vérifiez l'expiration du certificat du serveur API :

```bash
sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates
# notBefore=Jan  1 00:00:00 2024 GMT
# notAfter=Jan  1 00:00:00 2025 GMT
```

Pour les certificats clients kubelet sur un nœud worker, inspectez la configuration du kubelet :

```bash
sudo cat /var/lib/kubelet/config.yaml | grep clientCAFile
# clientCAFile: /etc/kubernetes/pki/ca.crt
```

Le certificat de service du kubelet est souvent auto-généré et stocké dans `/var/lib/kubelet/pki/`. Vérifiez son expiration et son sujet :

```bash
sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-server-current.pem -noout -subject -dates
# subject=O = system:nodes, CN = system:node:worker-1
# notBefore=... notAfter=...
```

Enregistrez les numéros de série et empreintes des certificats actuels pour comparaison ultérieure :

```bash
sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -serial -fingerprint -sha256
```

## Chemin de configuration sûr

Les modifications de certificats peuvent vous bloquer hors du cluster. Travaillez toujours d'abord sur un cluster de test, sauvegardez le répertoire PKI existant et suivez une approche de changement minimal.

### Sauvegarde des certificats

Sur chaque nœud du plan de contrôle, créez une sauvegarde horodatée de `/etc/kubernetes/pki/` :

```bash
sudo tar -czf /backup/kubernetes-pki-$(date +%Y%m%d%H%M%S).tar.gz -C /etc/kubernetes pki
```

Pour les certificats kubelet sur les workers, sauvegardez `/var/lib/kubelet/pki/` de manière similaire.

### Renouvellement d'un certificat du plan de contrôle avec kubeadm

Kubeadm fournit une commande de renouvellement sûre. D'abord, vérifiez quels certificats arrivent à expiration :

```bash
sudo kubeadm certs check-expiration
# [apiserver] Certificate will expire on 2025-01-01
# [apiserver-etcd-client] Certificate will expire on 2025-01-01
# etc.
```

Renouvelez tous les certificats à la fois (sur chaque nœud du plan de contrôle) :

```bash
sudo kubeadm certs renew all
```

Redémarrez les composants du plan de contrôle pour prendre en compte les nouveaux certificats :

```bash
sudo systemctl restart kubelet
# Attendez quelques secondes, puis vérifiez que le serveur API répond
kubectl get nodes
```

Si vous devez renouveler uniquement le certificat du serveur API :

```bash
sudo kubeadm certs renew apiserver
```

Après le renouvellement, vérifiez la nouvelle date d'expiration :

```bash
sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates
```

### Configuration de la rotation des certificats clients kubelet

Le kubelet peut demander automatiquement de nouveaux certificats clients à l'approche de leur expiration. Activez la rotation dans le fichier de configuration du kubelet `/var/lib/kubelet/config.yaml` :

```yaml
rotateCertificates: true
serverTLSBootstrap: true
```

Puis redémarrez le kubelet :

```bash
sudo systemctl restart kubelet
```

Pour approuver automatiquement la CSR en attente, vous pouvez configurer le gestionnaire de contrôleurs avec `--cluster-signing-duration=8760h` (1 an) et mettre en place un approbateur. Pour une approbation manuelle, voir la section suivante.

## Vérification et diagnostics

Après tout changement de certificat, vérifiez que tous les composants sont sains et que les certificats sont valides.

### Vérification de l'expiration des certificats dans le cluster

Utilisez `kubeadm certs check-expiration` sur les nœuds du plan de contrôle, et pour les certificats de service kubelet, inspectez-les sur chaque worker. Une approche plus automatisée consiste à utiliser un outil comme `kube-cert-manager` (obsolète) ou un système de surveillance avec un exportateur de certificats. Pour une vérification rapide de tous les certificats maîtres :

```bash
sudo kubeadm certs check-expiration
# Sortie attendue : liste des certificats avec dates d'expiration
```

### Vérification de la connectivité du serveur API

Depuis un poste de travail avec kubectl, exécutez :

```bash
kubectl get --raw='/healthz?verbose'
# [ok]etcd ok
# [ok]poststarthook/start-kube-apiserver-admission-initializer ok
# ...
```

Si le certificat du serveur API est invalide, vous pouvez voir `x509: certificate has expired or is not yet valid`. Vérifiez les journaux du serveur API :

```bash
sudo journalctl -u kube-apiserver -n 50 --no-pager | grep -i certificate
```

### Diagnostic des problèmes d'approbation de CSR

Lorsqu'un nœud ou un utilisateur demande un certificat, un objet CertificateSigningRequest est créé. Listez les CSR en attente :

```bash
kubectl get csr
# NAME        AGE   SIGNERNAME                     REQUESTOR          CONDITION
# node-csr-   10s   kubernetes.io/kube-apiserver-client-kubelet   system:node:worker-1   Pending
```

Inspectez les détails de la CSR :

```bash
kubectl describe csr node-csr-xxxx
# Events: ...
```

Approuvez la CSR après avoir vérifié le demandeur et l'utilisation :

```bash
kubectl certificate approve node-csr-xxxx
```

Si la CSR est refusée, vérifiez le nom du signataire et le demandeur. Les erreurs courantes incluent des permissions RBAC manquantes pour le jeton de bootstrap du nœud ou un nom de signataire incorrect.

## Modes de défaillance et récupération

Les certificats échouent silencieusement jusqu'à leur expiration. Voici des scénarios d'échec courants et les étapes de récupération exactes.

### Certificat du serveur API expiré

Symptômes : les commandes `kubectl` échouent avec `Unable to connect to the server: x509: certificate has expired`.

Récupération :

1. Sur un nœud du plan de contrôle, confirmez l'expiration :

```bash
sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates
```

2. Renouvelez le certificat :

```bash
sudo kubeadm certs renew apiserver
```

3. Redémarrez le kubelet pour déclencher le redémarrage du pod statique :

```bash
sudo systemctl restart kubelet
```

4. Vérifiez la connectivité :

```bash
kubectl get nodes
```

### Certificat client kubelet non renouvelé

Symptômes : les journaux du kubelet montrent `Failed to rotate client certificate` et peuvent cesser de publier le statut.

Vérifiez les paramètres de rotation :

```bash
sudo grep -E 'rotateCertificates|serverTLSBootstrap' /var/lib/kubelet/config.yaml
```

Si `rotateCertificates: false`, définissez-le sur `true`, redémarrez le kubelet, puis vérifiez la présence d'une nouvelle CSR :

```bash
kubectl get csr | grep node-csr
```

Approuvez la CSR manuellement si aucun approbateur automatique n'est configuré :

```bash
kubectl certificate approve <csr-name>
```

Vérifiez que le kubelet a un nouveau certificat client :

```bash
sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
```

### Échec de configuration mTLS pour une charge de travail

Si un pod ne parvient pas à se connecter à un service exigeant le mTLS, vérifiez les certificats montés dans le pod. Par exemple, une application attend `/etc/tls/tls.crt` et `/etc/tls/tls.key` :

```bash
kubectl exec -it <pod-name> -- ls -l /etc/tls/
# tls.crt, tls.key
kubectl exec -it <pod-name> -- openssl x509 -in /etc/tls/tls.crt -noout -subject -dates
```

Si le certificat est pour le mauvais nom d'hôte, la connexion échouera. Assurez-vous que les SAN du certificat incluent le nom DNS du service. Vous pouvez vérifier les SAN avec :

```bash
openssl x509 -in tls.crt -noout -ext subjectAltName
```

## Mise en œuvre du mTLS pour une charge de travail

Le TLS mutuel (mTLS) vérifie à la fois les identités du client et du serveur. Dans Kubernetes, cela implique souvent de créer une CA, d'émettre des certificats client et serveur, et de configurer l'application pour les présenter.

### Création d'une CA privée et émission de certificats avec OpenSSL

1. Générez une clé de CA et un certificat auto-signé :

```bash
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt -subj "/CN=my-ca"
```

2. Générez une clé de serveur et une demande de signature de certificat (CSR) avec des SAN pour le nom DNS du service :

```bash
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=my-service.default.svc" -config <(cat <<EOF
[req]
distinguished_name=dn
[dn]
[SAN]
subjectAltName=DNS:my-service.default.svc,DNS:my-service.default.svc.cluster.local
EOF
)
```

Remarque : la syntaxe exacte peut varier ; utilisez un fichier de configuration openssl approprié pour la production. Signez le certificat du serveur :

```bash
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256 -extensions SAN -extfile <(echo "subjectAltName=DNS:my-service.default.svc,DNS:my-service.default.svc.cluster.local")
```

3. Générez un certificat client de manière similaire, avec un CN représentant l'identité du client (par exemple, `my-client`).

### Stockage des certificats dans des Secrets Kubernetes

Créez un Secret contenant le certificat et la clé du serveur :

```bash
kubectl create secret tls my-service-tls --cert=server.crt --key=server.key
```

Pour le certificat de CA auquel les clients doivent faire confiance :

```bash
kubectl create secret generic my-ca --from-file=ca.crt
```

Montez le secret dans la spécification de votre pod :

```yaml
volumes:
- name: tls
  secret:
    secretName: my-service-tls
- name: ca
  secret:
    secretName: my-ca
containers:
- name: app
  volumeMounts:
  - name: tls
    mountPath: "/etc/tls"
    readOnly: true
  - name: ca
    mountPath: "/etc/ca"
    readOnly: true
```

Configurez votre application pour utiliser le certificat serveur et exiger des certificats clients signés par votre CA.

## Plongée dans l'API de demande de signature de certificat (CSR)

L'API CSR de Kubernetes permet aux utilisateurs et aux charges de travail de demander des certificats signés par la CA du cluster. Comprendre le flux aide au dépannage et à l'automatisation.

### Cycle de vie d'une CSR

1. Un client génère une clé et une CSR.
2. Le client soumet un objet `CertificateSigningRequest` à l'API Kubernetes.
3. Un administrateur ou un contrôleur approuve la CSR.
4. Le gestionnaire de contrôleurs signe la CSR en utilisant la CA configurée.
5. Le certificat signé est récupéré via le champ `status.certificate` de la CSR.

### Inspection d'un objet CSR

Obtenez toutes les CSR :

```bash
kubectl get csr
```

Affichez le YAML de la CSR :

```bash
kubectl get csr <name> -o yaml
```

Champs importants :
- `spec.request` : CSR encodée en base64.
- `spec.signerName` : par exemple, `kubernetes.io/kube-apiserver-client`.
- `spec.usages` : par exemple, `client auth`.
- `status.conditions` : affiche `Approved`, `Denied` ou `Failed`.

Approuvez ou refusez avec :

```bash
kubectl certificate approve <name>
kubectl certificate deny <name>
```

Pour récupérer le certificat signé :

```bash
kubectl get csr <name> -o jsonpath='{.status.certificate}' | base64 -d > client.crt
```

### Signataires CSR courants

- `kubernetes.io/kube-apiserver-client` : pour les certificats clients des utilisateurs.
- `kubernetes.io/kube-apiserver-client-kubelet` : pour les certificats clients kubelet.
- `kubernetes.io/kubelet-serving` : pour les certificats de service kubelet.

Assurez-vous que le gestionnaire de contrôleurs de votre cluster a les drapeaux de signataire appropriés :

```bash
--cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
--cluster-signing-key-file=/etc/kubernetes/pki/ca.key
```

## Stratégies de rotation des certificats

Au-delà de kubeadm, vous devrez peut-être planifier la rotation des certificats de la CA. La rotation de la CA du cluster est perturbatrice et nécessite une orchestration minutieuse.

### Rotation de la CA avec kubeadm (manuelle)

Kubeadm ne prend pas en charge la rotation automatique de la CA. Pour faire tourner la CA, vous devez :

1. Générer une nouvelle CA.
2. Réémettre tous les certificats des composants.
3. Distribuer la nouvelle CA à tous les nœuds.
4. Redémarrer tous les composants.

C'est une opération à haut risque. Testez toujours sur un cluster non productif et ayez un plan de retour en arrière. Certains outils comme `kubeadm certs renew` peuvent aider avec les certificats des composants, mais pas avec la CA elle-même.

### Rotation des certificats de service kubelet

Les certificats de service kubelet sont utilisés pour le point de terminaison HTTPS du kubelet (port 10250). Ils peuvent être renouvelés automatiquement si le kubelet est démarré avec `serverTLSBootstrap: true` et que les CSR sont approuvées. Le kubelet demande un nouveau certificat de service lorsque le certificat actuel approche de l'expiration.

Surveillez les CSR en attente pour garantir que la rotation a lieu :

```bash
kubectl get csr -o go-template='{{range .items}}{{.metadata.name}} {{.spec.signerName}} {{range .status.conditions}}{{.type}}={{.reason}}{{end}}{{"\n"}}{{end}}'
```

## Liste de contrôle opérationnelle

Utilisez cette liste pour assurer l'hygiène des certificats et la sécurité opérationnelle.

### Vérifications quotidiennes/hebdomadaires

- Exécutez `kubeadm certs check-expiration` sur tous les nœuds du plan de contrôle. Si un certificat expire dans les 30 jours, planifiez le renouvellement.
- Vérifiez les CSR en attente qui peuvent indiquer des problèmes de bootstrap de nœud : `kubectl get csr | grep Pending`.
- Vérifiez les certificats clients kubelet sur les nœuds worker : `sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates`.
- Surveillez les journaux du serveur API pour les erreurs de certificat : `sudo journalctl -u kube-apiserver --since "1 hour ago" | grep -i certificate`.

### Liste de contrôle avant renouvellement

- Sauvegardez le répertoire PKI.
- Documentez les numéros de série et empreintes des certificats actuels.
- Identifiez tous les composants affectés par le renouvellement.
- Planifiez une fenêtre de maintenance si un temps d'arrêt est prévu.

### Vérification après renouvellement

- Exécutez `kubectl get nodes` et `kubectl get pods -n kube-system` pour confirmer la santé du cluster.
- Vérifiez les dates des certificats avec `openssl x509 -noout -dates`.
- Vérifiez l'état de rotation du kubelet en cherchant de nouvelles CSR et les conditions approuvées.
- Testez l'accès externe au serveur API si vous utilisez un équilibreur de charge.

## Conclusion

Les certificats Kubernetes sont fondamentaux pour la sécurité et la disponibilité du cluster. En suivant les procédures d'inventaire, de configuration sûre, de vérification et de récupération de cet article, vous pouvez gérer les certificats en toute confiance. Observez toujours avant de changer, sauvegardez les fichiers critiques et vérifiez chaque étape avec des commandes concrètes. Commencez par des vérifications à faible risque comme la liste des dates d'expiration des certificats et la surveillance des CSR, puis passez à des renouvellements et rotations contrôlés. Une approche disciplinée de la gestion des certificats évite les pannes et maintient votre cluster sécurisé.