📍 Article principal du cluster : CKS Certified Kubernetes Security Specialist — guide pratique 2026
Ce tutoriel fait partie du cluster certification CKS. Pour la vue d’ensemble, lisez d’abord le pilier.
Introduction
Les domaines 1 et 2 du syllabus CKS — Cluster Setup et Cluster Hardening — pèsent 30 % de l’examen. Ils testent votre capacité à durcir un cluster Kubernetes selon les standards de l’industrie : application du CIS Kubernetes Benchmark, audit des composants control plane et nœuds, configuration TLS exhaustive, audit logging, et restriction de l’API Kubernetes par RBAC granulaire. Ce tutoriel installe kube-bench sur un cluster kind 1.34, lit les findings CIS, corrige les paramètres kube-apiserver et kubelet pour atteindre un score satisfaisant, et active l’audit logging pour les requêtes sensibles.
Prérequis
- Cluster Kubernetes 1.34 (CKS cible cette version)
- Notions CKA — vous devez savoir ce qu’est un kube-apiserver, kubelet, etcd
- 40 minutes
Étape 1 — Préparer un cluster kind 1.34 pour CKS
Pour ce tutoriel, on monte un cluster avec un node control-plane et 2 workers, en exposant le kube-apiserver pour pouvoir y appliquer des configurations custom.
cat > /tmp/kind-cks.yaml <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraMounts:
- hostPath: /tmp/audit
containerPath: /etc/kubernetes/audit
- role: worker
- role: worker
EOF
mkdir -p /tmp/audit
kind create cluster --config /tmp/kind-cks.yaml --name cks-prep --image kindest/node:v1.34.0
kubectl get nodes
Le `extraMounts` prépare l’emplacement des fichiers d’audit logging que nous configurerons plus tard. Vérifiez que les 3 nœuds sont en `Ready` avant de continuer.
Étape 2 — Installer kube-bench sur le control plane
kube-bench est l’outil de référence pour vérifier qu’un cluster respecte le CIS Kubernetes Benchmark. Il s’exécute en Job Kubernetes ou en binaire local.
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.10.0/kube-bench_0.10.0_linux_amd64.tar.gz -o /tmp/kb.tgz
mkdir -p /tmp/kube-bench && tar -xzf /tmp/kb.tgz -C /tmp/kube-bench
docker cp /tmp/kube-bench/kube-bench cks-prep-control-plane:/usr/local/bin/
docker cp /tmp/kube-bench/cfg cks-prep-control-plane:/etc/kube-bench-cfg
# Lancer le scan sur le master
docker exec cks-prep-control-plane kube-bench run --targets master --config-dir /etc/kube-bench-cfg --benchmark cis-1.10 | head -50
La sortie liste chaque check du CIS Benchmark avec son statut : `[PASS]`, `[FAIL]`, `[WARN]`, `[INFO]`. Concentrez-vous d’abord sur les `[FAIL]` qui sont les plus critiques.
Étape 3 — Lire et interpréter les findings CIS
Chaque finding a un identifiant (ex 1.2.18), une description, et une remédiation suggérée. Les checks 1.x portent sur le control plane, les 4.x sur les nœuds workers, les 5.x sur les policies cluster-wide.
docker exec cks-prep-control-plane kube-bench run --targets master --check 1.2.18 --benchmark cis-1.10
docker exec cks-prep-control-plane kube-bench run --targets master --check 1.2.21 --benchmark cis-1.10
Pour chaque finding `[FAIL]`, lisez la section « Remediations » qui indique exactement quel paramètre modifier dans `/etc/kubernetes/manifests/kube-apiserver.yaml`. Ces remediations sont reproduites quasi à l’identique dans les questions de l’examen.
Étape 4 — Configurer kube-apiserver pour audit logging
L’audit logging est explicitement requis par plusieurs checks CIS et tombe systématiquement à l’examen CKS. On configure une politique d’audit qui logge les opérations sensibles.
cat > /tmp/audit/policy.yaml <<'EOF'
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
- level: RequestResponse
resources:
- group: ""
resources: ["pods"]
verbs: ["create", "delete", "patch"]
- level: None
users: ["system:kube-proxy"]
EOF
# Modifier kube-apiserver pour activer l'audit
docker exec cks-prep-control-plane bash -c "
sed -i '/- --advertise-address/a\ - --audit-policy-file=/etc/kubernetes/audit/policy.yaml\n - --audit-log-path=/etc/kubernetes/audit/audit.log\n - --audit-log-maxage=30' /etc/kubernetes/manifests/kube-apiserver.yaml
"
sleep 30
kubectl get pods -n kube-system | grep apiserver
ls /tmp/audit/
Une fois kube-apiserver redémarré (kubelet recharge automatiquement les manifests changeants), un fichier `audit.log` apparaît avec les entrées JSONL des requêtes. Chaque création/suppression de Pod, accès à un Secret, est tracée.
Étape 5 — Restreindre l’API par NetworkPolicy
Le kube-apiserver doit être accessible uniquement depuis les composants Kubernetes et les opérateurs autorisés. On installe Calico pour activer les NetworkPolicies (kindnet ne suffit pas) et on applique une policy restrictive sur le namespace kube-system.
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.0/manifests/calico.yaml
sleep 30
cat > /tmp/np-apiserver.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-default-ns
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: TCP
port: 6443
EOF
kubectl apply -f /tmp/np-apiserver.yaml
kubectl describe networkpolicy deny-all-default-ns
Cette NetworkPolicy bloque tout le trafic dans le namespace default sauf l’accès au kube-apiserver (port 6443) dans kube-system. Pattern fortement recommandé en production pour les namespaces applicatifs.
Étape 6 — RBAC granulaire — supprimer les permissions par défaut
Le ClusterRoleBinding `cluster-admin` lié à `system:masters` est dangereux. À l’examen, on vous demande typiquement de réduire ces permissions ou de créer un Role minimal pour un ServiceAccount.
kubectl get clusterrolebindings -o wide | grep cluster-admin
# Créer un ServiceAccount dédié pour observabilité avec permissions minimales
kubectl create sa monitor -n default
kubectl create role pod-reader --verb=get,list,watch --resource=pods
kubectl create rolebinding monitor-reader --role=pod-reader --serviceaccount=default:monitor
# Vérifier les permissions du ServiceAccount
kubectl auth can-i list pods --as=system:serviceaccount:default:monitor
kubectl auth can-i delete pods --as=system:serviceaccount:default:monitor
# get,list,watch : yes — delete : no
Le `kubectl auth can-i` est une commande à mémoriser absolument pour CKS — elle permet de vérifier les permissions effectives d’un utilisateur ou ServiceAccount sans rien exécuter. Tombe en domaine 2.
Étape 7 — Désactiver l’auto-mount du token ServiceAccount
Par défaut, chaque Pod monte automatiquement le token de son ServiceAccount dans `/var/run/secrets/kubernetes.io/serviceaccount/token`. Pour les Pods qui n’ont pas besoin de l’API Kubernetes, c’est un risque de fuite.
cat > /tmp/sa-no-token.yaml <<'EOF'
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: default
automountServiceAccountToken: false
EOF
kubectl apply -f /tmp/sa-no-token.yaml
cat > /tmp/pod-no-token.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
serviceAccountName: app-sa
automountServiceAccountToken: false
containers:
- name: app
image: nginx:1.27
EOF
kubectl apply -f /tmp/pod-no-token.yaml
kubectl exec secure-pod -- ls /var/run/secrets/kubernetes.io 2>&1 || echo "Token non monté — bonne pratique"
Le test confirme que le token n’est plus monté. Cette configuration est testée directement à l’examen — un Pod web qui ne parle pas à l’API Kubernetes ne devrait jamais avoir un token monté.
Étape 8 — Mise à jour Kubernetes et sécurité des composants
L’examen CKS demande explicitement de savoir mettre à jour un cluster Kubernetes en suivant les bonnes pratiques. Sur kind, on simule en recréant le cluster avec une nouvelle image. En production réelle, on utilise `kubeadm upgrade plan` puis `apply`.
kubectl get nodes -o wide | head -5
kubectl version
# Pour un cluster réel kubeadm :
# kubeadm upgrade plan
# kubeadm upgrade apply v1.34.1
# kubectl drain NODE && kubectl uncordon NODE
# Mise à jour kubelet et kube-proxy après control plane
Le pattern « drain → upgrade → uncordon » est testé en domaine 2. Les questions vous donnent un nœud à mettre à jour sans interruption de service — vous devez exécuter la séquence dans le bon ordre.
Comprendre la différence Pod Security Standards et PodSecurityPolicy
PodSecurityPolicy (PSP) est deprecated depuis Kubernetes 1.21 et supprimé depuis 1.25. La CKS v1.34 teste exclusivement Pod Security Standards (PSS), un modèle déclaratif basé sur trois niveaux : Privileged (aucune restriction, pour workloads système uniquement), Baseline (empêche les escalations connues), Restricted (durcissement maximal — runAsNonRoot obligatoire, capabilities drop ALL, seccomp RuntimeDefault). Les PSS sont appliqués via labels au niveau namespace : `pod-security.kubernetes.io/enforce: restricted`.
Beaucoup de candidats venant de versions plus anciennes confondent PSP et PSS. Si une question CKS mentionne PSP, c’est un faux ami — répondre PSS.
Erreurs fréquentes
| Erreur | Cause | Solution |
|---|---|---|
| Audit log non créé après modif | kubelet n’a pas rechargé le manifest | Vérifier que le fichier policy.yaml est accessible depuis le conteneur control-plane |
| NetworkPolicy ignorée | CNI ne supporte pas (kindnet) | Installer Calico ou Cilium |
| kube-bench [FAIL] sur paramètres kubelet | Configuration différente entre nœuds | Standardiser via kubelet-config ConfigMap dans kube-system |
| kubectl auth can-i renvoie no inattendu | RoleBinding sur mauvais namespace | Vérifier `–namespace` dans la commande et les RoleBindings effectifs |
| Token monté malgré automount=false | Override au niveau ServiceAccount | Configurer `automountServiceAccountToken: false` aux deux niveaux (SA et Pod) |
Adaptation au contexte ouest-africain
Pour les équipes plateforme à Dakar, Abidjan, Bamako qui opèrent des clusters Kubernetes en production réelle, l’application du CIS Benchmark est de plus en plus exigée par les audits réglementaires (BCEAO pour banques, ANSCT au Sénégal pour la cybersécurité, OHADA pour les sociétés). kube-bench est gratuit et simple à intégrer en CI — exécutez-le après chaque mise à jour Kubernetes pour détecter les régressions de configuration. Pour les clusters self-hosted sur Hostinger Cloud Startup, atteindre 80 %+ de checks PASS est un objectif réaliste en 1-2 jours d’effort.
Tutoriels frères
- Pod Security Standards et OPA Gatekeeper — politiques d’admission strictes (à venir)
- Falco runtime security — détecter les attaques en temps réel (à venir)
Pour aller plus loin
- 🔝 Retour au pilier : CKS — guide pratique 2026
- kube-bench : github.com/aquasecurity/kube-bench
- CIS Kubernetes Benchmark : cisecurity.org/benchmark/kubernetes
- Documentation audit logging : kubernetes.io/docs/tasks/debug/debug-cluster/audit
FAQ
Faut-il corriger 100 % des findings CIS ?
Non. Certains FAIL ne sont pas applicables à votre contexte (ex : checks sur etcd externe alors que vous utilisez etcd embarqué). Documenter les exceptions est valide.
Audit logging consomme-t-il beaucoup de ressources ?
À niveau Metadata uniquement, c’est négligeable. À niveau RequestResponse pour tous les pods, ça peut générer plusieurs Go/jour — surveillez et rotez les logs.
Mots-clés secondaires : kube-bench cks, cis kubernetes benchmark, audit logging k8s, networkpolicy apiserver, automount service account token, rbac granulaire