docker-internals: Tuto done

This commit is contained in:
nemunaire 2022-11-27 10:56:56 +01:00
parent b0817e1011
commit 13a617ffe0
6 changed files with 56 additions and 40 deletions

View File

@ -6,7 +6,7 @@ SOURCES = tutorial.md \
tini.md \
oci.md \
runc.md \
linuxkit.md linuxkit-content.md \
linuxkit.md linuxkit-content.md linuxkit-ex-vault.md \
rendu.md

View File

@ -162,7 +162,7 @@ réutiliser plus tard ce chemin, en remplacement du mot clef `new` :
<div lang="en-US">
```yaml
- name: xxxx
image: linuxkit/xxxx:v0.8
image: linuxkit/xxxx:v1.0
net: /run/netns/mynewnetns
```
</div>
@ -263,31 +263,3 @@ une interface `virtual ethernet` :
peer: veth-db
```
</div>
::::: {.exercice}
Réalisez une recette `vault.yml` démarrant une instance du gestionnaire de
secrets [Hashicorp Vault](https://www.vaultproject.io/), utilisant une [base de
données au
choix](https://www.vaultproject.io/docs/configuration/storage/index.html)
(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*](https://github.com/opencontainers/runtime-spec/blob/master/config.md#posix-platform-hooks)
ou bien à un conteneur issu du *package*
[`ip`](https://github.com/linuxkit/linuxkit/tree/master/pkg/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](https://github.com/linuxkit/linuxkit/blob/master/examples/swap.yml)
stockées dans Vault.
:::::

View File

@ -0,0 +1,26 @@
::::: {.exercice}
Réalisez une recette `vault.yml` démarrant une instance du gestionnaire de
secrets [Hashicorp Vault](https://www.vaultproject.io/), utilisant une [base de
données au
choix](https://www.vaultproject.io/docs/configuration/storage/index.html)
(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*](https://github.com/opencontainers/runtime-spec/blob/master/config.md#posix-platform-hooks)
ou bien à un conteneur issu du *package*
[`ip`](https://github.com/linuxkit/linuxkit/tree/master/pkg/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](https://github.com/linuxkit/linuxkit/blob/master/examples/swap.yml)
stockées dans Vault.
:::::

View File

@ -83,6 +83,3 @@ Si maintenant `docker` fait appel à un programme externe pour lancer
effectivement nos conteneurs, c'est que l'on peut changer cette
implémentation ? la réponse dans l'article :\
<https://ops.tips/blog/run-docker-with-forked-runc/>
Et `containerd` dans l'histoire ?\
<https://hackernoon.com/docker-containerd-standalone-runtimes-heres-what-you-should-know-b834ef155426>

View File

@ -124,10 +124,11 @@ ajouter un élément à cette liste, demandant de *bind* :
::::: {.exercice}
À vous maintenant d'éditer votre `config.json`, pour lancer le service youp0m.
À vous maintenant d'éditer votre `config.json`, pour lancer le service `youp0m`.
Dans un premier temps, assurez-vous de pouvoir télécharger et assembler
rapidement les couches du conteneur.
rapidement les couches du conteneur (elles seront placées dans le dossier
`rootfs`).
À partir du fichier `config.json` fourni, adaptez la ligne de commande à lancer
et le dossier courant par défaut (`cwd`). Pensez également à faire un volume

View File

@ -45,7 +45,7 @@ génère beaucoup de zombies, qui vont finir par rendre la machine instable, car
le système sera à court de PID à distribuer.
On peut citer notamment la JVM, ou encore les conteneurs de construction de
logiciels (Jenkins, Drone, ...). En effet, si l'on peut blâmer les programmeurs
logiciels (Jenkins, Drone, ...). En effet, si l'on peut blâmer les programmeurs
qui oublient de `wait(2)` leurs fils directs, il peut arriver régulièrement
qu'une erreur de programmation crée des zombies dans les conteneurs de
construction. Sans processus pour les arrêter, chaque *build* risque d'ajouter
@ -82,14 +82,14 @@ d'extinction du conteneur (généralement `SIGTERM`), lorsque l'on fait un
::::: {.question}
### Ne pourrait-on pas simplement ajouter un *thread* dans Jenkins/DroneCI/... ? {-}
#### Ne pourrait-on pas simplement ajouter un *thread* dans Jenkins/DroneCI/... qui s'occupe de gérer les zombies ? {-}
\
Alors ce n'est pas vraiment une solution idéale... si Jenkins s'exécute en tant
que PID 1, il est paraît difficile de différencier les processus qui ont été
que PID 1, il paraît difficile de différencier les processus qui ont été
re-parentés à Jenkins (et sur lesquels il faut `wait(2)` directement) et ceux
qui ont été créés par Jenkins et pour lequel le code de retour est attendu par
ailleurs.
d'autres portions du code.
:::::
@ -105,7 +105,7 @@ reçoit un `SIGTERM`, celui-ci ne sera tout simplement pas traité et encore
moins transmis à ses fils, à moins d'avoir programmé un tel comportement en
shell.
Voici donc une raison supplémentaire de préférer `tini` à `bash` (ou rien du
Voici donc une raison supplémentaire de préférer `tini` à `bash` (ou à rien du
tout). D'autant plus qu'à moins d'avoir préparé la fin d'exécution, `bash` ne
retournera pas le code d'erreur de la commande que l'on a lancé, mais plutôt 0.
@ -117,3 +117,23 @@ application qui ne `fork(2)` pas n'a pas besoin de processus `init`. De même,
une image contenant un binaire qui gère correctement ses fils et qui n'a pas de
petit enfant n'aura pas besoin de `tini`. Par contre dans les autres cas, il
semble particulièrement indiqué.
L'utilisation par le paramètre `--init` du `run` n'est pas recommandée et
devrait se limiter aux cas où l'image a été construite par quelqu'un qui
n'avait pas en tête ces contraintes. Lorsque l'on sait que des zombies ne vont
pas être géré par leurs parents, le mainteneur se doit d'ajouter `tini` dans
son `Dockerfile`. La méthode recommandée est de l'installer par les paquets de
la distribution (`apt-get install tini`, `apk add tini`, ...). Néanmoins, dans
le cas d'une distribution qui ne possèderait pas le paquet, il convient
d'ajouter ces quelques lignes :
<div lang="en-US">
```
# Install tini for signal processing and zombie killing
ENV TINI_VERSION v0.18.0
RUN wget -O /usr/local/bin/tini "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini" && \
chmod +x /usr/local/bin/tini && \
tini --version
ENTRYPOINT ["/usr/local/bin/tini", ...]
```
</div>