Qu’est ce qu’un plugin CRI (Container Runtime Interface) ?

Publié le

Le plugin CRI est un composant important de tous les clusters Kubernetes. Au départ, Kubernetes ne savait exécuter que des containers avec Docker. Puis, CoreOS a décidé de créer son propre runtime concurrent de Docker, c'est ainsi que rkt est apparu.

Ce runtime, très prometteur apportait des avantages par rapport à Docker, et a donc drainé une partie des utilisateurs de ce dernier. Le besoin de supporter ce runtime dans Kubernetes s'est alors fait sentir. Ce support est apparu à partir de Kubernetes 1.3.

Comme souvent dans le monde du logiciel libre, d’autres solutions ont progressivement fait surface. À l’époque on commençait à voir apparaitre CRI-O, et Frakti.

La multiplication des runtimes aurait allourdi le code de Kubelet. Il était devenu plus logique de gérer les nouveaux runtimes à partir de plugins, plutôt que directement dans Kubelet. L’interface de communication entre de tels plugins et Kubernetes s’appelle CRI (Container Runtime Interface). Cette interface est disponible depuis Kubernetes 1.5 (en alpha).

Ce changement de stratégie permet l'ajout de nouveaux runtimes plus facilement, sans avoir besoin de modifier Kubelet. Pour simplifier, on peut dire que CRI définit le protocole de communication entre un kubelet et le container runtime.

Souvent par abus de langage, on parle de « CRI », là où on devrait plutôt parler de « plugin CRI » ou de « Container Runtime ». Moi même je plaide coupable 🦹🏻‍♂️.

Comment fonctionne un plugin CRI ?

Le plugin CRI est installé au niveau des nœuds du cluster, puisque c’est eux qui vont être responsables de la gestion de bas niveau des containers. Lorsque le kube-scheduler demande à un kubelet d’exécuter une action concernant les containers, le Kubelet en question va communiquer à son tour avec le plugin au moyen d’une API basée sur protocol buffers et gRPC. Cette API est accessible par des sockets UNIX, avec containerd par exemple, c’est souvent /run/containerd/containerd.sock.

Un plugin conforme à CRI implémente deux services :

  • ImageService gère les images de containers : il permet de les récupérer (pull), les inspecter et de les supprimer.
  • RuntimeService permet de gérer tout le cycle de vie des containers sur le nœud.

Ces deux services sont accessibles par deux sockets UNIX différentes, mais comme généralement ils sont implémentés dans un seul binaire, on les retrouve dans un seul socket.

Pourquoi utiliser un plugin CRI ?

Chaque plugin implémentant CRI a ses avantages et ses inconvénients.

Au départ, la norme était Docker via dockershim. Ce composant est déprécié depuis Kubernetes 1.20 (décembre 2020) et son support serait abandonné à partir de Kubernetes 1.23 (fin 2021). Pour gérer les containers, dockershim sert d'interface pour Docker, qui lui-même utilise runc au travers de containerd. Or il est possible de supprimer un niveau d’abstraction en développant directement un plugin CRI pour containerd plutôt que de travailler avec Docker. Un tel plugin a été implémenté et fait partie des choix recommandés par les développeurs de Kubernetes.

2021-02-17-CRI-dockershim.svg
(Fonctionnement de Kubelet avec dockershim)

2021-02-17-CRI-containerd-1-0.svg
(Fonctionnement de Kubelet avec CRI-containerd 1.0 : docker n'est plus utile)

2021-02-17-CRI-containerd-1-1.svg
(Fonctionnement de Kubelet avec containerd > 1.1 : l'interface CRI est directement implémentée dans containerd)

Un concurrent prometteur à containerd est CRI-O, déjà cité sur ce blog. CRI-O est la solution par défaut dans OpenShift de RedHat (une distribution de Kubernetes) depuis sa version 4.

Ces deux plugins (containerd et CRI-O) permettent l’utilisation de containers au format OCI tout en consommant moins de resources que Docker, et en restant compatible avec celui-ci. C’est ce genre de plugin CRI qu’on mettra le plus souvent en place. À partir de Kubernetes 1.20, le runtime de choix est généralement containerd ou CRI-O.

Les configurations exotiques

Les capacités d’orchestration de Kubernetes sont très intéressantes, et il est possible de s’en servir avec des machines virtuelles. C’est le but du projet Frakti, qui depuis quelques années ne semble plus vraiment maintenu…

Par contre un autre projet qui se rapproche de Frakti est le projet Kata Containers, qui s’utilise au travers d’une configuration particulière de containerd ou CRI-O. Les Kata Containers sont compatibles avec les images OCI mais les exécutent dans des petites machines virtuelles très légères (on parle de microVMs), ce qui apporte une meilleure isolation des processus par rapport à un setup plus classique.

Le projet Kata Container n'implémente pas de plugins CRI mais un composant de plus bas niveau utilisé par ceux-ci. Dans Kubernetes, de telles charges de travail sont mises en place au travers des « runtime classes », qui définissent comment le plugin CRI doit exécuter le container : avec runc ou kata.

Conclusion

Dans la catégorie des runtimes de containers, il existe plusieurs alternatives viables à Docker. Elles se présentent sous la forme de plugins CRI, et deviennent la norme pour Kubernetes à partir de la version 1.20. Les deux principaux plugins CRI, sont containerd et CRI-O. Docker, par le biais de dockershim est maintenant déprécié, il sera donc de moins en moins visible en production dans les nouveaux clusters Kubernetes.

Resources supplémentaires

PHILIPPE CHEPY

Administrateur Système et Développeur