Pods - ii02735/learn-k8 GitHub Wiki

Les pods

Qu'est-ce qu'un Pod ?

Un Pod est la plus petite unité déployable de Kubernetes. Ce n'est pas un container, mais un groupe d'un ou plusieurs containers qui partagent :

  • le réseau : une seule adresse IP, un seul espace de ports, une communication via localhost
  • les volumes : un même stockage monté dans plusieurs containers
  • l'espace de nommage IPC et le cycle de vie

Un Pod avec deux containers qui partagent le réseau et les volumes

[!IMPORTANT] Un Pod est éphémère : il est conçu pour être remplacé, pas pour durer. Si un noeud tombe, ses Pods disparaissent.

Un ou plusieurs containers ?

Dans la grande majorité des cas, un Pod contient un seul container : on parle de Pod mono-container.

On ajoute un second container uniquement quand les containers sont fortement couplés (ils doivent partager le réseau ou les données). On parle alors de Pod multi-container et de modèles (patterns) :

  • sidecar : un container auxiliaire qui assiste le container principal (collecte de logs, proxy…)
  • init container : s'exécute et se termine avant le démarrage des containers principaux
  • ambassador : un proxy qui expose le container principal vers l'extérieur
  • adapter : un adaptateur qui normalise la sortie du container principal (métriques, logs…)

:warning: Multiplier les containers dans un Pod rend le débogage plus complexe. En cas de doute, garder un container par Pod.

Pods et contrôleurs

Un Pod ne se répare pas tout seul : s'il meurt, il n'est pas recréé. C'est pour cela qu'on ne déploie presque jamais des Pods directement, mais via un contrôleur qui les gère (nombre de réplicas, redémarrage, remplacement…) :

  • Deployment : applications sans état (stateless), gère les réplicas et les mises à jour
  • ReplicaSet : maintient un nombre de Pods identiques (généralement géré par un Deployment)
  • StatefulSet : applications avec état (stateful), identité réseau et stockage stables
  • DaemonSet : un Pod sur chaque noeud (agents de logs, monitoring…)
  • Job / CronJob : tâches ponctuelles ou planifiées

Le cycle de vie d'un Pod

Un Pod est éphémère : il passe par des phases (Pending, Running, Succeeded, Failed, Unknown), expose des conditions (PodScheduled, Initialized, ContainersReady, Ready) et redémarre ses containers selon sa restartPolicy (Always, OnFailure, Never).

Pour le détail — les phases et conditions, les états des containers, les init containers, les sondes (liveness, readiness, startup) et l'arrêt gracieux — voir la page dédiée : Les sondes et le cycle de vie d'un Pod.

Les spécifications d'un Pod

Un Pod se décrit dans un manifeste YAML, principalement sous la clé spec. Voici les champs les plus utiles au niveau d'un container.

Les ports

spec:
  containers:
    - name: app
      image: nginx:1.27
      ports:
        - name: http
          containerPort: 80
          protocol: TCP
  • containerPort : le port sur lequel écoute le container. C'est une information de documentation : cela ne publie rien à l'extérieur du cluster.
  • name : nomme le port pour pouvoir le référencer (utilisé par les Services et les sondes).
  • protocol : TCP (par défaut), UDP ou SCTP.
  • hostPort : publie le port directement sur le noeud. À éviter : cela entre en conflit avec le scheduler et empêche de faire tourner plusieurs réplicas sur le même noeud.

:warning: containerPort ne suffit pas à exposer une application : c'est un Service (ou un Ingress) qui rend un Pod joignable.

La gestion des ressources

On déclare pour chaque container les ressources qu'il demande (requests) et qu'il ne peut pas dépasser (limits) :

resources:
  requests:
    cpu: "250m"
    memory: "128Mi"
  limits:
    cpu: "500m"
    memory: "256Mi"
  • requests : la quantité garantie à la planification. Le scheduler s'en sert pour choisir un noeud qui a assez de ressources libres.
  • limits : le plafond. En cas de dépassement, le CPU est bridé (throttled) et la mémoire déclenche un OOMKilled.

Les unités :

  • CPU : en coeurs (1) ou en millicoeurs (250m = 0,25 coeur).
  • Mémoire : en octets avec le suffixe binaire Mi/Gi (recommandé) ou décimal M/G.

Ces valeurs déterminent la classe de QoS du Pod :

  • Guaranteed : requests = limits pour tous les containers (la plus prioritaire)
  • Burstable : requests < limits
  • BestEffort : aucune request ni limit (la première sacrifiée en cas de pression mémoire)

[!NOTE] Si tu définis une limit sans request, Kubernetes recopie la limit dans la request.

:warning: Sans limit, un container peut épuiser la mémoire du noeud et déstabiliser les autres Pods.

Les security contexts

On peut durcir la sécurité à deux niveaux : le Pod (spec.securityContext) et chaque container (spec.containers[].securityContext).

spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
    - name: app
      image: nginx:1.27
      securityContext:
        runAsNonRoot: true
        readOnlyRootFilesystem: true
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]

Les champs les plus courants :

  • runAsUser / runAsGroup : l'UID / GID avec lequel le container s'exécute.
  • runAsNonRoot : refuse de démarrer si l'image tourne en root. Une des protections les plus efficaces.
  • fsGroup : le groupe propriétaire des volumes montés (utile pour les volumes partagés).
  • readOnlyRootFilesystem : monte le système de fichiers du container en lecture seule.
  • allowPrivilegeEscalation : empêche l'escalade de privilèges (false recommandé).
  • capabilities : ajoute ou retire des capacités Linux ; drop: ["ALL"] retire tout.
  • privileged : donne tous les droits du noeud au container — à proscrire sauf cas très particulier.

:warning: Par défaut, un container peut tourner en root. Il est recommandé de combiner runAsNonRoot: true, readOnlyRootFilesystem: true et capabilities.drop: ["ALL"].

Les sondes (probes)

Les sondes (livenessProbe, readinessProbe, startupProbe) permettent au kubelet de vérifier régulièrement l'état d'un container : en cas d'échec, il le redémarre (vitalité) ou le retire des endpoints d'un Service (disponibilité). Elles se définissent au niveau de chaque container (spec.containers[]), et non au niveau du Pod.

Pour le détail des trois types, des modes de sonde (httpGet, tcpSocket, exec, grpc), des paramètres et des bonnes pratiques : Les sondes et le cycle de vie d'un Pod.

Autres champs utiles

  • env / envFrom : variables d'environnement (directement ou depuis un ConfigMap / Secret).
  • volumeMounts : points de montage des volumes déclarés dans spec.volumes.
  • command / args : remplacent l'ENTRYPOINT / CMD de l'image.
  • imagePullPolicy : Always, IfNotPresent ou Never.

Un manifeste complet

apiVersion: v1
kind: Pod
metadata:
  name: web
  labels:
    app: web
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
    - name: app
      image: nginx:1.27
      ports:
        - name: http
          containerPort: 80
          protocol: TCP
      env:
        - name: LOG_LEVEL
          value: info
      resources:
        requests:
          cpu: "250m"
          memory: "128Mi"
        limits:
          cpu: "500m"
          memory: "256Mi"
      securityContext:
        readOnlyRootFilesystem: true
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]
      startupProbe:
        httpGet:
          path: /
          port: http
        failureThreshold: 30
        periodSeconds: 5
      livenessProbe:
        httpGet:
          path: /
          port: http
        initialDelaySeconds: 10
      readinessProbe:
        httpGet:
          path: /
          port: http

Les commandes principales

  • Lister les Pods d'un namespace : kubectl get pods
  • Voir sur quel noeud tourne chaque Pod : kubectl get pods -o wide
  • Obtenir les détails d'un Pod : kubectl describe pod web
  • Consulter les logs d'un container : kubectl logs web -c app
  • Ouvrir un shell dans un container : kubectl exec -it web -c app -- sh
  • Suivre l'état des Pods en direct : kubectl get pods --watch
  • Supprimer un Pod : kubectl delete pod web