Aller au contenu

Module 4 · Gouvernance du cluster

Objectifs

  • RBAC : qui a le droit de faire quoi.
  • Ressources & quotas : requests/limits, LimitRange, ResourceQuota.
  • Placement : nodeSelector, taints/tolerations, DaemonSet.
  • Durée : ~1 h · Pré-requis : Module 3.

RBAC - Role Based Access Control

Quatre objets, deux niveaux de portée :

graph LR
    SA[ServiceAccount / User] --> RB[RoleBinding]
    RB --> R[Role]
    R --> V[Verbes sur ressources]
    SA --> CRB[ClusterRoleBinding]
    CRB --> CR[ClusterRole]
Objet Portée Rôle
Role Un namespace Liste de permissions (verbes × ressources)
ClusterRole Tout le cluster Idem, à l'échelle cluster
RoleBinding Un namespace Attribue un Role à un sujet (user/SA/group)
ClusterRoleBinding Cluster Idem à l'échelle cluster
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: lecteur-pods
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: dev
  name: antoine-lecteur
subjects:
  - kind: ServiceAccount
    name: antoine
    namespace: dev
roleRef:
  kind: Role
  name: lecteur-pods
  apiGroup: rbac.authorization.k8s.io
kubectl auth can-i get pods --as system:serviceaccount:dev:antoine -n dev   # yes
kubectl auth can-i delete pods --as system:serviceaccount:dev:antoine -n dev # no

Tu vis dedans depuis le module 0

Le RBAC n'est pas une théorie : ta sandbox elle-même repose dessus - demande au mentor de te montrer comment. La pratique du moindre privilège est approfondie au module Sécurité.

Ressources : requests, limits, quotas

resources:
  requests:        # ce que le scheduler réserve
    cpu: "100m"
    memory: "128Mi"
  limits:          # plafond ; au-delà → throttle (CPU) ou OOMKill (mémoire)
    cpu: "500m"
    memory: "256Mi"
  • requests = garanti, sert au scheduling.
  • limits = plafond. Dépasser la mémoire → le pod est OOMKilled.

Selon ce que tu déclares, Kubernetes classe le pod dans une classe QoS - visible dans le describe (ligne QoS Class) : Guaranteed (requests = limits partout), Burstable (des requests, des limits différentes) ou BestEffort (rien déclaré - premier sacrifié quand un nœud manque de mémoire). Un pod sans requests/limits, popeye te le reprochera aussi.

Les garde-fous du namespace

Sur un cluster partagé, on n'attend pas que chacun déclare bien ses ressources - on l'impose au namespace :

  • ResourceQuota plafonne la somme (CPU, mémoire, nb d'objets) de tout le namespace ;
  • LimitRange injecte des défauts (requests/limits) dans tout conteneur qui n'en déclare pas - et peut borner les valeurs permises.
kubectl get resourcequota      # k9s : :quota - la somme autorisée vs utilisée
kubectl describe quota         # le détail used / hard
kubectl get limitrange         # les défauts injectés dans les pods sans déclaration

Tu vis dessous depuis le module 0

Ta sandbox tourne sous quota (posé un cran au-dessus, sur le cluster hôte). Tu en vois la trace sur chacun de tes pods : dans un describe, l'annotation LimitRanger plugin set: cpu, memory request… montre le LimitRange en action - ton pod a reçu des requests par défaut que tu n'as jamais écrites.

Exercice - OOMKill

Déploie un pod avec limits.memory: 32Mi qui alloue 100 Mo. Observe dans k9s l'état OOMKilled et retrouve-le dans le describe.

Contrôler le placement - nodeSelector, taints & tolerations

Les requests décident si un pod peut être placé ; deux mécanismes décident :

  • nodeSelector (côté pod) : « je veux un nœud portant ce label » - nodeSelector: { disktype: ssd }.
  • Taints & tolerations (côté nœud) : un nœud taché (kubectl taint nodes n1 gpu=true:NoSchedule) repousse tous les pods… sauf ceux qui portent la toleration correspondante. C'est le miroir du nodeSelector : ici c'est le nœud qui filtre.

Le cordon d'un nœud (module 2b) n'en est qu'un cas particulier : il pose une taint spéciale qui interdit toute nouvelle planification sur le nœud. (Pour des règles plus fines, le champ affinity généralise tout ça - hors socle.)

Le placement poussé au maximum : DaemonSet

Un DaemonSet demande « un pod sur chaque nœud » - pas de replicas, le nombre suit le cluster (un nœud arrive → son pod arrive). C'est l'objet des agents : collecte de logs, métriques, réseau (le CNI lui-même tourne comme ça). Dans k9s : :ds. Tu n'en écriras probablement jamais, mais tu en croiseras dans tout cluster réel - savoir le reconnaître évite de chercher un Deployment qui n'existe pas.

Pratique

Le TP de ce module, dans le terminal de ta sandbox - une fois la lecture faite :

tp start 03-scheduling   # un pod Pending faute de mémoire : requests = réservation, pas usage
tp start ancrage-4       # en autonomie ensuite : garde-fous posés AVANT que ça coince

fais la manip puis tp check (ou tp watch pour l'auto-validation) · tp hint / tp solution si tu bloques.

Ce qu'il faut retenir

  • RBAC = verbes × ressources × sujet × portée. auth can-i pour vérifier.
  • requests/limits pilotent scheduling et stabilité (OOMKill) ; nodeSelector et taints/tolerations pilotent le placement.
  • ResourceQuota plafonne la somme d'un namespace, LimitRange impose des défauts.

Quiz éclair

Teste-toi : réponds de tête, puis déplie.

1. Comment vérifier qu'un ServiceAccount a (ou non) le droit de faire une action ?

kubectl auth can-i <verbe> <ressource> --as system:serviceaccount:<ns>:<nom> -n <ns> (répond yes/no). auth can-i --list montre tous ses droits.

2. Différence entre requests et limits ?

requests = ressources réservées (servent au scheduling). limits = plafond : dépasser la mémoire → le pod est OOMKilled, dépasser le CPU → throttling.

3. Un nœud doit n'accueillir que certains pods. Quel mécanisme ?

Une taint sur le nœud (NoSchedule) le repousse par défaut ; seuls les pods portant la toleration correspondante y sont planifiés. nodeSelector fait l'inverse (le pod choisit un nœud par label).

➡️ Suite : Module 4r - Exposer une app : le chemin d'une requête