Introduction
Seccomp (secure computing mode) est une fonctionnalité du noyau Linux qui restreint les appels système (syscalls) qu'un conteneur peut effectuer. Bien que Seccomp soit souvent associé au durcissement de la sécurité, il peut également avoir un impact sur les capacités réseau. Si un profil bloque ou gère mal les syscalls liés aux opérations réseau, vos pods peuvent ne pas résoudre le DNS, se connecter à d'autres services ou accepter le trafic entrant. Ce guide fournit une approche pratique, étape par étape, pour résoudre les problèmes réseau liés à Seccomp, y compris les méthodes de configuration sûres, les commandes de vérification et les procédures de récupération.
Inventaire de l'environnement et des versions
Avant de faire tout changement, documentez votre environnement. Cela garantit que vous pouvez reproduire les problèmes et revenir en arrière si nécessaire. Les éléments clés à enregistrer :
- Version de Kubernetes :
kubectl version --short(serveur et client)
Exemple de sortie :
Client Version: v1.28.2
Server Version: v1.28.2
- Runtime de conteneur et version :
crictl versionoudocker version(si vous utilisez Docker)
Exemple :
crictl version
Version: 0.1.0
RuntimeName: containerd
RuntimeVersion: v1.7.2
- OS du nœud et noyau :
uname -rsur un nœud (par exemple,5.15.0-91-generic)
- Support Seccomp : vérifiez que le kubelet a
seccomp-profile-rootconfiguré (par défaut,/var/lib/kubelet/seccomp). Vérifiez la configuration du kubelet sur un nœud :
cat /var/lib/kubelet/config.yaml | grep -i seccomp
Sortie attendue : seccomp-profile-root: /var/lib/kubelet/seccomp ou similaire.
- Topologie du cluster : nombre de nœuds, plugin réseau (par exemple, Calico, Flannel, Cilium) et si vous utilisez un service mesh (par exemple, Istio, Linkerd).
Prérequis pour les commandes de ce guide :
kubectlconfiguré pour accéder à votre cluster- Accès SSH aux nœuds pour les vérifications au niveau du runtime
jqpour analyser la sortie JSON (facultatif mais utile)
Exemple de commande d'inventaire de l'environnement :
kubectl get nodes -o wide
Sortie attendue (tronquée) :
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE
node01 Ready <none> 10d v1.28.2 10.0.0.1 <none> Ubuntu 22.04
Vérifiez également la configuration du kubelet pour Seccomp sur un nœud :
cat /var/lib/kubelet/config.yaml | grep -i seccomp
Si la sortie montre seccomp-profile-root, vous êtes prêt.
Chemin de configuration sûr
Lorsque vous soupçonnez que Seccomp cause des problèmes réseau, n'appliquez pas immédiatement un profil large ou restrictif. Suivez une approche ciblée :
1. Commencez avec le profil par défaut
Kubernetes dispose d'un profil Seccomp par défaut qui est généralement sûr pour la plupart des charges de travail. Vous pouvez l'activer par pod ou par conteneur. Par exemple, pour exécuter un pod avec le profil par défaut :
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: test
image: busybox
command: ["sh", "-c", "sleep 3600"]
Appliquez avec kubectl apply -f pod.yaml.
2. Si le défaut fonctionne, le problème vient du profil personnalisé
Si le profil par défaut fonctionne, le problème vient probablement d'un profil personnalisé. Si vous avez un profil personnalisé, comparez-le avec celui par défaut. Vous pouvez extraire le profil par défaut du runtime de conteneur. Pour containerd, il est généralement à /var/lib/containerd/io.containerd.runtime.v2.task/default/seccomp.json (le chemin peut varier). Utilisez crictl info pour trouver le chemin du profil Seccomp :
crictl info | jq '.config.seccomp'
3. Créer un profil personnalisé qui autorise les syscalls réseau nécessaires
Par exemple, si vous devez autoriser la résolution DNS, assurez-vous que ces syscalls sont autorisés : socket, connect, sendto, recvfrom, bind, listen, accept, getsockname, getpeername, setsockopt, getsockopt. Notez que getaddrinfo est une fonction glibc, pas un syscall ; elle utilise socket, connect, sendto, recvfrom. Commencez par un profil permissif qui journalise les refus :
{
"defaultAction": "SCMP_ACT_LOG",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": [
"socket", "bind", "connect", "listen", "accept", "accept4",
"sendto", "recvfrom", "sendmsg", "recvmsg", "getsockname",
"getpeername", "setsockopt", "getsockopt", "shutdown"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
Enregistrez ceci sous allow-net.json et utilisez-le dans une spécification de pod :
apiVersion: v1
kind: Pod
metadata:
name: test-net
spec:
securityContext:
seccompProfile:
type: Localhost
localhostProfile: "profiles/allow-net.json"
containers:
- name: test
image: busybox
command: ["sh", "-c", "sleep 3600"]
Important : vous devez placer le fichier de profil dans le répertoire racine des profils Seccomp sur le nœud, généralement /var/lib/kubelet/seccomp/profiles/allow-net.json. Assurez-vous que le fichier existe sur tous les nœuds où le pod peut s'exécuter.
4. Testez avec une vérification simple de connectivité
Exécutez un pod avec ce profil et vérifiez que le réseau fonctionne de base avant de continuer.
Vérification et diagnostics
Une fois votre pod exécuté avec un profil Seccomp, effectuez ces vérifications pour confirmer que le réseau fonctionne :
1. Vérifiez le statut du pod et les événements
kubectl describe pod test-net | tail -20
Attendu : Status: Running et aucun événement lié à Seccomp. Recherchez des avertissements comme Seccomp profile assigned ou des erreurs.
2. Exécutez un test de résolution DNS
kubectl exec -it test-net -- nslookup kubernetes.default
La sortie attendue inclut Address: 10.96.0.1 (ou l'adresse IP DNS de votre cluster). Si cela échoue avec connection timed out ou no servers could be reached, vérifiez les syscalls DNS.
3. Testez la connectivité sortante vers une IP externe
kubectl exec -it test-net -- wget -O- --timeout=5 http://example.com
Attendu : réponse HTTP. Si cela reste bloqué, vérifiez les syscalls connect et sendto.
4. Testez l'écoute sur un port (si votre application l'exige)
kubectl exec -it test-net -- nc -l -p 8080 &
sleep 2
kubectl exec -it test-net -- nc -z localhost 8080
Attendu : code de sortie 0. Si cela échoue, vérifiez bind et listen.
5. Consultez les journaux Seccomp
Si vous avez utilisé SCMP_ACT_LOG comme action par défaut, le noyau journalisera les refus dans dmesg. Sur le nœud où votre pod s'exécute, exécutez :
sudo dmesg | grep -i seccomp | tail -20
Recherchez des entrées comme SECCOMP: pid 1234 ... syscall=42 (connect) indiquant des syscalls bloqués. Le numéro de syscall peut être mappé à l'aide d'un tableau (par exemple, sur x86_64, 42 est connect).
Pour faciliter cela, utilisez un outil comme strace dans le conteneur (si disponible) pour voir quels syscalls échouent :
kubectl exec -it test-net -- strace -f -e trace=network nslookup kubernetes.default
Cela montrera les appels connect et leurs valeurs de retour.
Tableau : Syscalls réseau courants et leurs actions
| Syscall | Description | Erreur courante si bloqué |
|---|---|---|
socket | Créer un point de terminaison pour la communication | EPERM |
connect | Initier une connexion | EPERM |
bind | Associer un nom à un socket | EPERM |
listen | Écouter les connexions | EPERM |
accept | Accepter une connexion | EPERM |
sendto | Envoyer un message sur un socket | EPERM |
recvfrom | Recevoir un message d'un socket | EPERM |
getsockname | Obtenir le nom du socket | EPERM |
getsockopt | Obtenir les options du socket | EPERM |
Ces erreurs apparaissent généralement dans les journaux d'application ou via strace.
Modes de défaillance et récupération
Comprendre les modes de défaillance vous aide à réagir rapidement. Voici les problèmes courants et comment les résoudre :
1. Profil trop restrictif
Si votre profil personnalisé bloque un syscall requis, le conteneur peut ne pas démarrer ou planter. Vérifiez le statut du pod :
kubectl get pods
kubectl describe pod <name> | grep -A5 "Events:"
Recherchez failed to create containerd task: failed to create shim task: ... operation not permitted ou similaire.
Récupération : mettez à jour le profil pour autoriser le syscall manquant ou passez à RuntimeDefault. Appliquez le changement avec kubectl apply ou kubectl replace (si le pod est géré par un Deployment, utilisez kubectl rollout restart).
2. Échec réseau silencieux
Le pod s'exécute mais ne peut pas se connecter. Utilisez dmesg pour vérifier les refus Seccomp. Si vous avez SCMP_ACT_LOG, les journaux du noyau montreront le syscall fautif. Si vous avez utilisé SCMP_ACT_ERRNO, vous obtiendrez simplement un code d'erreur dans l'application.
Récupération : changez temporairement l'action par défaut du profil en SCMP_ACT_LOG pour diagnostiquer, puis ajoutez le syscall nécessaire à la liste autorisée.
3. Mauvais chemin de profil
Si le profil n'est pas trouvé, le pod échouera avec seccomp profile not found. Vérifiez que le fichier est présent sur le nœud et que le chemin dans la spécification du pod est correct.
Récupération : recréez le profil sur le nœud et réessayez.
4. Étapes de retour arrière
Si vous avez appliqué un profil Seccomp à l'échelle du cluster (via PodSecurityPolicy ou SecurityContextConstraints), vous pouvez revenir en arrière en supprimant la politique ou en réinitialisant la valeur par défaut. Pour un retour arrière immédiat d'un pod spécifique, appliquez la configuration précédente qui fonctionnait :
kubectl rollout undo deployment/<name>
Ou patchez le pod directement (s'il s'agit d'un pod simple) :
kubectl patch pod <name> --type='json' -p='[{"op": "replace", "path": "/spec/securityContext/seccompProfile/type", "value": "RuntimeDefault"}]'
Remarque : patcher un pod directement peut ne pas fonctionner si le pod est géré par un contrôleur ; utilisez kubectl edit sur le déploiement à la place.
Après la récupération, vérifiez à nouveau la connectivité avec les tests de la section précédente.
Liste de contrôle opérationnelle
Intégrez ces vérifications dans votre routine opérationnelle pour prévenir et résoudre rapidement les problèmes réseau liés à Seccomp :
- Documentez votre profil Seccomp pour chaque charge de travail. Stockez les profils dans un système de contrôle de version.
- Testez les profils dans un environnement de staging avant la production.
- Surveillez les refus Seccomp. Utilisez
dmesgou la collecte de journaux système pour alerter sur les refus répétés. - Examinez régulièrement les journaux Seccomp pour détecter des refus inattendus qui pourraient indiquer de nouvelles exigences réseau.
- Gardez les profils minimaux. N'autorisez que les syscalls requis par votre application.
- Lors de la mise à niveau de Kubernetes ou du runtime de conteneur, validez le comportement de Seccomp car les numéros de syscall peuvent changer.
- Utilisez le profil
RuntimeDefaultcomme base sauf si vous avez une raison spécifique de personnaliser. - Incluez une vérification de connectivité réseau dans les sondes de readiness de vos pods pour détecter les problèmes tôt.
Tableau : Liste de contrôle de dépannage rapide
| Symptôme | Première commande | Cause possible |
|---|---|---|
| Échec DNS | nslookup | connect ou sendto bloqué |
| Connexion sortante expirée | wget | connect bloqué |
| Impossible de lier un port | nc -l | bind ou listen bloqué |
| Le pod ne démarre pas | kubectl describe pod | Profil introuvable ou syscall refusé au démarrage |
Tableau : Correspondance des numéros de syscall aux noms (x86_64)
| Numéro de syscall | Nom |
|---|---|
| 41 | socket |
| 42 | connect |
| 49 | bind |
| 50 | listen |
| 43 | accept |
| 44 | sendto |
| 45 | recvfrom |
| 51 | getsockname |
| 54 | setsockopt |
| 55 | getsockopt |
Conclusion
Résoudre les problèmes réseau liés à Seccomp dans Kubernetes nécessite une approche systématique : inventorier votre environnement, appliquer des configurations sûres, vérifier avec des commandes concrètes et être prêt à revenir en arrière. En utilisant des profils de journalisation permissifs et un durcissement progressif, vous pouvez maintenir la sécurité sans compromettre les fonctionnalités réseau. Documentez toujours vos profils et testez les changements dans des environnements isolés. Les commandes et tableaux fournis ici vous donnent une boîte à outils pratique pour diagnostiquer et résoudre les défaillances réseau courantes causées par Seccomp, garantissant que vos applications restent sécurisées et connectées.