E-NO
Kubernetes 7 min de lecture

Architecture des comptes de service Kubernetes : conception, sécurité et opérations avec exemples pratiques

calendar_today Publié : 2026-10-04
update Dernière mise à jour : 2026-10-04
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Architecture des comptes de service Kubernetes : conception, sécurité et opérations avec exemples pratiques ».

Introduction

Dans Kubernetes, les comptes de service sont les identités utilisées par les charges de travail pour s'authentifier auprès de l'API Kubernetes et d'autres services. Un pod sans compte de service est comme un utilisateur sans identifiants : il peut exister, mais il ne peut rien faire de significatif à l'intérieur du cluster. Pourtant, de nombreuses équipes traitent les comptes de service comme une réflexion après coup, créant des jetons cluster-admin pour chaque déploiement et les laissant en clair dans les spécifications des pods. Cet article explore l'architecture des comptes de service Kubernetes, comment les jetons sont émis et montés, comment RBAC transforme une identité en autorisations, et comment les exploiter en toute sécurité en production. Vous y trouverez des commandes concrètes, des manifestes, des scénarios d'échec et des étapes de vérification qui vous feront passer des approximations à un processus reproductible.

Même si vous utilisez Kubernetes depuis des années, le paysage des comptes de service a changé plusieurs fois. Les anciens jetons à longue durée de vie stockés dans des Secrets sont remplacés par des jetons liés et à durée limitée projetés directement dans les pods. Comprendre ce changement est crucial, car une documentation obsolète, d'anciens manifestes et de vieilles habitudes peuvent créer silencieusement des autorisations plus larges et plus durables que prévu. À la fin de cet article, vous devriez être capable d'inspecter un cluster existant, d'attribuer une identité à portée étroite à une application, de vérifier qu'elle fonctionne, et de savoir quoi faire lorsque ce n'est pas le cas.

Inventaire des versions et de l'environnement

Avant de modifier quoi que ce soit, vous devez savoir ce que vous exécutez. Le comportement des comptes de service Kubernetes diffère selon les versions, notamment en ce qui concerne les jetons hérités et les volumes projetés. Exécutez les commandes en lecture seule suivantes et enregistrez la sortie. Elles vous indiquent la version du cluster, les ressources API disponibles et l'état actuel des comptes de service dans un espace de noms.

kubectl version --short
kubectl api-versions | grep authentication
kubectl get serviceaccounts -n default
kubectl get secrets -n default

Dans Kubernetes 1.24 et versions ultérieures, les comptes de service ne sont plus automatiquement dotés d'un Secret contenant un jeton à longue durée de vie. Au lieu de cela, vous devez explicitement créer un jeton à l'aide de kubectl create token ou vous fier au jeton de compte de service projeté qui est monté dans chaque pod par défaut. Si vous voyez une colonne Secrets vide pour un compte de service, c'est normal et non une erreur. Si vous êtes sur un cluster plus ancien, chaque compte de service possède généralement un Secret nommé <nom-du-sa>-token-<aléatoire> contenant un jeton, un certificat CA et un espace de noms. Comparez ce que vous voyez avec la version pour éviter de chercher un Secret manquant que les versions plus récentes ne créent plus.

Vérifiez les contrôleurs d'admission et les feature gates qui affectent les comptes de service. Le plugin d'admission ServiceAccount est responsable de l'attachement du volume de jeton projeté et de la définition du serviceAccountName du pod. La fonctionnalité BoundServiceAccountTokenVolume est activée par défaut depuis la version 1.21 et stable depuis 1.22, vous n'avez donc normalement pas besoin de la modifier, mais les distributions personnalisées peuvent différer.

kubectl get pod -n kube-system -l component=kube-apiserver -o jsonpath='{.items[0].spec.containers[0].command}' | tr ',' '\n' | grep -E 'service-account|token'

Gardez un petit environnement de test local pour vos expériences. Minikube, kind ou k3s suffisent. Appliquez un manifeste à la fois et inspectez les ressources générées. Par exemple, créez un pod avec un compte de service personnalisé et vérifiez le montage du jeton :

kubectl apply -f - <<'EOF'
apiVersion: v1
kind: ServiceAccount
metadata:
  name: inventory-sa
  namespace: default
---
apiVersion: v1
kind: Pod
metadata:
  name: inventory-test
spec:
  serviceAccountName: inventory-sa
  containers:
  - name: app
    image: nginx:1.25
EOF

kubectl exec inventory-test -- ls /var/run/secrets/kubernetes.io/serviceaccount
# Sortie attendue : ca.crt  namespace  token

Notez que le fichier jeton est un jeton projeté. Il est à courte durée de vie, automatiquement renouvelé et lié à l'identité du pod. Le jeton hérité basé sur un Secret, s'il existe, est distinct et peut avoir une longue durée de vie.

Question rapide 1 sur 2

Quelle est la principale différence entre les comptes d'utilisateur et les comptes de service dans Kubernetes ?

Le passage indique que les comptes d'utilisateur sont destinés aux humains, tandis que les comptes de service sont destinés aux processus applicatifs qui s'exécutent dans des conteneurs en tant que composants de pods.

Chemin de configuration sécurisé

L'expression « moindre privilège » est souvent répétée mais rarement mise en pratique. Pour les comptes de service, le chemin de configuration sécurisé consiste à : créer un compte de service dédié pour chaque charge de travail, le lier à un Role ou ClusterRole avec les verbes et ressources minimaux dont il a réellement besoin, et laisser la projection de jeton par défaut gérer l'authentification. N'attachez pas le même ClusterRole large à plusieurs charges de travail et n'utilisez jamais cluster-admin pour une application.

Commencez par documenter ce que fait la charge de travail. Supposons que vous ayez un déploiement qui n'a besoin que de lister les pods dans son propre espace de noms. Créez d'abord l'identité :

kubectl create serviceaccount pod-reader-sa -n default

Définissez ensuite un Role qui autorise uniquement get et list sur les pods dans cet espace de noms :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

Liez le Role au ServiceAccount avec un RoleBinding :

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: default
subjects:
- kind: ServiceAccount
  name: pod-reader-sa
  namespace: default
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Appliquez le Role et le RoleBinding, puis testez l'autorisation en créant un pod temporaire utilisant le compte de service et en essayant de lister les pods :

kubectl apply -f role.yaml -f rolebinding.yaml
kubectl run test-pod --rm -i --tty --image=alpine --serviceaccount=pod-reader-sa -- sh
# À l'intérieur du pod :
wget -qO- --header="Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" --ca-certificate=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes.default.svc/api/v1/namespaces/default/pods

Si le rôle est correctement limité, vous verrez une liste JSON de pods. Si vous essayez de lister les déploiements, vous devriez obtenir une réponse 403 Forbidden. Ce test négatif est tout aussi important que le positif, car il prouve que le Role n'est pas plus large que prévu.

Pour les pods qui ont besoin d'un accès en lecture seule à l'échelle du cluster, utilisez un ClusterRole et un ClusterRoleBinding. Par exemple, ce ClusterRole accorde un accès en lecture aux nœuds :

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-reader
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

Liez-le à un compte de service spécifique dans un espace de noms spécifique :

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: node-reader-binding
subjects:
- kind: ServiceAccount
  name: node-reader-sa
  namespace: monitoring
roleRef:
  kind: ClusterRole
  name: node-reader
  apiGroup: rbac.authorization.k8s.io

Ne liez jamais cluster-admin à un ServiceAccount, sauf si vous construisez un contrôleur de gestion de cluster, et même dans ce cas, envisagez des rôles plus granulaires. Si vous trouvez une liaison existante qui utilise cluster-admin, remplacez-la ou au moins ajoutez une annotation expliquant le propriétaire et la date de révision.

Vérification et diagnostic

Lorsqu'une charge de travail signale des erreurs d'autorisation, le diagnostic le plus rapide consiste à lire les événements du pod, puis à inspecter le compte de service et ses liaisons. Utilisez la séquence suivante :

kubectl describe pod <nom-du-pod> -n <espace-de-noms>
kubectl get serviceaccount <nom-du-sa> -n <espace-de-noms> -o yaml
kubectl get rolebindings,clusterrolebindings -n <espace-de-noms> -o wide | grep <nom-du-sa>

Les événements du pod peuvent indiquer Failed to mount volume ou token not found. Si le compte de service n'existe pas, le pod restera dans un état Pending avec un événement comme serviceaccount "missing-sa" not found.

Un problème courant est que le apiGroups du rôle ne correspond pas à la ressource. Pour les ressources de base comme les pods, les services et les nœuds, le apiGroups doit être [""] (chaîne vide), et non ["v1"] ou ["core"]. Pour les ressources apps comme les déploiements, utilisez ["apps"]. Vérifiez le groupe API de la ressource avec kubectl api-resources | grep <ressource>.

Si un pod fonctionnait auparavant et échoue maintenant, vérifiez si son jeton de compte de service a expiré. Les jetons projetés ont une durée de vie par défaut de 1 heure, mais le kubelet les renouvelle automatiquement. Cependant, si le pod est de longue durée et que le renouvellement échoue en raison d'un redémarrage du kubelet ou d'un problème réseau, le pod peut conserver un jeton expiré. Vérifiez l'expiration du jeton en le décodant :

kubectl exec <nom-du-pod> -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d. -f2 | base64 -d 2>/dev/null | jq .exp

Comparez le timestamp d'expiration numérique à l'heure actuelle. Un pod sain devrait avoir un jeton qui expire plus tard que maintenant, généralement dans l'heure qui suit.

Pour voir toutes les autorisations qu'un compte de service possède actuellement, utilisez kubectl auth can-i :

kubectl auth can-i list pods --as=system:serviceaccount:default:pod-reader-sa -n default
kubectl auth can-i create deployments --as=system:serviceaccount:default:pod-reader-sa -n default

La première commande devrait renvoyer yes, la seconde no. C'est un moyen rapide de valider RBAC sans déployer de pod de test.

Modes d'échec et récupération

Compte de service manquant. Si le manifeste d'un pod fait référence à un compte de service qui n'existe pas, le pod ne sera jamais planifié. Récupérez en créant le compte de service ou en corrigeant le nom. Utilisez kubectl get serviceaccounts -n <espace-de-noms> pour lister les comptes disponibles.

Autorisations trop larges. Un compte de service lié à cluster-admin peut supprimer toutes les ressources. Récupération : identifiez la liaison fautive, supprimez-la, créez un Role minimal avec uniquement les verbes et ressources nécessaires, et liez-le à la place. Exécutez kubectl auth can-i --list --as=system:serviceaccount:<ns>:<sa> pour auditer toutes les autorisations.

Vol de jeton. Un jeton divulgué peut être utilisé jusqu'à son expiration, ce qui, pour les jetons hérités, peut prendre des années. Récupération : supprimez le Secret hérité, recréez le compte de service si nécessaire et migrez vers des jetons projetés. Vous pouvez forcer la rotation de tous les jetons en supprimant le pod. Si vous ne pouvez pas cesser d'utiliser des jetons à longue durée de vie, définissez au moins une expiration courte sur le Secret.

Inadéquation d'espace de noms dans RoleBinding. Un RoleBinding dans l'espace de noms A ne peut pas accorder d'autorisations à un compte de service dans l'espace de noms B pour des ressources namespacées. La liaison doit être dans le même espace de noms que le Role et le compte de service. Récupération : vérifiez les espaces de noms dans les sujets et roleRef du RoleBinding.

Erreurs de groupe API. Les symptômes incluent 403 Forbidden même si le rôle semble correct. Utilisez kubectl explain ou la référence API pour confirmer le bon apiGroups pour la ressource. Les ressources de base utilisent "", apps utilise "apps", batch utilise "batch".

Jeton expiré dans un pod de longue durée. Si un pod ne peut pas atteindre l'API après plusieurs heures, vérifiez manuellement l'expiration du jeton. S'il est expiré et non renouvelé, redémarrez le pod pour monter un jeton frais. Pour les applications qui doivent détecter le renouvellement du jeton dynamiquement, utilisez une bibliothèque cliente qui surveille le fichier de jeton. Les clients Kubernetes officiels et la plupart des clients communautaires prennent en charge le rechargement automatique.

Plugin d'admission ServiceAccount désactivé. Si le kubelet ne monte pas de jeton du tout, vérifiez que le plugin d'admission ServiceAccount est activé dans le serveur API. C'est rare mais cela peut arriver dans des clusters personnalisés construits avec kubeadm ou d'autres outils. La récupération implique de modifier le manifeste du serveur API pour inclure le plugin et de redémarrer le serveur API.

Question rapide 2 sur 2

Quel flag peut être utilisé pour révoquer les jetons de compte de service qui sont supprimés de l'API ?

Le passage indique que si --service-account-lookup est activé, les jetons supprimés de l'API seront révoqués.

Liste de contrôle opérationnelle

Utilisez cette liste de contrôle comme point de départ pour toute nouvelle charge de travail nécessitant un accès à l'API Kubernetes. Adaptez-la à votre processus de gestion des changements organisationnel, mais gardez l'esprit : vérifiez avant de modifier, et modifiez la plus petite chose possible.

  1. Identifiez les actions API Kubernetes requises par la charge de travail. De quelles ressources et verbes a-t-elle réellement besoin ? Notez-les. Exemple : get, list pods dans l'espace de noms 'payments'.
  2. Créez un ServiceAccount dédié. kubectl create serviceaccount payments-reader -n payments. N'utilisez pas le compte de service par défaut.
  3. Définissez un Role ou ClusterRole avec exactement ces autorisations. Utilisez verbs: ["get", "list"] et resources: ["pods"]. Évitez les caractères génériques sauf en cas d'absolue nécessité, et documentez pourquoi.
  4. Créez un RoleBinding ou ClusterRoleBinding qui relie le ServiceAccount au Role. Vérifiez que les espaces de noms correspondent.
  5. Testez les autorisations avant de déployer en production. Exécutez kubectl auth can-i avec le compte de service comme indiqué précédemment. Confirmez à la fois les actions autorisées et refusées.
  6. Déployez l'application avec serviceAccountName défini dans la spécification du pod. Assurez-vous qu'aucun jeton de Secret hérité n'est monté sauf si explicitement nécessaire.
  7. Surveillez les journaux et les événements du pod pour détecter les erreurs d'authentification ou d'autorisation. Configurez une alerte pour 403 Forbidden dans votre agrégation de journaux.
  8. Révisez les autorisations des comptes de service trimestriellement. Utilisez kubectl get rolebindings,clusterrolebindings --all-namespaces -o json et scriptez un rapport qui signale les liaisons vers des ClusterRoles à haut risque comme cluster-admin, edit et admin.
  9. Renouvelez les jetons à longue durée de vie au moins tous les 90 jours. Mieux encore, éliminez-les et comptez sur les jetons projetés.
  10. Documentez l'objectif du compte de service, son propriétaire et sa date de révision dans une annotation sur le ServiceAccount. Par exemple :
metadata:
  name: payments-reader
  namespace: payments
  annotations:
    purpose: "Accès en lecture seule aux pods pour le contrôleur de réconciliation"
    owner: "Priya Shah, responsable de l'équipe plateforme"
    review-date: "2026-03-31"

Attribuez un propriétaire responsable unique pour chaque décision majeure de cette liste de contrôle. Par exemple, le responsable de l'équipe plateforme approuve tout ClusterRoleBinding, l'architecte de sécurité est responsable de la révision trimestrielle des autorisations, et le développeur d'applications s'assure que son déploiement utilise le bon serviceAccountName. Révisez les rôles et autorisations trimestriellement, ou immédiatement après tout changement significatif dans la fonctionnalité de l'application.

Pièges courants

Même les ingénieurs expérimentés tombent dans les mêmes pièges. Voici les erreurs les plus fréquentes et comment les éviter.

Piège 1 : Donner cluster-admin à chaque application. Les équipes sous pression commencent souvent par cluster-admin et ne réduisent jamais. Pourquoi cela arrive : l'application échoue d'abord avec des erreurs d'autorisation, et quelqu'un accorde le rôle le plus large pour la faire fonctionner rapidement. Comment éviter : investissez une heure pour déterminer les appels API exacts que l'application fait. Utilisez kubectl auth can-i --list pour simuler et construire itérativement un Role minimal.

Piège 2 : Ne pas comprendre les jetons hérités vs projetés. Les anciens tutoriels et manifestes font souvent référence à secrets et serviceAccountToken. Si vous êtes sur Kubernetes 1.24+, ceux-ci peuvent ne pas fonctionner comme prévu. Comment éviter : vérifiez d'abord la version de votre cluster et préférez le jeton projeté par défaut. Si vous devez utiliser un jeton hérité, créez explicitement un Secret de type kubernetes.io/service-account-token et définissez automountServiceAccountToken: false lorsque c'est approprié.

Piège 3 : RoleBinding dans le mauvais espace de noms. Une inadéquation d'espace de noms échoue silencieusement. Supposons que vous créez un Role dans l'espace de noms staging et le liez à un compte de service dans production sans ClusterRoleBinding. Le pod de production obtiendra des erreurs 403. Comment éviter : spécifiez toujours namespace dans les sujets et le roleRef du RoleBinding, et vérifiez avec kubectl auth can-i.

Piège 4 : Mauvaise utilisation d'apiGroups. Pour les ressources de base comme les pods et les services, utiliser apiGroups: ["v1"] au lieu de apiGroups: [""] entraîne aucune autorisation. Comment éviter : exécutez kubectl api-resources | grep <ressource> pour voir le bon groupe API. Le groupe de base est vide, pas v1.

Piège 5 : Négliger le compte de service par défaut. Chaque espace de noms a un compte de service par défaut sans autorisations, et les pods l'utilisent si vous n'en spécifiez pas. Si un pod fait des appels API, il obtiendra 403 Forbidden. Comment éviter : définissez explicitement serviceAccountName pour les pods qui ont besoin d'un accès API, et n'ajoutez jamais d'autorisations au compte de service par défaut, car alors tous les pods sans compte personnalisé les héritent.

Piège 6 : Fuite de jetons dans les journaux ou la configuration. Une erreur courante est d'imprimer le jeton dans une commande de débogage ou de le commiter dans une ConfigMap. Comment éviter : utilisez kubectl create token pour un accès temporaire, et ne stockez jamais de jetons en clair. Traitez un jeton de compte de service comme une identité porteur : s'il fuit, révoquez-le en supprimant le pod ou le Secret.

Conclusion

Les comptes de service sont une partie fondamentale de la sécurité Kubernetes, mais ils sont souvent négligés jusqu'à ce que quelque chose casse ou soit compromis. En comprenant l'architecture des jetons, des liaisons RBAC et de la projection d'identité des pods, vous pouvez concevoir des charges de travail qui ont exactement les autorisations dont elles ont besoin et rien de plus. Les commandes et manifestes de cet article vous fournissent une boîte à outils pratique pour auditer les comptes de service existants, en créer de nouveaux avec le moindre privilège, diagnostiquer les problèmes d'accès et récupérer des échecs courants.

Commencez par une vérification à faible risque : choisissez un pod en cours d'exécution dans votre cluster, inspectez son compte de service, exécutez kubectl auth can-i --list, et comparez la sortie avec ce que fait réellement l'application. Il y a de fortes chances que vous trouviez au moins une surprise. Documentez ensuite le compte de service, attribuez un propriétaire et fixez une date de révision. Cette petite habitude renforce la fiabilité et la sécurité qu'exige Kubernetes en production.

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 une vérification de récupération avant qu'un incident ne force la décision. Les comptes de service ne sont pas un simple détail de configuration ; ils constituent le fondement identitaire du modèle de sécurité de votre cluster.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO