Récemment j'ai pu lire un article intéressant sur la jungle des conteneurs qui rappelle la complexité du monde des containers et sa liste de plus en plus longue de solutions :

  • Docker,
  • Podman,
  • containerd,
  • rkt,
  • cri-o,
  • runc,
  • crun,
  • etc.

Mais finalement: Comment définir un container runtime ? Et pourquoi c'est si compliqué à expliquer ?

Container Runtime ?

Je n'ai sûrement pas la prétention de créer ma propre définition sur le sujet, alors regardons ce qui est dit et écrit ailleurs :

Dans le monde des conteneurs, la runtime est responsable de créer et de faire fonctionner le conteneur.

Mais ...

Cette définition est volontairement simpliste et très générique et on verra dans la suite de l'article qu'il existe plusieurs types de runtimes dont les objectifs sont différents et souvent complémentaires.
Source : https://blog.alterway.fr/le-point-sur-les-container-runtimes.html

Alors oui c'est flou, très flou même.

Et il faut dire que les projets associés à cet environnement ne nous aident pas :

Docker est donc un Container Runtime ?

Mais si on regarde de plus près l'architecture de Docker, on trouve deux autres container runtimes !

Pour rappel, voici l'architecture de Docker :

Architecture Docker

Docker utilise donc containerd qui va lui même utiliser runc 🤪

Et si on regarde la page du projet containerd , il se définit donc lui-même comme un container runtime :

Containerd

Mais runc aussi :

runC

J'ai donc 3 container runtimes dans une seule application pour faire tourner mes conteneurs ? Oui, il y a de quoi être perplexe!

Si nous revenons à la précédente définition d'un container runtime :

Dans le monde des conteneurs, la runtime est responsable de créer et de faire fonctionner le conteneur.

Alors dans le cas de Docker, runc est notre container runtime, puisque c'est lui qui lance les conteneurs ?

Et dieu... créa la femme ...

Et pendant ce temps, dans le monde du container on créé deux notions pour expliquer ce phénomène :

  • Les Container Runtimes Low-Level,
  • Les Container Runtimes High-Level.

Les container runtimes "bas niveau" ou Low-Level :

Les runtimes de bas niveau, sont les outils qui permettront l'exécution du conteneur au format OCI, rien de plus, rien de moins.
Source : https://catlife.drycat.fr/~/XataZ/la-jungle-des-conteneurs

Et les container runtimes "haut niveau" ou High-Level :

Some, like containerd and cri-o, actually use runc to run the container but implement image management and APIs on top. You can think of these features -- which include image transport, image management, image unpacking, and APIs -- as high-level features as compared to runc's low-level implementation.
Source : https://www.ianlewis.org/en/container-runtimes-part-1-introduction-container-r

Ian Lewis justement résume tout ceci par le schéma suivant :

Low Level vers le High Level.

Donc on a d'un côté, les container runtimes bas niveau : qui ne font qu'exécuter des containers.

Et de l'autre des container runtimes haut niveau : qui fournissent des couches d'abstractions supplémentaires, comme des API et/ou des interfaces utilisateurs, une gestion d'images ( pull/push) , etc.

Mais alors finalement, peut-on encore parler de Container Runtime dans le cas du high level ?

Container Engine

De mon côté, je préfère ne pas utiliser les termes "bas" et "haut" niveau mais plutôt faire la différence entre les Container runtimes qui vont :

  • Consuming the container mount point provided by the Container Engine (can also be a plain directory for testing)
  • Consuming the container metadata provided by the Container Engine (can be a also be a manually crafted config.json for testing)
  • Communicating with the kernel to start containerized processes (clone system call)
  • Setting up cgroups
  • Setting up SELinux Policy
  • Setting up App Armor rules

Et les Container Engines ( aussi appelés containers managers par certains ) qui vont :

  • Handling user input
  • Handling input over an API often from a Container Orchestrator
  • Pulling the Container Images from the Registry Server
  • Expanding decompressing and expanding the container image on disk using a Graph Driver (block, or file depending on driver)
  • Preparing a container mount point, typically on copy-on-write storage (again block or file depending on driver)
  • Preparing the metadata which will be passed to the container Container Runtime to start the Container correctly
  • Using some defaults from the container image (ex.ArchX86)
  • Using user input to override defaults in the container image (ex. CMD, ENTRYPOINT)
  • Using defaults specified by the container image (ex. SECCOM rules)
  • Calling the Container Runtime

Je reprends ici une définition apportée par Red Hat et Scott McCarty :

A Practical Introduction to Container Terminology

Je trouve que cette terminologie correspond bien plus à la réalité et rend le tout plus compréhensible !  


Oui le monde de la conteneurisation est une jungle ! Et ce n'est pas prêt de s'arrêter.

J'espère en tout cas vous avoir apporté quelques précisions sur le sujet ( et de la réflexion 😃 ), même si il s'agit  uniquement de mon point de vue sur le sujet !

N'hésitez pas à permettre au blog de continuer à exister et à fournir un contenu de qualité - enfin je l'espère - au travers de vos dons sur : buymeacoff.ee/lfache
Et n'hésitez pas à m'apporter des remarques ou des commentaires sur Twitter, ou ici 👇

D'autres références sur le sujet :

  • https://iximiuz.com/en/posts/journey-from-containerization-to-orchestration-and-beyond/
  • https://insujang.github.io/2019-10-31/container-runtime/#why-the-definition-becomes-unclear
  • http://crunchtools.com/so-what-does-a-container-engine-really-do-anyway/