Sécuriser Kubernetes en Production : Checklist 2026 des 15 Erreurs Fatales
82% des clusters Kubernetes en production contiennent au moins une vulnérabilité critique exploitable (Red Hat State of Kubernetes Security 2026). Les attaques ciblant les clusters K8s ont augmenté de +350% en 2025, avec des cryptomineurs exploitant les pods mal configurés et des ransomwares chiffrant les etcd.
Kubernetes 1.32-1.35 apporte des améliorations majeures de sécurité : Pod Security Standards (PSS) remplaçant PSP deprecated, Enhanced RBAC avec fine-grained permissions, Image signing natif avec Sigstore, mais 67% des organisations n'activent pas ces protections (CNCF Survey 2026).
Cet article technique vous guide à travers les 15 erreurs fatales à éviter absolument, avec pour chacune : l'exploitation concrète, l'impact business, et la configuration sécurisée recommandée pour 2026.
Erreur #1 : Pas de RBAC ou RBAC Trop Permissif
L'Exploitation
Configuration vulnérable :
# ❌ DANGER : ClusterRoleBinding donnant cluster-admin à tous
apiVersion: rbac.authorization.k8s.io/v1
kind:ClusterRoleBinding
metadata:
name: default-admin
subjects:
kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
Attaque : 1. Attaquant compromise un pod quelconque 2. ServiceAccount default a cluster-admin 3. Attaquant peut lister tous les secrets, créer pods privilégiés, modifier etcd
Impact : Contrôle total du cluster en < 5 minutes.
Configuration Sécurisée
# ✅ Principe du moindre privilège
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-role
namespace: production
rules:
apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"] # Read-only sur pods seulement
apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-rolebinding
namespace: production
subjects:
kind: ServiceAccount
name: myapp-sa
namespace: production
roleRef:
kind: Role
name: app-role
apiGroup: rbac.authorization.k8s.io
---
# ServiceAccount dédié (pas default)
apiVersion: v1
kind: ServiceAccount
metadata:
name: myapp-sa
namespace: production
automountServiceAccountToken: false # ✅ Désactiver si pas besoin K8s API
Audit RBAC :
# Lister tous les ClusterRoleBindings dangereux
kubectl get clusterrolebindings -o json | \
jq '.items[] select(.roleRef.name=="cluster-admin") .metadata.name'
Erreur #2 : Pods Privilégiés en Production
L'Exploitation
# ❌ Pod privilégié = root sur le nœud
apiVersion: v1
kind: Pod
metadata:
name: vulnerable-pod
spec:
containers:
- name: app
image: myapp:latest
securityContext:
privileged: true # ❌ DANGER
capabilities:
add: ["SYS_ADMIN", "NET_ADMIN"]
Attaque :
# Depuis le pod privilégié
kubectl exec -it vulnerable-pod -- bash
# Accès au système de fichiers de l'hôte
ls /host/root/.ssh
cat /host/etc/shadow
Configuration Sécurisée (Pod Security Standards)
# ✅ Pod Security Standard : Restricted
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
labels:
pod-security.kubernetes.io/enforce: restricted
spec:
serviceAccountName: myapp-sa
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop: ["ALL"] # Drop toutes capabilities
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
Enforcer PSS au namespace :
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Erreur #3 : Pas de Network Policies
L'Exploitation
Sans Network Policies : Tous les pods peuvent communiquer avec tous les autres (flat network).
Attaque : 1. Compromission d'un pod frontend 2. Pivot vers base de données directement 3. Exfiltration données
Configuration Sécurisée
# ✅ Default Deny All
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# ✅ Allow Frontend → Backend seulement
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
# ✅ Allow Backend → Database seulement
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432
---
# ✅ Egress : Allow DNS + Internet HTTPS seulement
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-https
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53 # DNS
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 443 # HTTPS externe
Erreur #4 : Secrets en Plaintext dans Git/ConfigMaps
L'Exploitation
# ❌ Secret exposé dans ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_URL: "postgres://user:SuperSecret123@db:5432/mydb"
API_KEY: "sk-1234567890abcdef"
Attaque : Simple kubectl get configmap → secrets exposés.
Configuration Sécurisée
Option 1 : Sealed Secrets (Bitnami) :
# Installer Sealed Secrets Controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml
# Créer secret chiffré
echo -n "SuperSecret123" | \
kubectl create secret generic db-password --dry-run=client --from-file=password=/dev/stdin -o yaml | \
kubeseal -o yaml > sealed-secret.yaml
Option 2 : External Secrets Operator (AWS Secrets Manager, Vault) :
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: db-credentials
creationPolicy: Owner
data:
- secretKey: password
remoteRef:
key: prod/database/password
- secretKey: username
remoteRef:
key: prod/database/username
Utilisation dans Pod :
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
Erreur #5 : Images Non Signées et Non Scannées
L'Exploitation
Attaque Supply Chain : 1. Attaquant publie image malveillante nginx:latest-backdoor 2. Développeur pull l'image (typosquatting) 3. Cryptominer s'exécute sur tous les pods
Configuration Sécurisée
Image Signing avec Sigstore/Cosign :
# Signer image
cosign sign --key cosign.key myregistry.io/myapp:v1.0.0
Policy Controller (Enforce signatures) :
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: require-signed-images
spec:
images:
- glob: "myregistry.io/**"
authorities:
- keyless:
url: https://fulcio.sigstore.dev
identities:
- issuer: https://token.actions.githubusercontent.com
subject: "https://github.com/myorg/myrepo/*"
Image Scanning avec Trivy :
# Scan local
trivy image myapp:latest
Admission Controller :
# OPA Gatekeeper : Bloquer images non scannées
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: allowed-repos
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
repos:
- "myregistry.io" # Seulement registry interne
Erreur #6 : etcd Non Chiffré
L'Exploitation
# Si attaquant accède au nœud master
etcdctl get / --prefix --keys-only
Configuration Sécurisée
Chiffrement etcd at-rest :
# /etc/kubernetes/enc/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
resources:
- secrets
- configmaps
providers:
- aescbc:
keys:
- name: key1
secret:
- identity: {} # Fallback pour anciens secrets
Activer dans kube-apiserver :
# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
containers:
- command:
- kube-apiserver
- --encryption-provider-config=/etc/kubernetes/enc/encryption-config.yaml
volumeMounts:
- name: enc
mountPath: /etc/kubernetes/enc
readOnly: true
volumes:
- name: enc
hostPath:
path: /etc/kubernetes/enc
type: DirectoryOrCreate
Rotation clés :
# Générer nouvelle clé
head -c 32 /dev/urandom | base64
Erreur #7-15 : Checklist Rapide
#7 : Pas d'Audit Logs
# ✅ Activer audit
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
level: RequestResponse
verbs: ["create", "update", "patch", "delete"]
resources:
- group: ""
resources: ["secrets", "configmaps"]
#8 : Service Accounts Tokens Jamais Expirés
# ✅ Token expiration (K8s 1.32+)
apiVersion: v1
kind: ServiceAccount
metadata:
name: myapp-sa
automountServiceAccountToken: false
---
# Volume projection avec expiration
volumes:
name: sa-token
projected:
sources:
- serviceAccountToken:
expirationSeconds: 3600 # 1h
path: token
#9 : Pas de Resource Limits
# ✅ Toujours définir limits
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
#10 : Kubelet Anonymous Auth Activé
# ✅ Désactiver dans kubelet-config
anonymous-auth=false
authorization-mode=Webhook
#11 : Dashboard K8s Exposé Publiquement
# ✅ Désactiver ou restreindre
kubectl delete deployment kubernetes-dashboard -n kubernetes-dashboard
#12 : Pas de Pod Disruption Budgets
# ✅ PDB pour haute disponibilité
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: myapp
#13 : Host Path Volumes en Production
# ❌ NE JAMAIS
volumes:
name: host-data
hostPath:
path: /var/data
# ✅ Utiliser PVC
volumes:
name: data
persistentVolumeClaim:
claimName: myapp-pvc
#14 : Pas de Monitoring Sécurité
# ✅ Installer Falco
helm install falco falcosecurity/falco \
--set falco.grpc.enabled=true \
--set falco.grpc_output.enabled=true
#15 : Pas de Disaster Recovery
# ✅ Backup etcd quotidien
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%Y%m%d).db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
Scanning et Audit Automatisé
Kubescape (CNCF)
# Scan complet cluster
kubescape scan --verbose
# Frameworks spécifiques
kubescape scan framework nsa # NSA/CISA guidelines
kubescape scan framework mitre # MITRE ATT&CK
kube-bench (CIS Benchmark)
# Audit conformité CIS
kube-bench run --targets master,node,etcd,policies
Conclusion : Sécurité K8s en 2026
82% des clusters ont des vulnérabilités critiques, mais toutes sont évitables en appliquant ces 15 bonnes pratiques. La sécurité Kubernetes n'est pas une option en 2026, c'est une nécessité business avec des attaques de plus en plus sophistiquées.
Checklist minimale production :
- ✅ RBAC avec principe moindre privilège
- ✅ Pod Security Standards (Restricted)
- ✅ Network Policies (Default Deny All)
- ✅ Secrets chiffrés (Sealed Secrets/External Secrets)
- ✅ Images signées + scannées
- ✅ etcd chiffré at-rest
- ✅ Audit logs activés
- ✅ Monitoring sécurité (Falco)
Audits réguliers :
- Hebdomadaire :
kubescape scan - Mensuel :
kube-bench run - Trimestriel : Pentest externe
Pour approfondir la sécurité cloud-native, consultez nos guides sur Kubernetes pour développeurs pour les fondamentaux, ArgoCD 3.0 GitOps pour déploiements sécurisés, et sécuriser code généré par IA pour la supply chain.
Sécurité Kubernetes = RBAC + PSS + NetworkPolicies + Secrets Management + Monitoring continu.