Linux containers the hard way Simply explained

Cette vidéo démystifie les conteneurs Linux en montrant qu’ils ne sont pas des « couches magiques » mais des processus Linux standard avec des frontières strictes, construites à partir de fonctionnalités natives du noyau comme les namespaces, les cgroups et overlayfs.

Voir la source

SYNTHÈSE STRUCTURÉE

Les conteneurs ne sont pas de la magie

L’intervenant ouvre en dénonçant une idée reçue : « It’s quite crazy to me that a lot of engineers these days still think of Docker as a bunch of layers. Like there’s some overhead. Like it’s slower than just installing something on a machine. » Il explique que sous le capot, un conteneur est un processus Linux ordinaire, mais avec des limites plus strictes. Ces limites ne sont pas des couches, mais des mécanismes intégrés au noyau. Cette clarification est cruciale pour comprendre pourquoi les fournisseurs cloud utilisent massivement les conteneurs pour leurs services managés (Lambda, bases de données, Redis cache).

Le rôle central du noyau Linux

Le noyau est l’intermédiaire entre les processus et le matériel. Quand une application a besoin de lire un fichier, elle fait un appel système (system call) au noyau. Dans un conteneur, cet appel système est le même, mais le noyau redirige la requête vers un système de fichiers spécifique, appelé « root file system » du conteneur. L’intervenant illustre cela avec deux processus : un dans un conteneur, un autre non, qui demandent le même fichier file.txt. Le premier reçoit la version du système de fichiers overlay, le second celle du disque hôte. C’est cette redirection qui crée l’isolation.

OverlayFS : la base des images conteneur

OverlayFS est un système de fichiers union mount du noyau Linux. Il permet de superposer un répertoire inférieur (lecture seule, la base image) et un répertoire supérieur (lecture/écriture, les modifications) pour présenter une vue fusionnée. L’intervenant le démontre en créant manuellement un conteneur Alpine : il télécharge le mini rootfs d’Alpine, l’extrait dans un répertoire base, puis monte le tout avec sudo mount overlay. Il précise : « The lower directory is the base layer. It’s considered read-only. Think of this as all the files in our base image. Any changes we make goes into the upper directory. » C’est exactement ce que Docker, containerd et Podman automatisent.

Namespaces : l’isolation des processus

Les namespaces sont des fonctionnalités du noyau qui isolent les ressources entre processus. L’intervenant utilise la commande unshare pour créer plusieurs namespaces : PID (pour que le processus devienne PID 1 dans le conteneur), UTS (pour un hostname personnalisé), IPC (pour l’isolation de la communication inter-processus), réseau (pour un stack réseau vide) et mount (pour changer la racine). Il explique que sans ces namespaces, un processus conteneurisé verrait tous les processus de l’hôte. Avec eux, il ne voit que lui-même et ses enfants.

chroot : verrouiller le système de fichiers

chroot (change root) est utilisé pour changer le répertoire racine d’un processus. Dans la démo, l’intervenant lance bin/sh comme processus initial du conteneur, puis utilise chroot pour que ce processus voie le système de fichiers Alpine comme sa racine. Il note que c’est une étape clé, mais que ce n’est pas suffisant pour une isolation complète : il faut aussi les namespaces et les cgroups. C’est une distinction importante pour comprendre les limites des conteneurs « faits maison ».

Cgroups : limiter les ressources

Les cgroups (control groups) permettent de limiter l’utilisation des ressources (CPU, mémoire, I/O) pour un processus ou un groupe de processus. L’intervenant montre comment créer un cgroup pour son conteneur, y appliquer une limite mémoire de 100 Mo, puis attacher le processus du conteneur à ce cgroup. Il souligne que ces limites sont appliquées par le noyau, que le processus soit dans un conteneur ou non : « Linux will terminate a process that breaches these limits, whether they’re a container or not. » C’est une garantie de stabilité pour l’hôte.

Réseau : les veth pairs et la NAT

Pour donner accès à Internet à un conteneur, il faut créer une paire d’interfaces virtuelles (veth). L’intervenant utilise ip link add pour créer veth0 sur l’hôte et veth1 dans le namespace réseau du conteneur. Il configure ensuite une adresse IP, un route par défaut et une NAT pour permettre la communication avec l’extérieur. Il visualise cela comme un « câble réseau virtuel » entre l’hôte et le conteneur. Cette étape est essentielle pour comprendre pourquoi les conteneurs ont leur propre stack réseau, avec leur propre localhost et leurs propres ports.

La démonstration pratique : un conteneur Alpine fait main

L’intervenant construit un conteneur Alpine de zéro, sans Docker ni containerd. Il montre que, une fois les namespaces, chroot, cgroups et réseau configurés, on peut installer nginx et curl dans le conteneur, puis y accéder depuis l’hôte via l’IP du conteneur. Il vérifie aussi que les modifications (nginx, curl) sont bien dans le répertoire upper de l’overlay, tandis que la base reste intacte. Cette démo illustre concrètement chaque concept et montre que les outils comme Docker ne font qu’automatiser ces étapes.

Pourquoi utiliser Docker, containerd ou Podman ?

L’intervenant conclut en expliquant que ces outils automatisent toute la complexité qu’il vient de montrer manuellement. Il insiste : « Hopefully this video helps you understand what containers really are and why it’s important to use something like Containerd, Docker or Podman because it automates a lot of this noise. » Il ajoute que cette compréhension est essentielle pour appréhender Kubernetes, notamment des concepts comme les ConfigMaps, les StatefulSets et les DaemonSets, qui reposent sur ces mécanismes sous-jacents.

CONCEPTS CLÉS

  • OverlayFS : système de fichiers union mount qui superpose des répertoires pour créer une vue fusionnée, avec une couche inférieure en lecture seule et une couche supérieure en écriture.
  • Namespaces : fonctionnalités du noyau qui isolent les ressources (PID, réseau, mount, UTS, IPC) entre processus.
  • chroot : commande qui change le répertoire racine d’un processus, le limitant à un sous-arbre du système de fichiers.
  • Cgroups : mécanisme du noyau pour limiter et monitorer l’utilisation des ressources (CPU, mémoire, I/O) d’un processus ou d’un groupe.
  • Veth pair : paire d’interfaces réseau virtuelles qui connecte un namespace réseau à un autre, souvent utilisée pour relier un conteneur à l’hôte.
  • NAT (Network Address Translation) : technique pour traduire les adresses IP privées en adresse publique, permettant aux conteneurs d’accéder à Internet.
  • Rootfs : système de fichiers racine d’un conteneur, souvent basé sur une distribution minimale comme Alpine.

CONCLUSION

Le message principal est que les conteneurs Linux ne sont pas une abstraction complexe ou lente, mais une combinaison de fonctionnalités natives du noyau (namespaces, cgroups, overlayfs) qui permettent d’isoler des processus de manière efficace et sécurisée. Comprendre ces mécanismes est crucial pour tout ingénieur qui travaille avec des conteneurs, car cela permet de mieux diagnostiquer les problèmes, d’optimiser les performances et de saisir pourquoi des outils comme Kubernetes ont été conçus avec certaines abstractions. En fin de compte, cette vidéo rappelle que la technologie repose sur des principes simples et puissants, et que les outils modernes ne font que les rendre accessibles.