GNU/Linux >> Tutoriels Linux >  >> Linux

Un historique des runtimes de conteneurs Linux de bas niveau

Chez Red Hat, nous aimons dire :« Les conteneurs sont Linux, Linux est des conteneurs ». Voici ce que cela signifie. Les conteneurs traditionnels sont des processus sur un système qui présentent généralement les trois caractéristiques suivantes :

1. Contraintes de ressources

Conteneurs Linux

  • Que sont les conteneurs Linux ?
  • Une introduction à la terminologie des conteneurs
  • Télécharger :Introduction aux conteneurs
  • Opérateurs Kubernetes :automatisation de la plate-forme d'orchestration de conteneurs
  • eBook :Modèles Kubernetes pour la conception d'applications cloud natives
  • Qu'est-ce que Kubernetes ?

Lorsque vous exécutez de nombreux conteneurs sur un système, vous ne souhaitez pas qu'un conteneur monopolise le système d'exploitation. Nous utilisons donc des contraintes de ressources pour contrôler des éléments tels que le processeur, la mémoire, la bande passante du réseau, etc. Le noyau Linux fournit la fonctionnalité cgroups, qui peut être configuré pour contrôler les ressources du processus de conteneur.

2. Contraintes de sécurité

Habituellement, vous ne voulez pas que vos conteneurs puissent s'attaquer les uns les autres ou attaquer le système hôte. Nous profitons de plusieurs fonctionnalités du noyau Linux pour mettre en place une séparation de sécurité, telles que SELinux, seccomp, les capacités, etc.

3. Séparation virtuelle

Les processus de conteneur ne doivent pas avoir une vue sur les processus en dehors du conteneur. Ils doivent être sur leur propre réseau. Les processus de conteneur doivent pouvoir se lier au port 80 dans différents conteneurs. Chaque conteneur a besoin d'une vue différente de son image, a besoin de son propre système de fichiers racine (rootfs). Sous Linux, nous utilisons les espaces de noms du noyau pour fournir une séparation virtuelle.

Par conséquent, un processus qui s'exécute dans un groupe de contrôle, possède des paramètres de sécurité et s'exécute dans des espaces de noms peut être appelé un conteneur. En regardant PID 1, systemd, sur un système Red Hat Enterprise Linux 7, vous voyez que systemd s'exécute dans un groupe de contrôle.

# tail -1 /proc/1/cgroup
1:name=systemd:/

Le ps La commande vous indique que le processus système a une étiquette SELinux ...

# ps -eZ | grep systemd
system_u:system_r:init_t:s0             1 ?     00:00:48 systemd

et capacités.

# grep Cap /proc/1/status
...
CapEff: 0000001fffffffff
CapBnd: 0000001fffffffff
CapBnd:    0000003fffffffff

Enfin, si vous regardez le /proc/1/ns subdir, vous verrez l'espace de noms dans lequel systemd s'exécute.

ls -l /proc/1/ns
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 net -> net:[4026532009]
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 pid -> pid:[4026531836]
...

Si le PID 1 (et vraiment tous les autres processus du système) a des contraintes de ressources, des paramètres de sécurité et des espaces de noms, je soutiens que chaque processus du système se trouve dans un conteneur.

Les outils d'exécution de conteneur modifient simplement ces contraintes de ressources, paramètres de sécurité et espaces de noms. Ensuite, le noyau Linux exécute les processus. Une fois le conteneur lancé, l'environnement d'exécution du conteneur peut surveiller le PID 1 à l'intérieur du conteneur ou le stdin du conteneur. /stdout — le runtime du conteneur gère les cycles de vie de ces processus.

Exécutions de conteneurs

Vous pourriez vous dire que bien systemd ressemble assez à un environnement d'exécution de conteneur. Eh bien, après avoir eu plusieurs discussions par e-mail sur les raisons pour lesquelles les runtimes de conteneurs n'utilisent pas systemd-nspawn en tant qu'outil de lancement de conteneurs, j'ai décidé qu'il valait la peine de discuter des durées d'exécution des conteneurs et de donner un contexte historique.

Docker est souvent appelé runtime de conteneur, mais « runtime de conteneur » est un terme surchargé. Lorsque les gens parlent d'un "environnement d'exécution de conteneur", ils parlent en réalité d'outils de niveau supérieur tels que Docker, CRI-O et RKT, qui sont fournis avec des fonctionnalités de développement. Ils sont pilotés par l'API. Ils incluent des concepts tels que l'extraction de l'image du conteneur à partir du registre de conteneurs, la configuration du stockage et enfin le lancement du conteneur. Le lancement du conteneur implique souvent l'exécution d'un outil spécialisé qui configure le noyau pour exécuter le conteneur, et ceux-ci sont également appelés "environnements d'exécution de conteneur". Je les appellerai "environnements d'exécution de conteneur de bas niveau". Les démons comme Docker et CRI-O, ainsi que les outils de ligne de commande comme Podman et Buildah, devraient plutôt être appelés "gestionnaires de conteneurs".

Lorsque Docker a été écrit à l'origine, il lançait des conteneurs en utilisant le lxc ensemble d'outils, qui est antérieur à systemd-nspawn . Le travail original de Red Hat avec Docker était d'essayer d'intégrer libvirt (libvirt-lxc ) dans Docker comme alternative au lxc outils, qui n'étaient pas pris en charge dans RHEL. libvirt-lxc n'a pas non plus utilisé systemd-nspawn . À ce moment-là, l'équipe systemd disait que systemd-nspawn n'était qu'un outil de test, pas de production.

Dans le même temps, les développeurs Docker en amont, y compris certains membres de mon équipe Red Hat, ont décidé qu'ils voulaient un moyen natif golang de lancer des conteneurs, plutôt que de lancer une application distincte. Le travail a commencé sur libcontainer, en tant que bibliothèque golang native pour lancer des conteneurs. L'ingénierie Red Hat a décidé que c'était la meilleure voie à suivre et a abandonné libvirt-lxc .

Plus tard, l'Open Container Initiative (OCI) a été formée, parti parce que les gens voulaient pouvoir lancer des conteneurs de manières supplémentaires. Les conteneurs traditionnels séparés par des espaces de noms étaient populaires, mais les gens souhaitaient également une isolation au niveau de la machine virtuelle. Intel et Hyper.sh travaillaient sur des conteneurs séparés par KVM, et Microsoft travaillait sur des conteneurs basés sur Windows. L'OCI voulait une spécification standard définissant ce qu'est un conteneur, c'est pourquoi la spécification d'exécution OCI est née.

La spécification d'exécution OCI définit un format de fichier JSON qui décrit quel binaire doit être exécuté, comment il doit être contenu et l'emplacement du rootfs du conteneur. Les outils peuvent générer ce fichier JSON. Ensuite, d'autres outils peuvent lire ce fichier JSON et exécuter un conteneur sur le rootfs. Les parties libcontainer de Docker ont été éclatées et données à l'OCI. Les ingénieurs Docker en amont et nos ingénieurs ont aidé à créer un nouvel outil frontal pour lire le fichier JSON de spécification d'exécution OCI et interagir avec libcontainer pour exécuter le conteneur. Cet outil, appelé runc , a également été reversé à l'OCI. Tant que runc peuvent lire le fichier OCI JSON, les utilisateurs doivent le générer eux-mêmes. runc est depuis devenu le runtime de conteneur de bas niveau le plus populaire. Presque tous les outils de gestion de conteneurs prennent en charge runc , y compris CRI-O, Docker, Buildah, Podman et Cloud Foundry Garden. Depuis lors, d'autres outils ont également implémenté la spécification d'exécution OCI pour exécuter des conteneurs conformes à OCI.

À la fois Clear Containers et runV d'Hyper.sh Des outils ont été créés pour utiliser la spécification d'exécution OCI pour exécuter des conteneurs basés sur KVM, et ils combinent leurs efforts dans un nouveau projet appelé Kata. L'année dernière, Oracle a créé une version de démonstration d'un outil d'exécution OCI appelé RailCar, écrit en Rust. Cela fait deux mois que le projet GitHub a été mis à jour, il n'est donc pas clair s'il est toujours en développement. Il y a quelques années, Vincent Batts a travaillé sur l'ajout d'un outil, nspawn-oci , qui a interprété un fichier OCI Runtime Specification et lancé systemd-nspawn , mais personne ne s'en est vraiment rendu compte, et ce n'était pas une implémentation native.

Si quelqu'un veut implémenter un systemd-nspawn --oci OCI-SPEC.json natif et faites-le accepter par l'équipe systemd pour l'assistance, puis CRI-O, Docker et éventuellement Podman pourront l'utiliser en plus de runc  et Clear Container/runV (Kata). (Personne dans mon équipe ne travaille dessus.)

En fin de compte, il y a trois ou quatre ans, les développeurs en amont voulaient écrire un outil golang de bas niveau pour lancer des conteneurs, et cet outil a fini par devenir runc . Ces développeurs à l'époque disposaient d'un outil basé sur C pour ce faire appelé lxc et s'en est éloigné. Je suis presque sûr qu'au moment où ils ont pris la décision de construire libcontainer, ils n'auraient pas été intéressés par systemd-nspawn ou tout autre moyen non natif (golang) d'exécuter des conteneurs séparés par "espace de noms".


Linux
  1. La commande d'historique sous Linux expliquée en profondeur

  2. 5 raisons pour lesquelles vous devriez développer une stratégie de conteneur Linux

  3. 7 fonctionnalités amusantes de conteneurs/transports d'images Linux

  4. Comment créer, répertorier et supprimer des conteneurs Docker sous Linux

  5. Commande d'historique Linux

Commande d'historique sous Linux (historique de bash)

Commande d'historique sous Linux avec des exemples

Introduction à la gestion des conteneurs Linux

Comment installer Mcfly sur Linux.

Commande d'historique sous Linux - Afficher l'historique du terminal Linux

Comment gérer les conteneurs Docker