Aide-mémoire CKAD

exemple YAML SecurityContext k8s

Linux découpe « root » en capabilities (binder :80, charger des modules, …). Ces champs les retirent au process du conteneur. drop ALL, puis add seulement ce que la question nomme.

Un vaisseau capital encaisse des tirs, le pont d’artillerie reste verrouillé. Un vaisseau capital encaisse des tirs, le pont d’artillerie reste verrouillé.
YAML
apiVersion: v1
kind: Pod
metadata:
  name: locked
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
    - name: app
      image: nginx:1.27
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]
          add: ["NET_BIND_SERVICE"]
Verrou conteneur
securityContext:
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop: ["ALL"]
    add: ["NET_BIND_SERVICE"]
Requests / limits
resources:
  requests:
    cpu: "100m"
    memory: 128Mi
  limits:
    cpu: "200m"
    memory: 256Mi

Champs

securityContext
Sur spec : qui est le process (user/group) pour chaque conteneur. Sur un conteneur : ce que ce process a le droit de faire.
runAsNonRoot
L’uid ne doit pas être 0. Échoue si l’image a USER 0 et que runAsUser n’est pas posé.
runAsUser
Uid numérique du process. À coupler avec runAsNonRoot pour que l’image ne revienne pas à 0.
fsGroup
Champ du Pod. Les fichiers des volumes prennent ce gid pour qu’un process non-root puisse les lire.
allowPrivilegeEscalation
false = le process ne peut plus gagner de privilèges ensuite (setuid vers root bloqué). Conteneur seulement.
readOnlyRootFilesystem
true = `/` est en lecture seule. Le process ne peut pas écrire dans l’image. Monter emptyDir sur /tmp s’il a besoin d’écrire.
capabilities
Tranches de root. Un conteneur démarre avec un jeu par défaut, pas zéro. drop ALL, puis add ce que la question nomme.
drop
drop : [ALL] d’abord. Ça retire NET_ADMIN, SYS_ADMIN, CHOWN — tous les pouvoirs en plus.
add
Après drop ALL, ne rendre que ça. NET_BIND_SERVICE = binder les ports < 1024 (80, 443) sans être root.
requests
Ce que le scheduler garantit. Sans ça le Pod ne démarre pas.
limits
Plafond. Au-delà de la mémoire → OOMKilled.

Pièges

  • securityContext du Pod = qui (runAsUser, fsGroup) pour chaque conteneur. Celui du conteneur = ce que le process a le droit de faire. allowPrivilegeEscalation, capabilities et readOnlyRootFilesystem sont seulement sur le conteneur — l’API les refuse sur le Pod.
  • allowPrivilegeEscalation : false — le process ne peut plus devenir plus privilégié après le démarrage. Un binaire setuid ne peut pas passer root. runAsNonRoot tout seul ne bloque pas ça.
  • readOnlyRootFilesystem : true — on ne peut pas écrire dans `/`. Le process ne peut pas poser de fichiers dans l’image. S’il a besoin de /tmp, y monter un emptyDir.
  • Les capabilities sont des tranches de root. Un conteneur démarre avec un jeu par défaut, pas zéro. drop : [ALL] les retire toutes. add : [NET_BIND_SERVICE] ne rend que « binder les ports TCP/UDP < 1024 », pour qu’un process uid 1000 puisse encore écouter sur :80.
  • runAsNonRoot: true échoue si l’image tourne en 0 et que runAsUser n’est pas posé.

Doc officielle Security Context

S’entraîner sur un cluster réel →