De Docker à containerd : brève histoire des runtimes Kubernetes
Pourquoi Kubernetes a cessé de dialoguer directement avec Docker, et ce qu'est réellement containerd par rapport à lui.
Les anciens tutoriels Kubernetes supposent que Docker est le runtime de conteneurs. Les tutoriels actuels supposent containerd. Aucun n’a tort : ils décrivent des moments différents de l’histoire de Kubernetes, et comprendre ce qui a changé dissipe l’essentiel de la confusion autour de ctr, crictl, et de la raison pour laquelle docker ps ne vous montre plus rien d’utile sur un nœud de cluster.
Docker est venu en premier, et Kubernetes a été construit autour de lui
Docker a rendu les conteneurs utilisables : une CLI, un format d’image, un daemon qui exécutait tout. Les débuts de Kubernetes ont été conçus spécifiquement pour orchestrer des conteneurs Docker, et les deux étaient étroitement couplés. À mesure que Kubernetes grandissait, d’autres runtimes (rkt, entre autres) ont voulu s’intégrer aussi, ce qui impliquait que Kubernetes puisse travailler avec plus d’un runtime au lieu d’être câblé en dur à l’API de Docker.
CRI et OCI : standardiser l’interface
La réponse de Kubernetes a été la Container Runtime Interface (CRI), une API gRPC que le kubelet utilise pour dialoguer avec le runtime installé, sans code spécifique à chacun. Tout runtime qui implémente CRI peut se brancher à Kubernetes.
CRI s’appuie elle-même sur les standards de l’Open Container Initiative (OCI), une spécification que Docker a contribué à établir précisément pour que l’écosystème ne dépende pas de l’implémentation d’un seul fournisseur :
- La spécification d’image définit comment une image de conteneur est structurée et adressée, de sorte qu’une image construite par un outil puisse être exécutée par un autre.
- La spécification de runtime définit comment un conteneur doit être réellement créé et exécuté sur un hôte, jusqu’aux namespaces, aux montages et à la configuration du processus.
- La spécification de distribution (ajoutée plus tard) définit comment les images sont poussées vers un registre et récupérées depuis celui-ci.
Ensemble, CRI et OCI font qu’un runtime et un orchestrateur n’ont plus à être le même produit, ni même du même fournisseur.
Docker précède CRI, Kubernetes a donc dû faire le pont
Docker n’a pas été conçu pour parler CRI, puisque CRI n’existait pas encore à sa création, et Docker est resté le runtime dominant malgré tout. La solution de contournement de Kubernetes a été dockershim : une couche de compatibilité traduisant les appels CRI vers l’API propre à Docker, permettant au kubelet de continuer à fonctionner avec Docker sans que Docker lui-même change.
containerd était déjà à l’intérieur de Docker
Docker n’a jamais été un simple runtime. Il regroupait une CLI, un système de build, la gestion des volumes et du réseau, l’authentification et, sous tout cela, la pièce qui exécutait réellement les conteneurs : un daemon appelé containerd, posé sur le runtime bas niveau runc. containerd a été extrait comme projet à part entière et donné à la CNCF, où il a obtenu le statut graduated en 2019, et contrairement aux outils destinés aux utilisateurs de Docker, il parle CRI nativement. Voilà toute la relation en une phrase : containerd est le composant runtime qui a toujours été à l’intérieur de Docker, désormais disponible seul, et compatible CRI.
La suppression de dockershim
Maintenir une couche de traduction pour un seul runtime, alors que tous les autres parlaient directement CRI, représentait une charge continue pour un bénéfice décroissant. Kubernetes a supprimé dockershim dans la version 1.24 (2022), et avec lui la prise en charge directe de Docker comme runtime de conteneurs d’un cluster.
Cela n’a pas cassé les images existantes. Docker construisait ses images selon la spécification d’image OCI, donc tout ce qui se trouve déjà dans un registre s’exécute sur containerd exactement comme avant. Ce qui a cessé de fonctionner, c’est l’usage du Docker Engine lui-même comme ce qui exécute réellement les conteneurs sur un nœud ; les clusters ont dû passer à un runtime natif CRI tel que containerd ou CRI-O.
Ce que cela signifie quand vous êtes sur un nœud aujourd’hui
Sur un nœud moderne, docker ps n’existe pas ou n’affiche rien de pertinent, car Docker n’est plus ce qui exécute vos conteneurs. Les outils pour cela sont crictl, ctr et nerdctl, et le guide suivant de cette série explique quand utiliser chacun. Les images de conteneurs elles-mêmes, les couches applicatives réelles, ne sont en rien affectées par cette histoire ; ce qui a changé se situe entièrement dans la mécanique sous-jacente.
Guides populaires
-
Fonctionnement interne du runtime : cgroups, runc et la place de containerd Ce qui isole et limite réellement un conteneur, de la fonctionnalité du noyau jusqu'au daemon avec lequel Kubernetes dialogue. -
Les outils CLI de containerd : ctr, nerdctl et crictl Trois outils en ligne de commande, trois rôles différents : lequel choisir et quand.