tuto5: add part on filesystems
This commit is contained in:
parent
75c35a36d1
commit
d02f573142
8 changed files with 547 additions and 45 deletions
|
|
@ -1,6 +1,12 @@
|
|||
include ../pandoc-opts.mk
|
||||
|
||||
SOURCES = tutorial.md oci.md registry.md runc.md linuxkit.md linuxkit-content.md rendu.md
|
||||
SOURCES = tutorial.md \
|
||||
registry.md \
|
||||
../4/filesystem.md ../4/filesystem-ex.md ../4/filesystem-more.md \
|
||||
oci.md \
|
||||
runc.md \
|
||||
linuxkit.md linuxkit-content.md \
|
||||
rendu.md
|
||||
|
||||
|
||||
all: tutorial.pdf
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
## Prérequis
|
||||
|
||||
Si vous n'avez pas déjà le binaire `linuxkit`, vous pouvez télécharger ici :\
|
||||
Si vous n'avez pas déjà le binaire `linuxkit`, vous pouvez le 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 binaire[^lollibc] ;-)
|
||||
en plus du binaire[^lollibc]. Un simple `chmod +x` vous permettra de l'exécuter
|
||||
depuis n'importe quel dossier
|
||||
|
||||
[^lollibc]: à condition tout de même que vous utilisiez une libc habituelle.
|
||||
|
||||
|
|
@ -19,51 +21,77 @@ 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
|
||||
donner naissance au *rootfs* de la machine. On y place normalement qu'un
|
||||
gestionnaire de conteneurs, qui sera chargé de lancer chaque conteneur au bon
|
||||
moment ;
|
||||
- `onboot`, `onshutdown` et `services` : il s'agit de conteneurs qui seront
|
||||
lancés par le système disponible dans l'`init`, au bon moment. Les conteneurs
|
||||
indiqués dans `onboot` seront lancés **séquentiellement** au démarrage de la
|
||||
machine, ceux dans `onshutdown` seront lancés lors de l'arrêt de la
|
||||
machine. Les conteneurs dans `services` seront lancés simultanément une fois
|
||||
que le dernier conteneur de `onboot` aura rendu la main ;
|
||||
- `files` : des fichiers supplémentaires à placer dans le rootfs.
|
||||
lancés par le gestionnaire disponible dans l'`init`, au moment désigné.\ Les
|
||||
conteneurs indiqués dans `onboot` seront lancés **séquentiellement** au
|
||||
démarrage de la machine, ceux dans `onshutdown` seront lancés lors de l'arrêt
|
||||
de la machine. Les conteneurs dans `services` seront lancés simultanément une
|
||||
fois que le dernier conteneur de `onboot` aura rendu la main ;
|
||||
- `files` : des fichiers supplémentaires à placer dans le système de fichier à
|
||||
l'emplacement déterminé.
|
||||
|
||||
Le format est documenté ici :
|
||||
<https://github.com/linuxkit/linuxkit/blob/master/docs/yaml.md>
|
||||
|
||||
|
||||
## Hello?
|
||||
### Hello?
|
||||
|
||||
L'image la plus simple que l'on puisse réaliser pourrait être :
|
||||
|
||||
<div lang="en-US">
|
||||
```yaml
|
||||
kernel:
|
||||
image: linuxkit/kernel:5.10.76
|
||||
image: linuxkit/kernel:5.10.104
|
||||
cmdline: "console=tty0 console=ttyS0"
|
||||
init:
|
||||
- linuxkit/init:eb597ef74d808b5320ad1060b1620a6ac31e7ced
|
||||
- linuxkit/runc:21dbbda709ae138de0af6b0c7e4ae49525db5e88
|
||||
- linuxkit/containerd:2f0907913dd54ab5186006034eb224a0da12443e
|
||||
- linuxkit/init:8f1e6a0747acbbb4d7e24dc98f97faa8d1c6cec7
|
||||
- linuxkit/runc:f01b88c7033180d50ae43562d72707c6881904e4
|
||||
- linuxkit/containerd:de1b18eed76a266baa3092e5c154c84f595e56da
|
||||
onboot:
|
||||
- name: dhcpcd
|
||||
image: linuxkit/dhcpcd:v0.8
|
||||
image: linuxkit/dhcpcd:52d2c4df0311b182e99241cdc382ff726755c450
|
||||
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
|
||||
services:
|
||||
- name: getty
|
||||
image: linuxkit/getty:ed32c71531f5998aa510847bb07bd847492d4101
|
||||
image: linuxkit/getty:76951a596aa5e0867a38e28f0b94d620e948e3e8
|
||||
env:
|
||||
- INSECURE=true
|
||||
trust:
|
||||
org:
|
||||
- linuxkit
|
||||
```
|
||||
</div>
|
||||
|
||||
L'image `getty` est très pratique pour déboguer, car elle permet d'avoir un
|
||||
shell sur la machine !
|
||||
On retrouve nos différentes sections : `kernel` indique qu'il faut récupérer
|
||||
l'image `linuxkit/kernel` depuis le registre Docker : il ne s'agit pas d'une
|
||||
image qui sera lancé, elle est plutôt utilisée comme une archive de stockage
|
||||
pour le noyau et ses modules. LinuxKit au moment de la construction de l'image
|
||||
se chargera de placer les fichiers aux bons endroits.
|
||||
|
||||
Ensuite, nous avons une section `init` qui déclare 3 images Docker :
|
||||
- `linuxkit/init` contient les fichiers de base et un binaire `/sbin/init` qui
|
||||
servira de système d'initialisation ;
|
||||
- `linuxkit/runc` nous donnera les outils pour lancer des conteneurs ;
|
||||
- `linuxkit/containerd` apporte un daemon pour gérer les conteneurs pendant
|
||||
leur durée de vie.
|
||||
|
||||
Ces trois images ne sont pas non plus des images Docker conventionnelles, dans
|
||||
le sens où on ne peut pas les utiliser pour faire un `docker container
|
||||
run`. Elles contiennent chacune une partie de l'arborescence du système de
|
||||
fichiers, uniquement les fichiers nécessaire, en plus, au fonctionnement du
|
||||
programme qu'elles ajoutent. Les images déclarées dans la section `init` seront
|
||||
fusionnées ensemble et formeront le système de fichiers de base de notre image
|
||||
LinuxKit.
|
||||
|
||||
Enfin les sections `onboot` et `services` sont plus conventionnelles : il
|
||||
s'agit bien d'images Docker, les conteneurs seront lancés comme tel, à partir
|
||||
d'une configuration `runc` qui sera générée au moment de la construction de
|
||||
l'image LinuxKit.
|
||||
|
||||
L'image `getty` est notamment très pratique pour déboguer, car elle permet
|
||||
d'avoir un shell sur la machine !
|
||||
|
||||
::::: {.more}
|
||||
|
||||
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
|
||||
|
|
@ -74,6 +102,8 @@ la partie `init`, elle sera alors lancée comme un équivalent de
|
|||
[^infogetty]: Plus d'infos à
|
||||
<https://github.com/linuxkit/linuxkit/blob/master/pkg/getty/README.md#linuxkit-debug>
|
||||
|
||||
:::::
|
||||
|
||||
|
||||
## `namespaces`
|
||||
|
||||
|
|
@ -81,7 +111,7 @@ Chaque nouveau conteneur est donc lancé dans un espace distinct où il ne pourr
|
|||
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
|
||||
Néanmoins, contrairement à Docker qui, de base, va 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.
|
||||
|
|
@ -173,10 +203,29 @@ serveur SSH aux `services` :
|
|||
<div lang="en-US">
|
||||
```yaml
|
||||
- name: sshd
|
||||
image: linuxkit/sshd:add8c094a9a253870b0a596796628fd4ec220b70
|
||||
image: linuxkit/sshd:4696ba61c3ec091328e1c14857d77e675802342f
|
||||
binds.add:
|
||||
- /root/.ssh:/root/.ssh
|
||||
```
|
||||
</div>
|
||||
|
||||
::::: {.question}
|
||||
|
||||
#### Que fait la ligne `binds.add` ? {-}
|
||||
\
|
||||
|
||||
Avec l'instruction `binds.add`, LinuxKit va créer un *bind mount* selon le même
|
||||
principe que les volumes des conteneurs Docker. Ici nous allons partager le
|
||||
dossier `/root/.ssh` de notre image LinuxKit avec celui du conteneur `sshd`.
|
||||
\
|
||||
|
||||
Un certain nombre de *bind mounts* sont effectués par défaut. Ceux-ci sont
|
||||
déclarés dans les métadonnées des images. Pour avoir la liste, il convient de
|
||||
regarder le fichier `build.yml` de chaque image :\
|
||||
<https://github.com/linuxkit/linuxkit/blob/master/pkg/sshd/build.yml#L5>
|
||||
|
||||
:::::
|
||||
|
||||
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` :
|
||||
|
||||
|
|
@ -188,12 +237,10 @@ SSH pour se connecter. Voilà un bon début d'utilisation de la section `files`
|
|||
```
|
||||
</div>
|
||||
|
||||
Ceci va aller chercher votre clef RSA publique sur votre machine, pour
|
||||
la placer directement comme contenu du fichier `authorized_keys`.
|
||||
Ceci va aller chercher votre clef RSA publique sur votre machine, pour la
|
||||
placer directement comme contenu du fichier `authorized_keys`. À adapter en
|
||||
fonction de votre situation.
|
||||
|
||||
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 :\
|
||||
cf. <https://github.com/linuxkit/linuxkit/blob/master/pkg/sshd/build.yml#L5>
|
||||
|
||||
|
||||
## Interface réseau virtuelle
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ Formée en juin 2015, l'Open Container Initiative (OCI) a pour but d'établir le
|
|||
standard commun aux programmes de contenerisation, afin d'éviter une
|
||||
fragmentation de l'écosystème.
|
||||
|
||||
## Spécifications
|
||||
|
||||
Trois spécifications ont été écrites :
|
||||
|
||||
- [`runtime-spec`](https://github.com/opencontainers/runtime-spec/blob/master/spec.md#platforms): définis les paramètres du démarrage d'un conteneur ;
|
||||
|
|
@ -14,7 +16,7 @@ Trois spécifications ont été écrites :
|
|||
- [`distribution-spec`](https://github.com/opencontainers/distribution-spec/blob/master/spec.md): définis la manière dont sont partagées et récupérées les images.
|
||||
|
||||
|
||||
## `runtime-spec`
|
||||
### `runtime-spec`
|
||||
|
||||
`runc` est l'implémentation de cette spécification ; elle a été extraite de
|
||||
`docker`, puis donnée par Docker Inc. à l'OCI.
|
||||
|
|
@ -38,7 +40,7 @@ plus de conteneur a proprement parlé, il fait seulement en sorte d'atteindre
|
|||
l'état voulu par cette spécification, avant de passer la main à `runc`.
|
||||
|
||||
|
||||
## `image-spec`
|
||||
### `image-spec`
|
||||
|
||||
Une image OCI est composée d'un manifest, d'une suite de couches de systèmes de
|
||||
fichiers, d'une configuration ainsi qu'un index d'image optionnel.
|
||||
|
|
@ -68,14 +70,14 @@ là-dedans que finissent toutes les métadonnées que l'on inscrit dans nos
|
|||
des couches du système de fichiers, ainsi que l'historique de l'image.
|
||||
|
||||
|
||||
## `distribution-spec`
|
||||
### `distribution-spec`
|
||||
|
||||
Dernière née de l'organisme, cette spécification fédère la notion de
|
||||
*registre* : une API REST sur HTTP où l'on peut récupérer des images, mais
|
||||
aussi en envoyer.
|
||||
|
||||
|
||||
## Pour aller plus loin {-}
|
||||
### Pour aller plus loin {-}
|
||||
|
||||
Si maintenant `docker` fait appel à un programme externe pour lancer
|
||||
effectivement nos conteneurs, c'est que l'on peut changer cette
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ registre.
|
|||
Avec `jq`, on peut l'extraire grâce à :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
```
|
||||
| jq -r .token
|
||||
```
|
||||
</div>
|
||||
|
|
@ -149,7 +149,7 @@ tar xzf ${DL_LAYER} -C rootfs
|
|||
Et voilà, nous avons extrait notre première image, nous devrions pouvoir :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
```
|
||||
42sh# chroot rootfs /hello
|
||||
Hello from Docker!
|
||||
[...]
|
||||
|
|
@ -164,7 +164,7 @@ Hello from Docker!
|
|||
Réalisez un script pour automatiser l'ensemble de ces étapes :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
```
|
||||
42sh$ cd $(mktemp -d)
|
||||
|
||||
42sh$ ./registry_play library/hello-world:latest
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
\newpage
|
||||
|
||||
`runc`
|
||||
======
|
||||
------
|
||||
|
||||
`runc` est le programme qui est responsable de la création effective du
|
||||
conteneur : c'est lui qui va mettre en place toute la machinerie, les points de
|
||||
|
|
@ -18,14 +16,14 @@ Pour appréhender l'utilisation de `runc` sans l'aide de Docker, nous allons
|
|||
essayer de lancer un shell `alpine` avec un volume dans notre home.
|
||||
|
||||
|
||||
## Prérequis
|
||||
### Prérequis
|
||||
|
||||
Vous devriez avoir le binaire `runc` ou `docker-runc`. Si ce n'est pas le cas,
|
||||
vous pouvez télécharger la dernière version :
|
||||
<https://github.com/opencontainers/runc/releases>.
|
||||
|
||||
|
||||
## Extraction du rootfs
|
||||
### Extraction du rootfs
|
||||
|
||||
À l'aide du script d'extraction de registre déjà réalisé, extrayons le
|
||||
*rootfs* d'alpine : `library/alpine` dans le registre Docker.
|
||||
|
|
@ -40,7 +38,7 @@ docker image save alpine | tar xv -C rootfs
|
|||
</div>
|
||||
|
||||
|
||||
## Modèle de configuration
|
||||
### Modèle de configuration
|
||||
|
||||
L'écriture complète d'un fichier `config.json` pour `runc` est plutôt
|
||||
fastidieux et répétitif, nous allons donc gagner du temps et utiliser la
|
||||
|
|
@ -57,7 +55,7 @@ Pour savoir à quoi correspondent tous ces éléments, vous pouvez consulter :\
|
|||
|
||||
Rassurez-vous, il n'y a que très peu de champs à modifier.
|
||||
|
||||
## Test brut
|
||||
### Test brut
|
||||
|
||||
Voici comment nous pouvons tester le fonctionnement de notre *bundle* :
|
||||
|
||||
|
|
@ -87,7 +85,7 @@ virli1 12345 running /tmp/work/runctest 2012-12-12T12:12:12.123456789Z root
|
|||
</div>
|
||||
|
||||
|
||||
## Attacher notre `home`
|
||||
### Attacher notre `home`
|
||||
|
||||
Dans le modèle de `config.json`, il y a déjà de nombreux systèmes de fichiers
|
||||
qui sont montés. Nous pouvons les filtrer avec :
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue