7.7 KiB
Prérequis
Si vous n'avez pas déjà le binaire linuxkit
, vous pouvez télécharger ici :
https://github.com/linuxkit/linuxkit/releases/latest.
Notez qu'étant donné qu'il est écrit en Go, aucune dépendance n'est nécessaire en plus du binaire1 ;-)
Vous aurez également besoin de QEMU pour tester vos créations.
Structure d'un fichier linuxkit.yml
Le fichier utilisé pour construire notre image se décompose en plusieurs parties :
kernel
: il est attendu ici une image OCI contenant le nécessaire pour pouvoir utiliser un noyau : l'image du noyau, ses modules et un initramfs ;init
: l'ensemble des images OCI de cette liste seront fusionnés pour donner naissance au rootfs de la machine. On n'y place normalement qu'un gestionnaire de conteneur, qui sera chargé de lancer chaque conteneur au bon moment ;onboot
,onshutdown
etservices
: il s'agit de conteneurs qui seront lancés par le système disponible dans l'init
, au bon moment. Les conteneurs indiqués dansonboot
seront lancés séquentiellement au démarrage de la machine, ceux dansonshutdown
seront lancés lors de l'arrêt de la machine. Les conteneurs dansservices
seront lancés simultanément une fois que le dernier conteneur deonboot
aura rendu la main ;files
: des fichiers supplémentaires à placer dans le rootfs.
Le format est documenté ici.
Hello?
L'image la plus simple que l'on puisse réaliser pourrait être :
L'image getty
est très pratique pour déboguer, car elle permet d'avoir un
shell sur la machine !
On notera cependant que, positionné dans services
, le shell que nous
obtiendrons sera lui-même exécuté dans un conteneur, nous n'aurons donc pas un
accès entièrement privilégier. Pour déboguer, il faut placer cette image dans
la partie init
, elle sera alors lancée comme un équivalent de
init=/bin/sh
.2
namespaces
Chaque nouveau conteneur est donc lancé dans un espace distinct où il ne pourra pas interagir avec les autres, ou déborder s'il s'avérait qu'il expose une faille exploitable.
Néanmoins, contrairement à Docker qui va de base nous dissocier du maximum de
namespaces, linuxkit
ne le fait pas pour les namespaces net
, ipc
et
uts
. C'est-à-dire que, par défaut, la pile réseau est partagée entre tous les
conteneurs, tout comme les IPC et le nom de la machine.
Il reste possible de se dissocier également de ces namespaces, en précisant :
Ou inversement, pour persister dans le namespace initial :
Partage de namespace
Dans le cas où l'on souhaite que deux conteneurs partagent le même namespace, il faut passer le chemin vers la structure du noyau correspondante.
On commence donc d'abord par créer le nouveau namespace, en prenant soin de bind mount la structure du noyau à un emplacement connu :
À la création du namespace net
, le lien vers la structure du noyau
correspondante sera bind mount sur /run/netns/synchro
. On pourra alors
réutiliser plus tard ce chemin, en remplacement du mot clef new
:
Construction et démarrage
Toute la puissance de linuxkit
repose dans son système de construction et
surtout de lancement. En effet, il peut construire des images pour un grand
nombre de plate-forme, mais il est également possible d'utiliser les API de ces
plates-formes pour aller y lancer des instances de cette image !
Pour construire l'image faite précédemment :
Cela va générer plusieurs fichiers dont un noyau (extrait de l'image de la
partie kernel
) ainsi qu'une image. Exactement ce qu'attend QEMU ! Pour
tester, n'attendons pas davantage pour lancer :
Ajouter un service
Maintenant que notre machine fonctionne, que nous pouvons interagir avec elle,
tentons de se passer de l'interface de QEMU (option -gui
) en ajoutant un
serveur SSH aux services
:
Comme nous n'avons défini aucun mot de passe, il va falloir utiliser une clef
SSH pour se connecter. Voilà un bon début d'utilisation de la section files
:
Ceci va aller chercher votre clef RSA sur votre machine, pour la placer dans
Notons qu'il est inutile d'ajouter un bind mount du dossier .ssh
ainsi
recopié, car le package linuxkit/sshd
défini déjà cela :
pkg/sshd/build.yml#L5.
Interface réseau virtuelle
Lorsque l'on souhaite se dissocier d'un namespace net
afin de s'isoler,
mais que l'on veut tout de même pouvoir communiquer, il est nécessaire de créer
une interface virtual ethernet
:
::::: {.exercice}
Réalisez une recette vault.yml
démarrant une instance du gestionnaire de
secrets Hashicorp Vault, utilisant une base de
données au
choix
(Consul, Etcd, MySQL, Cassandra, ...).
Au démarrage, Vault devra déjà être configuré pour parler à sa base de données,
qui devra se trouver dans un conteneur isolé et non accessible d'internet. Il
faudra donc établir un lien virtual ethernet
entre les deux conteneurs ; et
ne pas oublier de le configurer (automatiquement au runtime, grâce à un
poststart
hook
ou bien à un conteneur issu du package
ip
).
Les permissions étant généralement très strictes, vous aurez sans doute besoin de les assouplir un peu en ajoutant des capabilities autorisées à vos conteneurs, sans quoi vos conteneurs risquent d'être tués prématurément.
En bonus, vous pouvez gérer la persistance des données stockées dans Vault.
:::::
-
à condition tout de même que vous utilisiez une libc habituelle. ↩︎
-
Plus d'infos à https://github.com/linuxkit/linuxkit/blob/master/pkg/getty/README.md#linuxkit-debug ↩︎