E-NO
Kubernetes 8 min de lecture

Dépannage des contextes de sécurité Kubernetes : guide pratique de terrain

calendar_today Publié : 2026-09-09
update Dernière mise à jour : 2026-09-09
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Dépannage des contextes de sécurité Kubernetes : guide pratique de terrain ».

Introduction

Lorsqu’un pod échoue avec CreateContainerConfigError ou qu’un conteneur se termine immédiatement avec operation not permitted, la cause est souvent cachée dans le securityContext du pod. Ce guide transforme ces échecs opaques en un processus de dépannage reproductible. Il s’adresse aux développeurs, aux ingénieurs de plateforme, aux consultants DevOps et à toute personne qui exploite des clusters Kubernetes et souhaite résoudre les problèmes de contexte de sécurité sans deviner.

L’article parcourt des scénarios de défaillance réalistes, montre les commandes exactes pour les diagnostiquer et fournit des correctifs minimaux qui maintiennent la sécurité du cluster. Chaque étape de récupération est réversible là où Kubernetes le permet, et chaque section inclut une commande de vérification pour s’assurer que le problème est réellement résolu.

Avant d’effectuer des modifications, observez toujours l’état actuel : vérifiez la version de Kubernetes, la configuration de sécurité du pod et les politiques de sécurité du nœud. Capturez les horodatages et les sorties de commande. Limitez tout changement à un seul champ ciblé et préparez un plan de retour en arrière. Cette discipline opérationnelle évite de transformer une petite erreur de configuration en une panne plus large.

Inventaire de la version et de l’environnement

Commencez par noter la version de Kubernetes, le runtime de conteneur et le système d’exploitation du nœud. Le comportement du contexte de sécurité diffère selon les versions, notamment en ce qui concerne seccomp et AppArmor. Utilisez les commandes en lecture seule suivantes pour recueillir les détails :

kubectl version --short
kubectl get nodes -o wide
kubectl describe node <nom-du-nœud> | grep -A5 "System Info"

La sortie attendue pour kubectl version --short ressemble à :

Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.2

Si la version du serveur est antérieure à la v1.19, le champ seccompProfile dans le contexte de sécurité du pod peut ne pas être disponible en tant qu’API stable. Cela réduit immédiatement le chemin de dépannage.

Ensuite, obtenez une vue d’ensemble de tous les pods et de leurs champs liés à la sécurité :

kubectl get pods -o custom-columns='NAME:.metadata.name,STATUS:.status.phase,RUNASUSER:.spec.containers[*].securityContext.runAsUser,RUNASGROUP:.spec.containers[*].securityContext.runAsGroup,PRIVILEGED:.spec.containers[*].securityContext.privileged'

Exemple de sortie :

NAME                     STATUS    RUNASUSER   RUNASGROUP   PRIVILEGED
nginx-6799fc88d8-abcde   Running   1000        <none>       false
api-server-7b58f5c9-x    Error     <none>      <none>       false

Le second pod est dans l’état Error et n’a pas de runAsUser défini. C’est un indice, mais pas encore un diagnostic.

Pour un pod défaillant spécifique, inspectez ses événements :

kubectl describe pod api-server-7b58f5c9-x

Recherchez des événements comme :

Warning  Failed     5s (x2 over 10s)   kubelet            Error: container has runAsNonRoot and image will run as root

Cet événement vous indique exactement quel champ du contexte de sécurité est en conflit. Avant de modifier quoi que ce soit, capturez le manifeste actuel :

kubectl get pod api-server-7b58f5c9-x -o yaml > failing-pod-backup.yaml

Vous disposez maintenant d’une référence et d’une sauvegarde. L’étape suivante consiste à isoler le plus petit changement qui résout le problème sans affaiblir la sécurité.

Question rapide 1 sur 2

Que définit l'exemple de Pod dans la référence [1] pour les capabilities ?

L'exemple de Pod au niveau du conteneur définit les capabilities sur drop: ALL.

Chemin de configuration sûr

Le chemin sûr pour modifier un contexte de sécurité consiste à tester les modifications d’abord dans un espace de noms hors production, ou sur un seul pod avec une étiquette canari. Ne modifiez jamais directement le modèle de pod d’un déploiement en cours sans test ; créez plutôt une copie du manifeste, modifiez-la et appliquez-la à un espace de noms de test.

Voici un pod minimal qui s’exécute en tant qu’utilisateur non root :

apiVersion: v1
kind: Pod
metadata:
  name: security-test
  namespace: test
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: app
    image: nginx:1.25
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: ["ALL"]
      readOnlyRootFilesystem: true

Appliquez ceci à l’espace de noms de test, puis vérifiez que le pod fonctionne :

kubectl apply -f security-test.yaml
kubectl get pod security-test -n test -o wide

Si le pod s’exécute avec succès, les champs du contexte de sécurité sont acceptables pour le cluster. S’il échoue, décrivez-le pour voir l’événement exact :

kubectl describe pod security-test -n test

Les échecs courants incluent :

  • runAsNonRoot est vrai mais l’utilisateur par défaut de l’image est root (UID 0). Le runtime de conteneur refuse de démarrer. Correctif : spécifiez runAsUser avec un UID non nul qui existe dans l’image.
  • readOnlyRootFilesystem: true fait échouer l’application lorsqu’elle tente d’écrire dans /tmp ou /var/log. Correctif : montez un volume emptyDir sur ces chemins, ou ajustez l’application pour écrire ailleurs.
  • Supprimer toutes les capacités avec drop: ["ALL"] casse les applications qui ont besoin de NET_BIND_SERVICE pour se lier à des ports inférieurs à 1024. Correctif : rajoutez uniquement les capacités requises avec add: ["NET_BIND_SERVICE"].

Essayez toujours le plus petit changement en premier. Par exemple, si le conteneur échoue à cause de readOnlyRootFilesystem, ne modifiez pas aussi runAsUser ; changez un seul champ, testez, puis continuez.

Vérification et diagnostics

Le diagnostic des problèmes de contexte de sécurité nécessite d’inspecter l’état d’exécution réel du conteneur, pas seulement la spécification du pod. Les commandes suivantes offrent une visibilité approfondie.

Vérifiez les paramètres de sécurité effectifs du pod en interrogeant le serveur d’API avec kubectl get pod -o yaml ; la section status peut inclure une entrée containerStatuses avec un lastState ou une reason.

Affichez les journaux du conteneur, y compris l’instance précédente qui a planté :

kubectl logs security-test -n test --previous

Si le conteneur n’a jamais démarré, les journaux peuvent être vides. Dans ce cas, utilisez kubectl describe pod pour lire les événements.

Inspectez directement le runtime de conteneur si vous avez accès au nœud. Pour containerd :

crictl ps -a | grep security-test
crictl inspect <container-id> | jq '.info.runtimeSpec.linux.securityContext'

La sortie affiche le contexte de sécurité Linux exact appliqué au conteneur, y compris runAsUser, capabilities et seccomp.

Vérifiez le profil seccomp appliqué au conteneur :

crictl inspect <container-id> | jq '.info.runtimeSpec.linux.seccomp'

Si le profil est localhost/default mais que le nœud ne possède pas ce fichier de profil, le conteneur échoue avec cannot load seccomp profile. Le correctif consiste à utiliser RuntimeDefault ou à fournir le profil.

Validez les profils AppArmor ou SELinux lorsqu’ils sont utilisés. Pour SELinux, vérifiez le seLinuxOptions du contexte de sécurité du pod et le mode d’application actuel du nœud :

getenforce

Si le nœud est en mode enforcing et que le type SELinux du conteneur n’est pas autorisé, le conteneur sera refusé. Vous pouvez temporairement passer en mode permissif pour les tests (avec prudence), puis affiner la politique.

Vérifiez les avertissements de Pod Security Admission. Si l’espace de noms applique une politique restreinte, un pod qui la viole peut être rejeté ou averti. Affichez les étiquettes de l’espace de noms :

kubectl get namespace test -o yaml | grep pod-security

Si pod-security.kubernetes.io/enforce=restricted est défini, alors runAsNonRoot: true est obligatoire et les capacités doivent être supprimées. Ajustez le contexte de sécurité du pod pour qu’il soit conforme.

Un tableau de diagnostic structuré peut aider à organiser les constatations. Voici un exemple de ce qu’il faut enregistrer :

VérificationCommandeAttenduObservéÉtape suivante
Statut du podkubectl get podRunningErrorDécrire le pod, vérifier les événements
Événementskubectl describe podAucun avertissementConflit runAsNonRootDéfinir runAsUser sur une valeur non nulle
Journauxkubectl logs --previousApplication démarréePermission refusée en écritureMonter emptyDir ou ajuster les permissions
Seccompcrictl inspectRuntimeDefaultlocalhost/default fichier manquantChanger seccompProfile en RuntimeDefault
SELinuxgetenforceEnforcingEnforcingVérifier seLinuxOptions dans la spec du pod

Remplissez les valeurs observées réelles à chaque fois ; le tableau ci-dessus est illustratif.

Modes de défaillance et récupération

Plusieurs modes de défaillance sont courants avec les contextes de sécurité. Les comprendre accélère la récupération.

Échec 1 : le conteneur se termine avec operation not permitted

Cause : le conteneur tente une opération privilégiée qui est bloquée par le contexte de sécurité, comme changer la propriété d’un fichier, se lier à un port bas ou utiliser un module du noyau.

Diagnostic : consultez les journaux du conteneur et le code de sortie. Par exemple :

Error: listen EACCES: permission denied 0.0.0.0:80

Cela indique que le conteneur n’a pas la capacité NET_BIND_SERVICE et tente de se lier au port 80.

Récupération : ajoutez explicitement la capacité dans le contexte de sécurité du conteneur :

securityContext:
  capabilities:
    add: ["NET_BIND_SERVICE"]

Vous pouvez également modifier l’application pour qu’elle se lie à un port supérieur à 1024, par exemple 8080. C’est plus sûr.

Échec 2 : pod bloqué dans CreateContainerConfigError

Cause : le contexte de sécurité référence un profil seccomp, un profil AppArmor ou une étiquette SELinux inexistant.

Diagnostic : kubectl describe pod affiche un événement comme :

Error: cannot load seccomp profile "/var/lib/kubelet/seccomp/custom.json": no such file or directory

Récupération : fournissez le fichier de profil sur le nœud, ou modifiez la spec du pod pour utiliser seccompProfile: type: RuntimeDefault.

Échec 3 : pod bloqué par Pod Security Admission

Cause : l’espace de noms applique un niveau de politique (baseline ou restricted) que le pod viole.

Diagnostic : kubectl describe pod peut afficher un événement d’avertissement, ou le pod n’est pas créé du tout. Vérifiez les étiquettes de l’espace de noms :

kubectl get namespace myapp -o jsonpath='{.metadata.labels}'

Si pod-security.kubernetes.io/enforce=restricted est défini, le pod doit avoir runAsNonRoot: true, supprimer toutes les capacités et définir seccompProfile sur RuntimeDefault.

Récupération : modifiez le pod pour qu’il respecte la politique, ou changez l’application de l’espace de noms à un niveau inférieur si l’activité l’exige (non recommandé en production).

Échec 4 : problèmes de permissions de volume avec fsGroup

Cause : le pod a fsGroup défini, mais le type de volume ne le prend pas en charge, ou l’ID de groupe n’existe pas dans /etc/group du conteneur.

Diagnostic : les journaux du pod affichent mkdir: cannot create directory '/data': Permission denied.

Récupération : assurez-vous que le volume est d’un type qui prend en charge fsGroup (par exemple, emptyDir, la plupart des volumes CSI). Si l’application crée des fichiers nécessitant un accès de groupe, définissez fsGroup sur un GID qui existe dans l’image ou utilisez un initContainer pour ajuster les permissions.

Chaque récupération doit être suivie d’une étape de vérification. Par exemple, après avoir ajouté NET_BIND_SERVICE, redémarrez le pod et vérifiez que l’application est accessible :

kubectl port-forward pod/myapp 8080:80
curl localhost:8080

Si vous devez revenir en arrière, appliquez le manifeste de sauvegarde :

kubectl apply -f failing-pod-backup.yaml

Question rapide 2 sur 2

Dans l'exemple de securityContext au niveau du Pod, quelle est la valeur de fsGroup ?

L'exemple de securityContext au niveau du Pod a fsGroup: 2000.

Liste de contrôle opérationnelle

Utilisez cette liste de contrôle pour normaliser le dépannage des contextes de sécurité. Attribuez un responsable unique à chaque élément et révisez la liste chaque trimestre ou après toute mise à niveau du cluster.

  • Avant tout changement : capturez le manifeste actuel du pod avec kubectl get pod <nom> -o yaml > backup.yaml. Responsable : ingénieur d’astreinte.
  • Vérification de version : enregistrez la version du serveur Kubernetes avec kubectl version --short. Assurez-vous que seccomp et les autres fonctionnalités sont prises en charge. Responsable : responsable de plateforme.
  • Diagnostics en lecture seule : exécutez kubectl describe pod, kubectl logs --previous et kubectl get events. Documentez les résultats dans un ticket partagé. Responsable : ingénieur de dépannage.
  • Isolation du changement : modifiez un champ du contexte de sécurité à la fois dans un espace de noms de test. Responsable : développeur.
  • Vérification : après avoir appliqué le correctif, vérifiez que le pod passe à Running et que l’application répond correctement. Utilisez kubectl port-forward et curl. Responsable : ingénieur QA ou développeur.
  • Plan de retour en arrière : conservez le manifeste de sauvegarde et une commande de retour écrite dans le ticket. Responsable : ingénieur d’astreinte.
  • Revue de politique : si le problème a été causé par Pod Security Admission, examinez la politique de l’espace de noms et décidez d’ajuster le pod ou la politique. Responsable : responsable sécurité et responsable de plateforme, revue mensuelle.
  • Documentation : mettez à jour les runbooks ou la documentation de l’équipe avec le mode de défaillance et son correctif. Responsable : rédacteur technique ou responsable DevOps.
  • Revue post-incident : pour les problèmes de gravité élevée, planifiez une post-mortem sans blâme dans les 5 jours ouvrables. Responsable : responsable d’ingénierie.

Pièges courants

Voici les pièges qui font souvent trébucher les opérateurs lorsqu’ils travaillent avec les contextes de sécurité, et comment les éviter.

Piège 1 : définir runAsNonRoot: true sans vérifier l’utilisateur par défaut de l’image

De nombreuses images s’exécutent en tant que root par défaut. Lorsque vous ajoutez runAsNonRoot: true, le conteneur échoue immédiatement avec Error: container has runAsNonRoot and image will run as root. Évitez cela en vérifiant d’abord l’utilisateur de l’image avec docker inspect ou en lisant sa documentation. Spécifiez toujours runAsUser avec un UID durci.

Piège 2 : supprimer toutes les capacités sans tester l’application

capabilities: drop: ["ALL"] est une bonne pratique de sécurité, mais de nombreuses applications ont besoin d’au moins une capacité. Par exemple, un serveur web qui se lie au port 80 a besoin de NET_BIND_SERVICE. Testez l’application avec toutes les capacités supprimées dans un environnement de préproduction, et ne rajoutez que les capacités exactes requises.

Piège 3 : utiliser readOnlyRootFilesystem: true sans fournir de volumes inscriptibles

Les applications ont souvent besoin d’écrire des fichiers temporaires, des journaux ou des caches. Avec un système de fichiers racine en lecture seule, elles échouent avec Permission denied. Planifiez à l’avance : montez des volumes emptyDir sur /tmp, /var/log et d’autres chemins inscriptibles. Utilisez un initContainer si l’application doit pré-peupler des répertoires.

Piège 4 : mal comprendre les types de profil seccomp

Définir seccompProfile: type: Localhost nécessite que le fichier de profil soit présent sur le nœud à un chemin spécifique sous /var/lib/kubelet/seccomp/. Si le fichier est manquant, le pod échoue avec CreateContainerConfigError. Utiliser RuntimeDefault est plus sûr et fonctionne partout. N’utilisez des profils personnalisés que lorsque vous contrôlez le système de fichiers du nœud et disposez d’un processus de déploiement.

Piège 5 : utiliser une image de conteneur qui n’inclut pas l’UID runAsUser spécifié

Si vous définissez runAsUser: 1000 mais que le /etc/passwd de l’image n’a pas d’UID 1000, le conteneur s’exécute quand même avec l’UID 1000 (le noyau n’a pas besoin que l’utilisateur existe), mais l’application peut rencontrer des problèmes de permission lorsqu’elle accède à des fichiers appartenant à d’autres utilisateurs. Assurez-vous que l’image est construite avec l’utilisateur attendu, ou utilisez fsGroup et runAsGroup pour aligner la propriété des fichiers.

Piège 6 : appliquer les contextes de sécurité uniquement au niveau du pod et oublier les remplacements au niveau du conteneur

Un securityContext au niveau du pod définit des valeurs par défaut pour tous les conteneurs, mais chaque conteneur peut le remplacer par son propre securityContext. Si un conteneur nécessite des paramètres différents, vérifiez que les champs au niveau du conteneur sont corrects. Une erreur courante consiste à définir runAsUser au niveau du pod, puis à le remplacer par inadvertance dans un conteneur.

Conclusion

Le dépannage des contextes de sécurité Kubernetes est un processus méthodique, pas un jeu de devinettes. En suivant la séquence de ce guide, vous pouvez résoudre la plupart des échecs rapidement sans affaiblir la posture de sécurité du cluster. Observez toujours avant de modifier, faites un changement ciblé à la fois, vérifiez le résultat et ayez un plan de retour en arrière.

La prochaine fois que vous serez confronté à une erreur CreateContainerConfigError ou operation not permitted, commencez par l’inventaire des versions et les diagnostics en lecture seule, puis appliquez le correctif minimal de la section des modes de défaillance. Conservez ce guide comme référence de terrain et mettez-le à jour au fur et à mesure que vos clusters évoluent.

Une exploitation fiable de Kubernetes exige que chaque décision de sécurité soit intentionnelle. Documentez vos contextes de sécurité, testez-les en préproduction et révisez-les régulièrement. Cette discipline transforme la sécurité d’une source d’incidents en une partie prévisible de votre pipeline de déploiement.

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