## Introduction Les comptes de service Kubernetes sont les identités que les pods utilisent pour s'authentifier auprès de l'API Kubernetes et des services externes. À mesure que les clusters grandissent et que les exigences de sécurité mûrissent, les administrateurs sont souvent confrontés à des mises à niveau, comme le passage de jetons statiques à longue durée de vie à des jetons projetés à durée limitée, ou la migration de charges de travail vers de nouveaux comptes de service avec des liaisons RBAC plus propres. Ces tâches peuvent perturber les applications si elles sont effectuées sans plan clair. Ce guide parcourt tout le cycle de vie : de l'inventaire initial de la version et de l'environnement jusqu'aux changements de configuration sécurisés, à la vérification, à la récupération en cas d'échec et à une liste de contrôle opérationnelle. Il est rédigé pour les développeurs, les consultants DevOps et les équipes techniques de startups qui ont besoin de procédures pratiques axées sur les commandes. Bien que les exemples se concentrent sur les comptes de service, les concepts touchent également au RBAC et aux Secrets car ils sont étroitement liés à l'identité et à l'accès. L'objectif est la sécurité opérationnelle : observer avant de changer, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier le résultat et documenter comment récupérer si l'état attendu n'est pas atteint. Chaque section comprend des commandes concrètes et les sorties attendues pour que vous puissiez suivre en toute confiance. ## Inventaire de la version et de l'environnement Avant de toucher à un compte de service, sachez exactement ce que vous avez. Un inventaire complet comprend la version de Kubernetes, les indicateurs du serveur d'API, les comptes de service existants, leurs types de jetons et les liaisons RBAC. Cela évite les surprises comme faire un changement incompatible avec une ancienne version de l'API. Commencez par vérifier la version du cluster : ```bash kubectl version --short ``` Sortie attendue (exemple) : ``` Client Version: v1.28.2 Server Version: v1.27.6 ``` Si votre cluster est en version 1.24 ou ultérieure, les jetons de compte de service projetés (la fonctionnalité `BoundServiceAccountTokenVolume`) sont stables et devraient être votre valeur par défaut. Pour les versions antérieures, vous pouvez encore dépendre de jetons statiques hérités. Connaître cette différence est essentiel pour une mise à niveau. Listez les comptes de service existants dans tous les espaces de noms : ```bash kubectl get serviceaccounts --all-namespaces ``` Recherchez les comptes qui existent depuis longtemps, en particulier dans `kube-system` ou les espaces de noms personnalisés. Inspectez ensuite un compte de service spécifique pour voir ses secrets et les jetons associés : ```bash kubectl get serviceaccount my-app-sa -n my-namespace -o yaml ``` Dans la sortie, notez le champ `secrets`. S'il liste plusieurs secrets, ce sont probablement des secrets de jetons hérités. Dans les clusters plus récents, ce champ est souvent vide car les jetons sont projetés et ne sont pas stockés comme secrets. Pour déterminer si le compte de service peut émettre des jetons à courte durée de vie via l'API TokenRequest, exécutez : ```bash kubectl create token my-app-sa -n my-namespace ``` Cette commande demande un jeton frais à durée limitée et l'imprime sur la sortie standard. Vous pouvez décoder le JWT (par exemple, en utilisant `jq -R 'split(".") | .[1] | @base64d | fromjson'`) pour inspecter la revendication `exp` et confirmer qu'il expire. Les jetons statiques hérités ne sont pas créés de cette façon ; ils sont stockés comme Secrets et n'expirent jamais. Si vous trouvez des Secrets de jetons hérités dans le champ `secrets` du compte de service, planifiez une migration vers des jetons à courte durée de vie. Enfin, examinez les liaisons RBAC pour le compte de service : ```bash kubectl get rolebindings,clusterrolebindings --all-namespaces -o json | jq '.items[] | select(.subjects[]?.name == "my-app-sa")' ``` Cela montre tous les rôles et rôles de cluster attribués au compte. Documentez les autorisations, car vous devrez les reproduire en toute sécurité après la migration. Liste de contrôle rapide d'inventaire de l'environnement : - Version du serveur Kubernetes : `kubectl version --short` - Paramètres de jeton du serveur d'API : vérifiez les arguments du pod `kube-apiserver` pour `--service-account-issuer`, `--service-account-key-file` et `--service-account-signing-key-file` - Lister tous les comptes de service et leurs espaces de noms - Identifier les secrets de jetons hérités - Cartographier les liaisons RBAC pour chaque compte de service utilisé ## Chemin de configuration sécurisé Une fois que vous comprenez votre état actuel, vous pouvez planifier une mise à niveau sécurisée. Le chemin le plus sûr est de créer de nouveaux comptes de service à jetons projetés à côté des anciens, de basculer les charges de travail progressivement et de supprimer les jetons hérités seulement après vérification. Cela limite le rayon d'impact et vous donne un point de retour en arrière clair. ### Étape 1 : Activer les jetons projetés (si ce n'est pas déjà fait) Pour les clusters v1.21+, la fonctionnalité est activée par défaut. Vérifiez en examinant la spécification du pod `kube-apiserver` : ```bash kubectl get pod -n kube-system -l component=kube-apiserver -o yaml | grep -E 'service-account-(issuer|key-file|signing-key-file)' ``` Vous devriez voir des valeurs pour `--service-account-issuer`, `--service-account-key-file` et `--service-account-signing-key-file`. Si elles manquent, vous devez les ajouter à la configuration du serveur d'API et le redémarrer. Pour les clusters gérés (EKS, GKE, AKS), cela est géré par le fournisseur. ### Étape 2 : Créer un nouveau compte de service Supposons que votre compte de service hérité s'appelle `legacy-app-sa`. Créez-en un nouveau avec un nom clair : ```yaml apiVersion: v1 kind: ServiceAccount metadata: name: new-app-sa namespace: my-namespace ``` Appliquez-le : ```bash kubectl apply -f new-sa.yaml ``` À ce stade, le nouveau compte de service n'a aucun secret supplémentaire ni liaison RBAC. Il est inoffensif. ### Étape 3 : Attribuer les mêmes autorisations RBAC Si `legacy-app-sa` avait un RoleBinding vers un rôle nommé `app-role`, créez une liaison équivalente pour `new-app-sa` : ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: new-app-sa-binding namespace: my-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: app-role subjects: - kind: ServiceAccount name: new-app-sa namespace: my-namespace ``` Appliquez et vérifiez : ```bash kubectl apply -f new-binding.yaml kubectl auth can-i list pods --as=system:serviceaccount:my-namespace:new-app-sa -n my-namespace ``` La dernière commande devrait retourner `yes` si le rôle accorde la permission. ### Étape 4 : Basculer une charge de travail de test Modifiez un déploiement pour utiliser le nouveau compte de service : ```yaml spec: template: spec: serviceAccountName: new-app-sa automountServiceAccountToken: true ``` Appliquez le changement et surveillez le déploiement : ```bash kubectl apply -f deployment.yaml kubectl rollout status deployment/my-app -n my-namespace ``` Sortie attendue : ``` Waiting for deployment "my-app" rollout to finish: 1 old replicas are pending termination... deployment "my-app" successfully rolled out ``` Inspectez maintenant le pod pour confirmer qu'il a un jeton projeté : ```bash kubectl get pod -n my-namespace -l app=my-app -o jsonpath='{.spec.volumes[?(@.projected.sources[0].serviceAccountToken)].projected.sources[0].serviceAccountToken.expirationSeconds}' ``` Si la valeur est `3600` (ou n'importe quel nombre), le jeton est projeté et expirera après ce nombre de secondes. ### Étape 5 : Supprimer les jetons hérités Après que toutes les charges de travail sont migrées, supprimez les secrets de jetons hérités de l'ancien compte de service. D'abord, supprimez les références de secrets de l'ancien compte de service (ou supprimez simplement l'ancien compte de service s'il n'est plus nécessaire) : ```bash kubectl delete serviceaccount legacy-app-sa -n my-namespace ``` Mais avant de supprimer, assurez-vous qu'aucun pod ne l'utilise : ```bash kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.serviceAccountName == "legacy-app-sa")' ``` Si vide, la suppression est sûre. Sinon, mettez à jour ces charges de travail d'abord. Une note sur le retour en arrière : pour revenir en arrière sur un seul déploiement, changez simplement `serviceAccountName` en `legacy-app-sa` et appliquez à nouveau. Si vous n'avez pas encore supprimé l'ancien compte de service, cela fonctionne immédiatement. C'est pourquoi nous migrons progressivement au lieu de tout supprimer d'un coup. ## Vérification et diagnostics Après avoir effectué des changements, vérifiez toujours que le nouveau compte de service fonctionne comme prévu et qu'aucun problème persistant n'existe. Les diagnostics doivent couvrir la présence du jeton, l'expiration du jeton, l'accès à l'API et le comportement de l'application. ### Vérifier la disponibilité du jeton projeté Dans un pod utilisant le nouveau compte de service, le jeton est disponible à `/var/run/secrets/kubernetes.io/serviceaccount/token`. Exécutez une commande dans le pod et affichez son expiration : ```bash kubectl exec -it my-app-pod -n my-namespace -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ``` Cela imprime le JWT. Décodez-le (avec un outil comme `jq` ou un décodeur en ligne) pour voir la revendication `exp`. Alternativement, utilisez `kubectl` pour décrire le pod et cherchez le volume monté : ```bash kubectl describe pod my-app-pod -n my-namespace ``` Cherchez un volume `projected` avec une source `serviceAccountToken`. Le champ `Expiration` doit être défini. ### Valider l'accès à l'API Utilisez `kubectl auth can-i` pour tester les autorisations : ```bash kubectl auth can-i get pods --as=system:serviceaccount:my-namespace:new-app-sa -n my-namespace ``` Si la sortie est `yes`, le compte de service a la permission nécessaire. Si `no`, examinez la liaison RBAC. ### Surveiller les journaux de l'application Vérifiez si votre application journalise des erreurs d'authentification : ```bash kubectl logs my-app-pod -n my-namespace --tail=50 ``` Cherchez des messages comme `forbidden`, `token expired` ou `unauthorized`. Si le jeton expire et que l'application ne le recharge pas, vous verrez des échecs après la période d'expiration (1 heure par défaut). Pour tester, vous pouvez temporairement définir une expiration très courte dans la spécification du pod (par exemple, `expirationSeconds: 60`) et observer le comportement de l'application. Si elle échoue, ajoutez une logique pour recharger le jeton. ### Diagnostiquer les problèmes de jeton Si un pod ne démarre pas avec le nouveau compte de service, vérifiez les événements : ```bash kubectl get events -n my-namespace --sort-by=.lastTimestamp ``` Cherchez des messages comme `MountVolume.SetUp failed for volume "kube-api-access-xyz" : failed to fetch token: serviceaccount "new-app-sa" not found`. Cela indiquerait une faute de frappe dans le nom du compte de service. Problème courant : le compte de service existe mais le pod ne peut pas monter le jeton parce que `automountServiceAccountToken` est défini sur `false` au niveau du compte de service. Vérifiez : ```bash kubectl get serviceaccount new-app-sa -n my-namespace -o yaml | grep automountServiceAccountToken ``` Si cela dit `false`, soit définissez-le sur `true`, soit définissez explicitement `automountServiceAccountToken: true` dans la spécification du pod. ## Modes de défaillance et récupération Même avec une planification minutieuse, les choses peuvent mal tourner. Voici les modes de défaillance courants lors des mises à niveau des comptes de service et comment s'en remettre. ### Défaillance 1 : L'application casse après le changement de compte de service **Symptômes :** Les pods redémarrent avec des erreurs, les journaux de l'application montrent `forbidden` ou `unable to authenticate`. **Cause :** Les autorisations RBAC ne sont pas correctement attribuées au nouveau compte de service, ou l'application essaie d'accéder à une ressource qui était autorisée avant mais est maintenant refusée. **Récupération :** 1. Vérifiez les autorisations : `kubectl auth can-i --list --as=system:serviceaccount:my-namespace:new-app-sa -n my-namespace` 2. Comparez avec les autorisations de l'ancien compte de service : `kubectl auth can-i --list --as=system:serviceaccount:my-namespace:legacy-app-sa -n my-namespace` 3. Corrigez les RoleBindings manquants et appliquez. 4. Si un retour en arrière immédiat est nécessaire, changez le déploiement en `legacy-app-sa`. Cela devrait prendre effet lors d'un redéploiement. ### Défaillance 2 : Le jeton du compte de service expire dans un pod longue durée **Symptômes :** Après environ 1 heure (durée de vie du jeton par défaut), l'application commence à recevoir des erreurs 401 lors des appels à l'API. **Cause :** L'application met en cache le jeton et ne le recharge pas. Les jetons projetés expirent ; les jetons hérités ne le faisaient pas. **Récupération :** - Mettez à jour l'application pour surveiller le fichier de jeton et recharger lors d'un changement, ou utilisez une bibliothèque cliente qui gère la rotation automatiquement (par exemple, les clients Kubernetes officiels). - Comme mesure temporaire, vous pouvez prolonger l'expiration du jeton en définissant `expirationSeconds` dans la spécification du pod à une valeur plus grande (jusqu'à 604800 secondes, 7 jours). Mais corrigez la cause racine. - Retour en arrière : repassez au compte de service hérité si disponible, mais notez que ce n'est pas une solution à long terme. ### Défaillance 3 : Compte de service introuvable **Symptômes :** Le pod ne démarre pas avec `MountVolume.SetUp failed`. **Cause :** Faute de frappe dans `serviceAccountName` ou le compte de service a été supprimé prématurément. **Récupération :** - Corrigez le nom ou recréez le compte de service et ses liaisons. - Si l'ancien compte de service a été supprimé et que vous devez le restaurer à partir d'une sauvegarde, utilisez `kubectl apply` à partir de vos manifestes sauvegardés ou recréez manuellement. ### Défaillance 4 : Le jeton hérité fonctionne toujours mais vous ne pouvez pas le supprimer **Symptômes :** Vous essayez de supprimer un secret de jeton hérité, mais il est immédiatement recréé par le contrôleur de compte de service. **Cause :** Le compte de service référence toujours le secret dans son champ `secrets`. Le contrôleur le rajoute. **Récupération :** - Supprimez la référence au secret du compte de service d'abord : ```bash kubectl patch serviceaccount my-sa -n my-namespace -p '{"secrets": []}' ``` - Puis supprimez le secret : ```bash kubectl delete secret my-sa-token-abcde -n my-namespace ``` ### Défaillance 5 : Le cluster géré ne permet pas de changer l'émetteur du compte de service **Symptômes :** Dans Kubernetes géré (EKS, GKE, AKS), essayer de personnaliser l'émetteur entraîne une erreur. **Cause :** Le fournisseur cloud gère le serveur d'API et n'expose pas ces indicateurs. **Récupération :** - Utilisez l'émetteur par défaut et la configuration de jeton du cluster géré. Vous pouvez toujours migrer vers des jetons projetés si pris en charge. - Pour des besoins spécialisés, envisagez d'utiliser un secret de jeton de compte de service séparé (toujours hérité) ou utilisez un fournisseur d'identité externe avec la fédération d'identité de charge de travail. Étapes de récupération générales : 1. Gardez une sauvegarde de tous les comptes de service et liaisons RBAC : `kubectl get serviceaccounts,roles,rolebindings,clusterroles,clusterrolebindings --all-namespaces -o yaml > backup.yaml` 2. Restaurez à partir de la sauvegarde : `kubectl apply -f backup.yaml` 3. Testez la procédure de retour en arrière dans un environnement de préproduction avant la production. ## Liste de contrôle opérationnelle Utilisez cette liste de contrôle pour assurer une mise à niveau et une migration des comptes de service en douceur. Attribuez un seul responsable pour chaque décision majeure et révisez périodiquement. - **Inventaire :** Responsable : Ingénieur plateforme (par exemple, Priya Shah). Fréquence : Avant tout changement et trimestriellement. Vérifier la version de Kubernetes, lister les comptes de service, trouver les jetons hérités, cartographier le RBAC. - **Activer les jetons projetés :** Responsable : Administrateur de cluster (par exemple, Marcus Lee). Fréquence : Une fois lors de la mise à niveau. Confirmer les indicateurs du serveur d'API, si absents coordonner avec le fournisseur. - **Créer de nouveaux comptes de service :** Responsable : Chef d'équipe applicative (par exemple, Ana Rodriguez). Fréquence : Par migration. Pour chaque compte de service hérité, créer un nouveau compte de service avec une convention de nommage claire. - **Attribuer le RBAC :** Responsable : Ingénieur sécurité (par exemple, Tom Chen). Fréquence : Par migration. Répliquer les autorisations en utilisant le moindre privilège. Réviser avec `kubectl auth can-i --list`. - **Tester la migration :** Responsable : Chef QA (par exemple, Sarah Kim). Fréquence : Par migration. Basculer un déploiement canari vers le nouveau compte de service, surveiller les journaux, valider l'expiration du jeton. - **Déploiement complet :** Responsable : Responsable des mises en production (par exemple, David Nguyen). Fréquence : Par application. Mettre à jour tous les déploiements, effectuer des mises à jour progressives, surveiller les échecs. - **Supprimer les jetons hérités :** Responsable : Ingénieur sécurité (Tom Chen). Fréquence : Après que toutes les charges de travail sont migrées et vérifiées. Supprimer les références aux secrets, supprimer les secrets, puis supprimer les anciens comptes de service s'ils ne sont pas utilisés. - **Revue post-migration :** Responsable : Architecte plateforme (par exemple, Emily Johnson). Fréquence : Dans la semaine suivant chaque migration majeure. Vérifier les erreurs de jeton, réviser la dérive RBAC, documenter les leçons apprises. - **Audit d'accès trimestriel :** Responsable : Ingénieur sécurité (Tom Chen). Fréquence : Trimestriel. Réviser toutes les autorisations des comptes de service, supprimer les comptes inutilisés, s'assurer que les politiques de jeton sont appliquées. ## Pièges courants et comment les éviter Voici les pièges que de nombreuses équipes rencontrent lors des migrations de comptes de service, avec des explications et des stratégies de prévention. ### Piège 1 : Supprimer les comptes de service hérités trop tôt **Pourquoi cela arrive :** Les équipes veulent nettoyer rapidement après la migration. **Conséquences :** Tout pod manqué référençant l'ancien compte de service échouera à démarrer. **Comment éviter :** Avant de supprimer, recherchez tous les pods utilisant le compte de service : ```bash kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.serviceAccountName == "legacy-app-sa")' ``` Si certains apparaissent, migrez-les d'abord. Gardez l'ancien compte de service pendant au moins un cycle de version complet. ### Piège 2 : Ne pas mettre à jour la logique de rafraîchissement des jetons dans les applications **Pourquoi cela arrive :** Les développeurs supposent que les jetons sont statiques parce qu'ils l'ont toujours été. **Conséquences :** Les applications cassent après l'expiration du jeton, souvent en production à des heures indues. **Comment éviter :** Testez avec une expiration de jeton courte (par exemple, 60 secondes) en préproduction. Assurez-vous que la bibliothèque cliente recharge le jeton. Documentez cette exigence pour toutes les applications. ### Piège 3 : RBAC trop permissif sur les nouveaux comptes de service **Pourquoi cela arrive :** Copier d'anciens rôles qui avaient accumulé des autorisations excessives. **Conséquences :** Risque de sécurité ; le nouveau compte de service peut avoir plus d'accès que nécessaire. **Comment éviter :** Commencez par le moindre privilège. Utilisez `kubectl auth can-i --list` pour voir les autorisations effectives réelles et réduisez au besoin. Impliquez une revue de sécurité. ### Piège 4 : Ignorer les secrets de compte de service dans les pipelines CI/CD **Pourquoi cela arrive :** Les pipelines utilisent des secrets de jeton codés en dur qui ne font pas partie de la spécification du pod. **Conséquences :** La rotation des secrets casse le CI/CD. **Comment éviter :** Inventoriez tous les consommateurs externes de jetons de compte de service, y compris les systèmes CI, les outils de surveillance et les scripts externes. Migrez-les pour utiliser des jetons projetés via l'API Kubernetes ou utilisez l'identité de charge de travail lorsque c'est possible. ### Piège 5 : Ne pas surveiller l'expiration des jetons dans les pods longue durée **Pourquoi cela arrive :** Les jetons expirent silencieusement ; les équipes ne s'en aperçoivent que lorsque les choses échouent. **Conséquences :** Échecs intermittents difficiles à déboguer. **Comment éviter :** Mettez en place des alertes de surveillance pour les pods avec des jetons projetés qui approchent de l'expiration. Utilisez un contrôleur ou un DaemonSet pour vérifier l'âge du jeton. Ou prolongez l'expiration à 7 jours comme solution temporaire. ## Conclusion La mise à niveau et la migration des comptes de service Kubernetes est un processus en plusieurs étapes qui nécessite un inventaire, une planification, un déploiement progressif et une vérification. En suivant les principes de sécurité opérationnelle d'observer avant de changer, de limiter le rayon d'impact, de sécuriser les secrets et de vérifier chaque changement, vous pouvez éviter les échecs courants. Comme prochaine étape, choisissez un compte de service hérité dans votre cluster, exécutez les commandes d'inventaire de la section 1 et créez un plan de migration en utilisant le chemin de configuration sécurisé. Attribuez un responsable et fixez une date de révision. Ensuite, exécutez la migration sur un déploiement canari, vérifiez l'expiration du jeton et les autorisations, et utilisez la liste de contrôle opérationnelle pour suivre les progrès. 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 procédures pour effectuer des mises à niveau de comptes de service en toute confiance.