From 46d1f91e0ebccd593c1e259cd241d2ce774609ee Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Tue, 30 Dec 2025 18:48:52 +0700 Subject: [PATCH 01/11] Improve and update docker-basis --- tutorial/docker-basis/first.md | 7 +- tutorial/docker-basis/installation.md | 14 ++++ tutorial/docker-basis/linking.md | 18 +++++ tutorial/docker-basis/secrets.md | 111 +++++++++++++++++++++++++- tutorial/docker-basis/volumes.md | 25 ++++++ tutorial/docker-basis/what.md | 6 +- 6 files changed, 174 insertions(+), 7 deletions(-) diff --git a/tutorial/docker-basis/first.md b/tutorial/docker-basis/first.md index 8b5a4d6..170e21c 100644 --- a/tutorial/docker-basis/first.md +++ b/tutorial/docker-basis/first.md @@ -62,6 +62,7 @@ principaux registres : - - +- (GitHub Container Registry) ::::: {.warning} @@ -155,7 +156,7 @@ registre tiers :
```bash -docker container un registry.nemunai.ie/hello-world +docker container run registry.nemunai.re/hello-world ```
@@ -164,9 +165,9 @@ nécessaire de récupérer l'image. Elle est ensuite exécutée. Vous devriez do obtenir un résultat en deux parties, similaire à la sortie suivante :
-```bash +``` Unable to find image 'registry.nemunai.re/hello-world:latest' locally -latest: Pulling from library/hello-world +latest: Pulling from hello-world 2db29710123e: Already exists Digest: sha256:7d246653d0511db2a6b2e0436cfd0e52ac8c066000264b3ce63331ac66dca625 Status: Downloaded newer image for registry.nemunai.re/hello-world:latest diff --git a/tutorial/docker-basis/installation.md b/tutorial/docker-basis/installation.md index 96264d3..c3f2bea 100644 --- a/tutorial/docker-basis/installation.md +++ b/tutorial/docker-basis/installation.md @@ -80,6 +80,12 @@ car la licence est gratuite pour un usage éducatif ou personnel. Notez que cela ne concerne pas le projet ou le binaire Docker : ceux-ci restent libres. Seules les applications Docker Desktop sont concernées. +Si vous souhaitez des alternatives libres, vous pouvez considérer : + +- **Rancher Desktop** : +- **Podman Desktop** : +- **Colima** (macOS uniquement) : + ::::: [^DockerSubscription]: @@ -175,4 +181,12 @@ Cette action n'est pas anodine d'un point de vue de la sécurité : +Les membres du groupe `docker` peuvent obtenir les privilèges root sur la +machine. Pour un environnement plus sécurisé, considérez : + +- **Docker en mode rootless** : permet d'exécuter le daemon Docker sans + privilèges root +- **Podman** : alternative à Docker fonctionnant sans daemon et sans privilèges + root par défaut + ::::: diff --git a/tutorial/docker-basis/linking.md b/tutorial/docker-basis/linking.md index 6011c3d..99f06e8 100644 --- a/tutorial/docker-basis/linking.md +++ b/tutorial/docker-basis/linking.md @@ -88,3 +88,21 @@ docker network connect NETWORK CONTAINER Lorsque plusieurs conteneurs ont rejoint un réseau utilisateur, ils peuvent mutuellement se découvrir grâce à un système de résolution de nom basé sur leur nom de conteneur. + +::::: {.question} + +#### Et l'option `--link` ? {-} + +Vous trouverez peut-être dans d'anciens tutoriels l'utilisation de l'option +`--link` pour connecter des conteneurs. Cette option est **dépréciée** depuis +Docker 1.13 et ne devrait plus être utilisée. + +Les réseaux utilisateurs (`user-defined bridge networks`) sont la méthode +recommandée pour faire communiquer des conteneurs, car ils offrent : + +- Une meilleure isolation réseau +- La découverte automatique des noms (DNS intégré) +- La possibilité de connecter/déconnecter dynamiquement des conteneurs +- Plus de flexibilité et de sécurité + +::::: diff --git a/tutorial/docker-basis/secrets.md b/tutorial/docker-basis/secrets.md index 46fcbe6..db6120c 100644 --- a/tutorial/docker-basis/secrets.md +++ b/tutorial/docker-basis/secrets.md @@ -3,4 +3,113 @@ Garder des secrets ================== -TODO +Lorsque nous déployons des applications conteneurisées, celles-ci ont souvent +besoin d'informations sensibles : mots de passe de base de données, clefs API, +certificats, tokens d'authentification, etc. La gestion de ces secrets est +cruciale pour la sécurité de nos applications. + + +## Ce qu'il ne faut pas faire + +Avant de voir les bonnes pratiques, commençons par les erreurs courantes à +éviter absolument : + +::::: {.warning} + +**Ne jamais inclure de secrets dans une image Docker !** + +Lorsque vous construisez une image avec un `Dockerfile`, tout ce qui est copié +dans l'image y reste, même si vous le supprimez dans une couche ultérieure. Les +images peuvent être inspectées, et les secrets peuvent être extraits de +l'historique des couches. + +::::: + +::::: {.warning} + +**Ne jamais passer de secrets via la ligne de commande !** + +Les arguments de la ligne de commande sont visibles via `ps`, `docker inspect`, +et sont souvent enregistrés dans l'historique du shell. + +
+```bash +# MAUVAIS EXEMPLE - À NE PAS FAIRE +docker container run -e DB_PASSWORD=monmotdepasse myapp +``` +
+ +::::: + + +## Variables d'environnement avec fichiers + +Pour éviter que les secrets n'apparaissent dans l'historique de commandes ou +dans les processus, Docker permet de charger les variables d'environnement +depuis un fichier : + +
+```bash +docker container run --env-file secrets.env myapp +``` +
+ +Le fichier `secrets.env` contiendrait : + +
+``` +DB_PASSWORD=monmotdepasse +API_KEY=ma_clef_secrete +``` +
+ +::::: {.warning} + +Pensez à ajouter ce fichier dans votre `.gitignore` ou `.dockerignore` pour éviter qu'il se retrouve accidentellement dans la nature ! + +::::: + + +## Montage de fichiers secrets + +Une approche plus sécurisée consiste à monter les secrets comme fichiers en +lecture seule dans le conteneur : + +
+```bash +docker container run \ + --mount type=bind,source=$HOME/.secrets/db_password,target=/run/secrets/db_password,readonly \ + myapp +``` +
+ +L'application peut ensuite lire le secret depuis `/run/secrets/db_password`. +Cette approche présente plusieurs avantages : + +- Les secrets ne sont pas visibles via `docker inspect` +- Les secrets peuvent avoir des permissions restrictives sur l'hôte +- Les applications peuvent être conçues pour lire les secrets depuis des + fichiers, ce qui est compatible avec les systèmes d'orchestration + + +## Docker Secrets (Docker Swarm) + +Docker propose un système de gestion de secrets natif, mais celui-ci n'est +disponible qu'en mode Swarm. + +
+```bash +# Création d'un secret (nécessite Swarm mode) +echo "monmotdepasse" | docker secret create db_password - + +# Utilisation dans un service +docker service create --secret db_password myapp +``` +
+ +Dans ce mode, les secrets sont : + +- Chiffrés pendant le transit et au repos +- Montés dans `/run/secrets/` sous forme de fichiers temporaires en RAM +- Distribués uniquement aux conteneurs qui en ont besoin +- Gérés de manière centralisée diff --git a/tutorial/docker-basis/volumes.md b/tutorial/docker-basis/volumes.md index bd7f7e2..882538a 100644 --- a/tutorial/docker-basis/volumes.md +++ b/tutorial/docker-basis/volumes.md @@ -41,6 +41,31 @@ exemple : ::::: +::::: {.question} + +Pour activer le listing de répertoires avec nginx, il faudrait créer un fichier +de configuration personnalisé avec la directive `autoindex on;` et le monter +dans le conteneur via un volume supplémentaire. + +::::: + +::::: {.question} + +#### Syntaxes `-v` et `--mount` {-} + +Vous remarquerez dans cette partie l'utilisation de deux syntaxes différentes +pour monter des volumes : + +- **`-v` ou `--volume`** : syntaxe courte et concise + (ex: `-v ~/Downloads:/usr/share/nginx/html:ro`) +- **`--mount`** : syntaxe explicite avec des paires clé-valeur + (ex: `--mount type=bind,source=...,target=...,readonly`) + +La syntaxe `--mount` est recommandée pour sa clarté, mais `-v` reste très +utilisée car plus courte. Les deux sont équivalentes en fonctionnalité. + +::::: + ## Les volumes Les volumes sont des espaces créés via Docker (il s'agit d'objets Docker). Ils diff --git a/tutorial/docker-basis/what.md b/tutorial/docker-basis/what.md index d020452..567b48b 100644 --- a/tutorial/docker-basis/what.md +++ b/tutorial/docker-basis/what.md @@ -67,13 +67,13 @@ défaut. ### Les plugins Docker L'architecture de Docker est devenue très modulable. Le projet est parti dans -de nombreuses directions, chacun voulant tirer la couverture vers soit, et +de nombreuses directions, chacun voulant tirer la couverture vers soi, et l'équipe maintenant le projet a parfois eu du mal à arbitrer les bonnes choses à ajouter ou non au projet. -Afin de palier aux besoins complémentaires, parfois accessoires, parfois +Afin de pallier aux besoins complémentaires, parfois accessoires, parfois salvateurs, un système de plugins a été intégré. Il permet d'appeler d'autres -programmes comme s'il s'agissait de composant de Docker. +programmes comme s'il s'agissait de composants de Docker. Certains plugins ajoutent des options à la ligne de commande (`docker-compose`, `docker-scan`, `docker-buildx` ...). D'autres ajoutent des typologies de From 15cc8d404c869aba115abdb1920195d114325197 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Tue, 30 Dec 2025 18:59:44 +0700 Subject: [PATCH 02/11] Improve and update docker-advanced --- tutorial/docker-advanced/compose.md | 14 +++++++------ tutorial/docker-advanced/manual.md | 10 ++++++++- tutorial/docker-advanced/rendu.md | 2 +- tutorial/docker-advanced/security.md | 31 ++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/tutorial/docker-advanced/compose.md b/tutorial/docker-advanced/compose.md index 248c23c..7a396bf 100644 --- a/tutorial/docker-advanced/compose.md +++ b/tutorial/docker-advanced/compose.md @@ -9,7 +9,6 @@ contiendra les paramètres d'exécution.
```yaml -version: "3.9" services: influxdb: ... @@ -30,11 +29,14 @@ Ce fichier est un condensé des options que nous passons habituellement au #### `version` -Notons toutefois la présence d'une ligne `version` ; il ne s'agit pas de la -version de vos conteneurs, mais de la version du format de fichier -`docker-compose` qui sera utilisé. Sans indication de version, la version -originale sera utilisée, ne vous permettant pas d'utiliser les dernières -fonctionnalités de Docker. +Le champ `version` était utilisé pour spécifier la version du format de fichier +`docker-compose`. Depuis les versions récentes de Docker Compose, ce champ est +**déprécié** et n'est plus nécessaire. Docker Compose détecte automatiquement +les fonctionnalités utilisées dans le fichier. + +Vous pouvez donc **omettre ce champ** dans vos nouveaux fichiers +`docker-compose.yml`. Si vous rencontrez d'anciens fichiers avec `version: +"3.9"` ou similaire, sachez qu'il peut être supprimé sans problème. #### `services` diff --git a/tutorial/docker-advanced/manual.md b/tutorial/docker-advanced/manual.md index 11eadfe..a63c5f9 100644 --- a/tutorial/docker-advanced/manual.md +++ b/tutorial/docker-advanced/manual.md @@ -147,6 +147,14 @@ tar xzv -C /tmp ```
+ +::::: {.more} + +Vous pouvez vérifier la dernière version disponible sur la +[page des releases](https://github.com/influxdata/telegraf/releases) +et ajuster la variable `V` en conséquence. + +::::: Puis, lançons *Telegraf* :
@@ -205,7 +213,7 @@ lancé, celui-ci va régulièrement envoyer des métriques de cette machine. ### Afficher les données collectées À vous de jouer pour lancer le conteneur -[*Chronograf*](https://store.docker.com/images/chronograf). +[*Chronograf*](https://hub.docker.com/_/chronograf). ::::: {.question} diff --git a/tutorial/docker-advanced/rendu.md b/tutorial/docker-advanced/rendu.md index f41d796..6c0cce7 100644 --- a/tutorial/docker-advanced/rendu.md +++ b/tutorial/docker-advanced/rendu.md @@ -11,7 +11,7 @@ monitoring, d'un simple :
``` -42sh$ docker-compose up +42sh$ docker compose up ```
diff --git a/tutorial/docker-advanced/security.md b/tutorial/docker-advanced/security.md index a9cb8f2..b819899 100644 --- a/tutorial/docker-advanced/security.md +++ b/tutorial/docker-advanced/security.md @@ -114,3 +114,34 @@ On peut ensuite l'appliquer à un conteneur Docker : sleep: cannot read realtime clock: Operation not permitted ```
+ + +::::: {.exercice} + +## Sécuriser la stack TICK + +Maintenant que vous connaissez les mécanismes de limitation de ressources et +de sécurisation, appliquez-les à votre stack de monitoring TICK. + +### Limites de ressources + +1. Ajoutez des limites mémoire à vos conteneurs dans le `docker-compose.yml` : + - InfluxDB : limiter à 512 Mo de RAM + - Chronograf : limiter à 256 Mo de RAM + - Telegraf : limiter à 128 Mo de RAM + +2. Configurez les partages CPU pour que : + - InfluxDB obtienne 75% des ressources CPU disponibles (768) + - Chronograf et Telegraf se partagent les 25% restants (128 chacun) + + +### Sécurité + +3. Identifiez quelles capabilities sont nécessaires pour Telegraf afin de + collecter les métriques système. + +4. Testez le lancement de vos conteneurs avec l'option `--read-only` pour le + système de fichiers. Quels volumes devez-vous ajouter pour que les + conteneurs fonctionnent correctement en lecture seule ? + +::::: From 594f853605cd54f225a97a2478d703d91ac7b933 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 31 Dec 2025 12:45:58 +0700 Subject: [PATCH 03/11] Improve dockerfiles chapter --- tutorial/dockerfiles/buildx.md | 15 +++++++++++++-- tutorial/dockerfiles/dockerfile-ex.md | 2 +- tutorial/dockerfiles/dockerfile.md | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tutorial/dockerfiles/buildx.md b/tutorial/dockerfiles/buildx.md index 0f6c35c..107fd00 100644 --- a/tutorial/dockerfiles/buildx.md +++ b/tutorial/dockerfiles/buildx.md @@ -21,11 +21,22 @@ peut-être déjà le plugin installé. Si vous n'avez pas d'erreur en exécutant vous pouvez l'installer comme ceci :
+```bash +# Pour Ubuntu/Debian +sudo apt-get install docker-buildx-plugin + +# Pour Fedora/RHEL +sudo dnf install docker-buildx-plugin ``` -V="v0.9.1" + +Alternativement, vous pouvez l'installer manuellement depuis GitHub : + +```bash +# Récupérer la dernière version depuis GitHub +BUILDX_VERSION=$(curl -s https://api.github.com/repos/docker/buildx/releases/latest | grep '"tag_name"' | cut -d'"' -f4) mkdir -p ~/.docker/cli-plugins curl -L -s -S -o ~/.docker/cli-plugins/docker-buildx \ - https://github.com/docker/buildx/releases/download/$V/buildx-$V.linux-amd64 + https://github.com/docker/buildx/releases/download/${BUILDX_VERSION}/buildx-${BUILDX_VERSION}.linux-amd64 chmod +x ~/.docker/cli-plugins/docker-buildx ```
diff --git a/tutorial/dockerfiles/dockerfile-ex.md b/tutorial/dockerfiles/dockerfile-ex.md index 675d825..c6ef51f 100644 --- a/tutorial/dockerfiles/dockerfile-ex.md +++ b/tutorial/dockerfiles/dockerfile-ex.md @@ -15,7 +15,7 @@ des instructions similaires à cela :
```dockerfile -FROM golang:1.18 +FROM golang:1 COPY . /go/src/git.nemunai.re/youp0m WORKDIR /go/src/git.nemunai.re/youp0m RUN go build -tags dev -v diff --git a/tutorial/dockerfiles/dockerfile.md b/tutorial/dockerfiles/dockerfile.md index f75d86e..a0725c2 100644 --- a/tutorial/dockerfiles/dockerfile.md +++ b/tutorial/dockerfiles/dockerfile.md @@ -201,7 +201,7 @@ COPY docker-entrypoint.d /docker-entrypoint.d ```
-Le dossier sera créé s'il n'existe pas, et le contenu du dossier source ser +Le dossier sera créé s'il n'existe pas, et le contenu du dossier source sera recopié. ::::: @@ -292,7 +292,7 @@ Par exemple, prenons le `Dockerfile` suivait :
```Dockerfile -FROM python:3.10 +FROM python:3 COPY build /usr/lib/python/grapher EXPOSE 8080 RUN pip install pillow pygal From c12f3e684b796729e5376c936605fe7fe5bb608e Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 31 Dec 2025 13:51:16 +0700 Subject: [PATCH 04/11] Improve docker-internals --- tutorial/docker-internals/registry.md | 2 +- tutorial/docker-internals/runc.md | 7 +++-- tutorial/docker-internals/setup.md | 45 ++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/tutorial/docker-internals/registry.md b/tutorial/docker-internals/registry.md index f6b0054..59a53c3 100644 --- a/tutorial/docker-internals/registry.md +++ b/tutorial/docker-internals/registry.md @@ -10,7 +10,7 @@ de nouveaux services. Dans les sections à venir, nous allons essayer de récupérer la configuration et les couches de quelques images courantes (Debian, Ubuntu, `hello-world`, ...) : dans un premier temps en nous préoccupant simplement de la couche la plus basse -(le système de baase). Puis nous verrons dans le chapitre suivant comment gérer +(le système de base). Puis nous verrons dans le chapitre suivant comment gérer les autres couches. diff --git a/tutorial/docker-internals/runc.md b/tutorial/docker-internals/runc.md index 48c5488..5918068 100644 --- a/tutorial/docker-internals/runc.md +++ b/tutorial/docker-internals/runc.md @@ -135,9 +135,12 @@ et le dossier courant par défaut (`cwd`). Pensez également à faire un volume entre un dossier de votre home (ou temporaire, peu importe), afin de pouvoir stocker les photos (dossier `/srv/images`)[^chmod]. -[^chmod]: faites attention aux droits du dossier que vous partagez. Le plus +[^chmod]: **Attention aux droits du dossier que vous partagez.** Le plus simple pour l'instant serait d'attribuer les permissions `0777` à la - source, temporairement. + source, temporairement. **AVERTISSEMENT :** les permissions `0777` donnent + un accès complet (lecture, écriture, exécution) à tous les utilisateurs du + système. **N'utilisez JAMAIS ces permissions en production** et pensez à les + révoquer après l'exercice (`chmod 755` ou `chmod 700` selon vos besoins). Pour cette étape, considérez que vous avez réussi si vous voyez s'afficher : diff --git a/tutorial/docker-internals/setup.md b/tutorial/docker-internals/setup.md index 05a05eb..c24d492 100644 --- a/tutorial/docker-internals/setup.md +++ b/tutorial/docker-internals/setup.md @@ -3,10 +3,41 @@ Mise en place ============= -* `docker-compose` -* `venv` (Python3) -* `jq` -* `runc` -* `containerd` -* `ctr` -* `linuxkit` +Les exercices suivants nécessiteront l'installation de plusieurs outils.. + +- `docker-compose` +- `venv` +- `jq` : un outil en ligne de commande pour manipuler du JSON. +- `runc` : *runtime* de bas niveau pour les conteneurs OCI. +- `containerd` : daemon de gestion de conteneurs. +- `ctr` : client en ligne de commande pour `containerd` (généralement installé avec `containerd`). + +## LinuxKit {-} + +Un outil pour construire des systèmes Linux minimaux et sécurisés. + +**Installation :** +
+```bash +wget https://github.com/linuxkit/linuxkit/releases/latest/download/linuxkit-linux-amd64 +sudo install -m 755 linuxkit-linux-amd64 /usr/local/bin/linuxkit +``` +
+ +### QEMU {-} + +Nécessaire pour tester les images LinuxKit. + +**Debian/Ubuntu :** +
+```bash +sudo apt-get install qemu-system-x86 +``` +
+ +**Arch Linux :** +
+```bash +sudo pacman -S qemu-full +``` +
From ab3341bc5417da92f063a47f8f0f932c2a5bdb62 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 31 Dec 2025 15:17:51 +0700 Subject: [PATCH 05/11] Fix and improve linux-internal part 1 --- tutorial/3/capabilities.md | 2 +- tutorial/3/cgroups.md | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tutorial/3/capabilities.md b/tutorial/3/capabilities.md index d213ef8..3b8882f 100644 --- a/tutorial/3/capabilities.md +++ b/tutorial/3/capabilities.md @@ -209,7 +209,7 @@ intervenir et par exemple les ACL POSIX[^ACLPOSIX] (espace *system*) : [^ACLPOSIX]: Les ACL POSIX sont des permissions supplémentaires qui viennent s'ajouter aux modes standards du fichier (propriétaire, groupe, reste du - monde). Avec les ACL POSIX, on peut doonner des droits à un ou plusieurs + monde). Avec les ACL POSIX, on peut donner des droits à un ou plusieurs utilisateurs ou groupe, de manière spécifique.
diff --git a/tutorial/3/cgroups.md b/tutorial/3/cgroups.md index 05f8e67..08466cd 100644 --- a/tutorial/3/cgroups.md +++ b/tutorial/3/cgroups.md @@ -331,18 +331,18 @@ quantité de ressources mises à disposition à un groupe de processus. Pour définir une limite, nous allons écrire la valeur dans le fichier correspondant à une valeur limite, comme par exemple -`memory.max_usage_in_bytes` (v1) ou `memory.max` (v2), qui limite le nombre +`memory.limit_in_bytes` (v1) ou `memory.max` (v2), qui limite le nombre d'octets que notre groupe de processus va pouvoir allouer au maximum :
``` # cgroup v1 -42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes +42sh$ cat /sys/fs/cgroup/memory/virli/memory.limit_in_bytes 0 # 0 = Aucune limite -42sh$ echo 4M > /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes +42sh$ echo 4M > /sys/fs/cgroup/memory/virli/memory.limit_in_bytes # Maintenant, la limite est à 4MB, vérifions... -42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes +42sh$ cat /sys/fs/cgroup/memory/virli/memory.limit_in_bytes 4194304 ```
@@ -372,7 +372,7 @@ limites que vous avez définies :
``` 42sh# mkdir /sys/fs/cgroup... -42sh# echo 512M > /sys/fs/cgroup.../memory.max_usage_in_bytes +42sh# echo 512M > /sys/fs/cgroup.../memory.limit_in_bytes 42sh# ./monitor group_name memhog 500 ~~~ 13595 ~~~ Current memory usage: 75194368/550502400 (13%) ~~~ 13595 ~~~ Current memory usage: 150290432/550502400 (27%) From 822dc619b8217408b35d4980d0e02baa1378d79c Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 7 Jan 2026 22:18:11 +0700 Subject: [PATCH 06/11] Add content for missing namespaces --- tutorial/4/cgroupns.md | 305 +++++++++++++++++++ tutorial/4/howto.md | 28 ++ tutorial/4/ipcns.md | 514 +++++++++++++++++++++++++++++++ tutorial/4/mountns.md | 2 +- tutorial/4/namespaces-recap.md | 532 +++++++++++++++++++++++++++++++++ tutorial/4/networkns.md | 12 +- tutorial/4/timens.md | 263 ++++++++++++++++ 7 files changed, 1650 insertions(+), 6 deletions(-) create mode 100644 tutorial/4/cgroupns.md create mode 100644 tutorial/4/ipcns.md create mode 100644 tutorial/4/namespaces-recap.md create mode 100644 tutorial/4/timens.md diff --git a/tutorial/4/cgroupns.md b/tutorial/4/cgroupns.md new file mode 100644 index 0000000..33567b1 --- /dev/null +++ b/tutorial/4/cgroupns.md @@ -0,0 +1,305 @@ +Le *namespace* `cgroup` {#cgroupns} +----------------------- + +### Introduction + +L'espace de noms `cgroup`, introduit dans Linux 4.6, permet de virtualiser la +vue d'un processus sur l'arborescence des *Control Groups*. Au sein d'un +*namespace* `cgroup`, la racine vue par le processus correspond en fait à un +sous-groupe de l'arborescence globale. + + +### Pourquoi virtualiser les *cgroups* ? + +Sans le *namespace* `cgroup`, un processus dans un conteneur pourrait : + +- Voir l'arborescence complète des *cgroups* du système hôte +- Obtenir des informations sur d'autres conteneurs +- Comprendre la structure organisationnelle du système + +Le *namespace* `cgroup` permet de : + +- Masquer l'arborescence globale des *cgroups* +- Faciliter la migration de conteneurs (l'arborescence reste cohérente) +- Renforcer l'isolation entre conteneurs + + +### Utilisation pratique + +#### Observer les *cgroups* sans isolation\ + +Commençons par observer notre position dans l'arborescence des *cgroups* : + +
+```bash +42sh$ cat /proc/self/cgroup +0::/user.slice/user-1000.slice/session-3.scope +``` +
+ +Cette ligne nous indique que nous nous trouvons dans le *cgroup* unifié +`/user.slice/user-1000.slice/session-3.scope`. + +Nous pouvons également explorer l'arborescence complète : + +
+```bash +42sh$ ls /sys/fs/cgroup/ +cgroup.controllers cpuset.cpus.effective memory.pressure +cgroup.max.depth cpuset.mems.effective sys-fs-fuse-connections.mount +cgroup.max.descendants dev-hugepages.mount sys-kernel-config.mount +cgroup.procs dev-mqueue.mount sys-kernel-debug.mount +cgroup.stat init.scope sys-kernel-tracing.mount +cgroup.subtree_control io.pressure system.slice +cgroup.threads memory.numa_stat user.slice +cpu.pressure memory.stat +``` +
+ + +#### S'isoler dans un nouveau *namespace* `cgroup`\ + +Créons maintenant un nouveau *namespace* `cgroup` : + +
+```bash +42sh$ unshare --cgroup /bin/bash + incgroupns$ cat /proc/self/cgroup + 0::/ +``` +
+ +Notre processus se voit maintenant à la racine de l'arborescence des *cgroups* ! +En réalité, il se trouve toujours au même endroit dans l'arborescence globale, +mais sa vue a été virtualisée. + +Si nous regardons le contenu de `/sys/fs/cgroup/` : + +
+```bash + incgroupns$ ls /sys/fs/cgroup/ + cgroup.controllers cgroup.threads io.pressure + cgroup.events cpu.pressure memory.numa_stat + cgroup.freeze cpu.stat memory.pressure + cgroup.max.depth cpuset.cpus memory.stat + cgroup.max.descendants cpuset.cpus.effective + cgroup.procs cpuset.mems + cgroup.stat cpuset.mems.effective + cgroup.subtree_control io.stat +``` +
+ +Nous voyons seulement notre sous-arbre, pas l'arborescence complète du système. + + +#### Créer des sous-*cgroups*\ + +Dans notre nouveau *namespace*, nous pouvons créer des sous-groupes : + +
+```bash + incgroupns$ mkdir /sys/fs/cgroup/mysubgroup + incgroupns$ ls /sys/fs/cgroup/ + cgroup.controllers cgroup.threads mysubgroup + cgroup.events cpu.pressure ... + ... +``` +
+ +Ces sous-groupes sont en réalité créés dans notre branche de l'arborescence +globale. Depuis l'extérieur du *namespace*, ils apparaîtraient sous un chemin +différent. + + +### Exemple avec Docker + +Docker utilise le *namespace* `cgroup` pour isoler la vue des *cgroups* dans +les conteneurs. Observons cela : + +
+```bash +42sh$ docker run --rm -it debian /bin/bash + indocker# cat /proc/self/cgroup + 0::/ + + indocker# ls /sys/fs/cgroup/ + cgroup.controllers cpu.max memory.events + cgroup.events cpu.pressure memory.high + cgroup.freeze cpu.stat memory.low + cgroup.kill cpu.weight memory.max + cgroup.max.depth io.max memory.min + cgroup.max.descendants io.pressure memory.numa_stat + cgroup.procs io.stat memory.oom.group + cgroup.stat io.weight memory.pressure + cgroup.subtree_control memory.current memory.stat + cgroup.threads memory.events.local memory.swap.current + cgroup.type ... +``` +
+ +Le conteneur se voit à la racine, bien qu'il soit en réalité placé dans un +sous-groupe dédié de l'arborescence globale. + + +### Vérifier la position réelle dans l'arborescence + +Depuis l'hôte, nous pouvons voir la véritable position d'un conteneur : + +
+```bash +42sh$ docker inspect mycontainer | grep -A5 CgroupParent + "CgroupParent": "", + "CgroupDriver": "systemd", + +42sh$ ps aux | grep containerd-shim +root 12345 /usr/bin/containerd-shim-runc-v2 ... + +42sh$ cat /proc/12345/cgroup +0::/system.slice/docker-abc123def456.scope +``` +
+ +Le processus du conteneur se trouve dans un sous-groupe bien spécifique, mais +grâce au *namespace* `cgroup`, il se perçoit à la racine. + + +### Combinaison avec le *namespace* `mount` + +Pour que l'isolation soit complète, il faut généralement combiner le *namespace* +`cgroup` avec le *namespace* `mount` afin de remonter `/sys/fs/cgroup` : + +
+```bash +42sh# unshare --cgroup --mount /bin/bash + incgroupns# mount -t cgroup2 none /sys/fs/cgroup + incgroupns# ls /sys/fs/cgroup/ + # Vue limitée à notre sous-arbre +``` +
+ +Sans remonter le *cgroup*, nous verrions toujours l'arborescence complète via +l'ancien point de montage. + + +### Cas d'usage + +#### Migration de conteneurs\ + +Lors de la migration d'un conteneur avec des outils comme CRIU (Checkpoint/Restore +In Userspace), le *namespace* `cgroup` garantit que l'arborescence des *cgroups* +reste cohérente du point de vue du processus, même si la structure de l'hôte +cible est différente. + + +#### Isolation de sécurité\ + +Sans *namespace* `cgroup`, un processus malveillant dans un conteneur pourrait : + +- Lire `/sys/fs/cgroup/` pour découvrir d'autres conteneurs +- Analyser les métriques d'autres processus +- Déduire des informations sur l'architecture du système + + +#### Délégation de contrôle\ + +Le *namespace* `cgroup` permet de donner à un utilisateur non-privilégié le +contrôle d'une sous-arborescence de *cgroups*, sans lui donner accès à +l'arborescence globale. + + +### Exemple en C + +Voici un exemple de création d'un *namespace* `cgroup` en C : + +
+```c +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +static int child_func(void *arg) +{ + FILE *fp; + char line[256]; + + printf("=== Dans le namespace cgroup ===\n"); + + fp = fopen("/proc/self/cgroup", "r"); + if (fp == NULL) { + perror("fopen"); + return EXIT_FAILURE; + } + + while (fgets(line, sizeof(line), fp) != NULL) { + printf(" %s", line); + } + + fclose(fp); + + return 0; +} + +#define STACK_SIZE (1024 * 1024) +static char child_stack[STACK_SIZE]; + +int main(void) +{ + pid_t pid; + FILE *fp; + char line[256]; + + printf("=== Avant le namespace cgroup ===\n"); + + fp = fopen("/proc/self/cgroup", "r"); + if (fp != NULL) { + while (fgets(line, sizeof(line), fp) != NULL) { + printf(" %s", line); + } + fclose(fp); + } + + printf("\n"); + + pid = clone(child_func, child_stack + STACK_SIZE, + CLONE_NEWCGROUP | SIGCHLD, NULL); + if (pid == -1) { + perror("clone"); + exit(EXIT_FAILURE); + } + + waitpid(pid, NULL, 0); + + return 0; +} +``` +
+ +::::: {.code} + +Pour compiler et exécuter : + +
+```bash +42sh$ gcc -o cgroup_ns_demo cgroup_ns_demo.c +42sh$ ./cgroup_ns_demo +=== Avant le namespace cgroup === + 0::/user.slice/user-1000.slice/session-3.scope + +=== Dans le namespace cgroup === + 0::/ +``` +
+ +::::: + + +### Aller plus loin {-} + +Pour plus d'informations : + +- `cgroup_namespaces(7)` - page de manuel +- [Cgroup Namespace](https://lwn.net/Articles/621006/) : +- [Control Group v2](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html) : Documentation du noyau sur cgroup v2 diff --git a/tutorial/4/howto.md b/tutorial/4/howto.md index f4e5dbf..2f6eb9b 100644 --- a/tutorial/4/howto.md +++ b/tutorial/4/howto.md @@ -121,6 +121,34 @@ pid_t pid = clone(do_execvp, // First function executed by child Dans cet exemple, le processus fils créé disposera d'un nouvel espace de noms pour les *CGroups* et disposera d'une nouvelle pile réseau. +::::: {.more} + +#### Compilation des exemples C {-} +\ + +Pour compiler les programmes C utilisant les namespaces, aucune bibliothèque +spéciale n'est requise au-delà de la bibliothèque C standard : + +
+```bash +42sh$ gcc -o mon_programme mon_programme.c +``` +
+ +Notez que certains appels système utilisés avec les namespaces nécessitent la +définition de `_GNU_SOURCE` au début du fichier source pour accéder aux +extensions GNU : + +
+```c +#define _GNU_SOURCE +#include +// ... +``` +
+ +::::: + ::::: {.question} #### Quel est le rôle du *flag* `SIGCHLD` ? {-} diff --git a/tutorial/4/ipcns.md b/tutorial/4/ipcns.md new file mode 100644 index 0000000..d5d8a62 --- /dev/null +++ b/tutorial/4/ipcns.md @@ -0,0 +1,514 @@ +Le *namespace* `IPC` {#ipc-ns} +------------------- + +### Introduction + +L'espace de noms `IPC`, introduit dans Linux 2.6.19, isole les objets de +communication inter-processus (IPC) System V et les files de messages POSIX. + +Les objets isolés incluent : + +- Les files de messages System V (`msgget`, `msgsnd`, `msgrcv`) +- Les sémaphores System V (`semget`, `semop`) +- Les segments de mémoire partagée System V (`shmget`, `shmat`) +- Les files de messages POSIX (`mq_open`, `mq_send`, `mq_receive`) + +Une fois dans un *namespace* IPC différent, un processus ne peut communiquer +qu'avec les processus du même *namespace* via ces mécanismes IPC. + + +### Pourquoi isoler les IPC ? + +Sans isolation IPC, des processus dans différents conteneurs pourraient : + +- Communiquer entre eux via des files de messages partagées +- Accéder à la mémoire partagée d'autres conteneurs +- Interférer avec les sémaphores d'autres applications + +L'isolation IPC garantit que chaque conteneur dispose de son propre ensemble +d'objets IPC, renforçant ainsi la sécurité et l'isolation. + + +### Utilisation pratique + +#### Observer les objets IPC du système\ + +La commande `ipcs` permet de lister tous les objets IPC du système : + +
+```bash +42sh$ ipcs + +------ Message Queues -------- +key msqid owner perms used-bytes messages + +------ Shared Memory Segments -------- +key shmid owner perms bytes nattch status +0x00000000 32768 alice 600 524288 2 dest + +------ Semaphore Arrays -------- +key semid owner perms nsems +0x12345678 0 bob 666 1 +``` +
+ +Cette commande nous montre tous les objets IPC visibles dans notre *namespace* +actuel. + + +#### Créer une file de messages System V\ + +Créons d'abord une file de messages dans notre *namespace* initial : + +
+```c +// ipc_create.c +#include +#include +#include +#include + +int main(void) +{ + key_t key; + int msgid; + + // Créer une clé unique + key = ftok("/tmp", 'A'); + if (key == -1) { + perror("ftok"); + exit(EXIT_FAILURE); + } + + // Créer une file de messages + msgid = msgget(key, 0666 | IPC_CREAT); + if (msgid == -1) { + perror("msgget"); + exit(EXIT_FAILURE); + } + + printf("File de messages créée avec l'ID : %d\n", msgid); + printf("Clé : 0x%08x\n", key); + + return 0; +} +``` +
+ +::::: {.code} + +Compilation et exécution : + +
+```bash +42sh$ gcc -o ipc_create ipc_create.c +42sh$ touch /tmp/ipc_key_file +42sh$ ./ipc_create +File de messages créée avec l'ID : 0 +Clé : 0x41000001 + +42sh$ ipcs -q +------ Message Queues -------- +key msqid owner perms used-bytes messages +0x41000001 0 alice 666 0 0 +``` +
+ +::::: + + +#### S'isoler dans un nouveau *namespace* IPC\ + +Maintenant, créons un nouveau *namespace* IPC : + +
+```bash +42sh$ unshare --ipc /bin/bash + inipcns$ ipcs -q + ------ Message Queues -------- + key msqid owner perms used-bytes messages +``` +
+ +Notre nouveau *namespace* ne contient aucun objet IPC ! La file de messages +créée précédemment n'est pas visible ici. + +Si nous créons une nouvelle file de messages dans ce *namespace* : + +
+```bash + inipcns$ ./ipc_create + File de messages créée avec l'ID : 0 + Clé : 0x41000001 + + inipcns$ ipcs -q + ------ Message Queues -------- + key msqid owner perms used-bytes messages + 0x41000001 0 alice 666 0 0 +``` +
+ +Cette nouvelle file a le même ID (0) et la même clé que celle créée dans le +*namespace* initial, mais il s'agit d'un objet complètement distinct. + + +#### Communication entre processus dans le même *namespace*\ + +Créons un exemple de communication par file de messages : + +
+```c +// ipc_send.c +#include +#include +#include +#include +#include + +struct message { + long mtype; + char mtext[100]; +}; + +int main(void) +{ + key_t key; + int msgid; + struct message msg; + + key = ftok("/tmp", 'A'); + msgid = msgget(key, 0666 | IPC_CREAT); + + msg.mtype = 1; + snprintf(msg.mtext, sizeof(msg.mtext), "Hello from PID %d", getpid()); + + if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) { + perror("msgsnd"); + exit(EXIT_FAILURE); + } + + printf("Message envoyé : %s\n", msg.mtext); + + return 0; +} +``` +
+ +
+```c +// ipc_receive.c +#include +#include +#include +#include + +struct message { + long mtype; + char mtext[100]; +}; + +int main(void) +{ + key_t key; + int msgid; + struct message msg; + + key = ftok("/tmp", 'A'); + msgid = msgget(key, 0666 | IPC_CREAT); + + if (msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0) == -1) { + perror("msgrcv"); + exit(EXIT_FAILURE); + } + + printf("Message reçu : %s\n", msg.mtext); + + return 0; +} +``` +
+ +::::: {.code} + +Compilation : + +
+```bash +42sh$ gcc -o ipc_send ipc_send.c +42sh$ gcc -o ipc_receive ipc_receive.c +``` +
+ +Test dans le même *namespace* : + +
+```bash +# Terminal 1 +42sh$ ./ipc_receive +# Attend un message... + +# Terminal 2 +42sh$ ./ipc_send +Message envoyé : Hello from PID 12345 + +# Terminal 1 reçoit : +Message reçu : Hello from PID 12345 +``` +
+ +::::: + + +#### Isolation entre *namespaces*\ + +Maintenant, testons avec deux *namespaces* IPC différents : + +
+```bash +# Terminal 1 - namespace IPC A +42sh$ unshare --ipc /bin/bash + ipcns-A$ ./ipc_receive + # Attend un message... + +# Terminal 2 - namespace IPC B (différent) +42sh$ unshare --ipc /bin/bash + ipcns-B$ ./ipc_send + Message envoyé : Hello from PID 23456 + +# Terminal 1 ne reçoit RIEN car les namespaces sont différents +``` +
+ +Les deux processus utilisent la même clé IPC, mais comme ils sont dans des +*namespaces* différents, ils ne peuvent pas communiquer. + + +### Exemple avec la mémoire partagée + +Voici un exemple utilisant la mémoire partagée System V : + +
+```c +// shm_demo.c +#include +#include +#include +#include +#include +#include + +int main(void) +{ + key_t key; + int shmid; + char *data; + + // Créer une clé + key = ftok("/tmp", 'S'); + + // Créer un segment de mémoire partagée de 1024 octets + shmid = shmget(key, 1024, 0644 | IPC_CREAT); + if (shmid == -1) { + perror("shmget"); + exit(EXIT_FAILURE); + } + + // Attacher le segment + data = shmat(shmid, NULL, 0); + if (data == (char *)(-1)) { + perror("shmat"); + exit(EXIT_FAILURE); + } + + printf("Segment de mémoire partagée attaché\n"); + printf("Écriture dans la mémoire partagée...\n"); + + sprintf(data, "Hello from PID %d in namespace", getpid()); + + printf("Contenu : %s\n", data); + printf("Appuyez sur Entrée pour détacher...\n"); + getchar(); + + // Détacher + shmdt(data); + + printf("Voulez-vous supprimer le segment ? (o/n) : "); + char choice = getchar(); + if (choice == 'o' || choice == 'O') { + shmctl(shmid, IPC_RMID, NULL); + printf("Segment supprimé\n"); + } + + return 0; +} +``` +
+ +::::: {.code} + +Compilation et test : + +
+```bash +42sh$ gcc -o shm_demo shm_demo.c + +# Dans le namespace initial +42sh$ ./shm_demo & +Segment de mémoire partagée attaché +Écriture dans la mémoire partagée... +Contenu : Hello from PID 12345 in namespace + +42sh$ ipcs -m +------ Shared Memory Segments -------- +key shmid owner perms bytes nattch status +0x53000001 0 alice 644 1024 1 + +# Dans un nouveau namespace IPC +42sh$ unshare --ipc /bin/bash + inipcns$ ipcs -m + ------ Shared Memory Segments -------- + key shmid owner perms bytes nattch status + + # Aucun segment visible ! +``` +
+ +::::: + + +### Files de messages POSIX + +Le *namespace* IPC isole également les files de messages POSIX (qui sont +différentes des files System V) : + +
+```c +// mqueue_demo.c +#include +#include +#include +#include +#include + +int main(void) +{ + mqd_t mq; + struct mq_attr attr; + char buffer[1024]; + + // Configurer les attributs de la file + attr.mq_flags = 0; + attr.mq_maxmsg = 10; + attr.mq_msgsize = 1024; + attr.mq_curmsgs = 0; + + // Créer ou ouvrir une file de messages POSIX + mq = mq_open("/myqueue", O_CREAT | O_RDWR, 0644, &attr); + if (mq == (mqd_t)-1) { + perror("mq_open"); + exit(EXIT_FAILURE); + } + + printf("File de messages POSIX créée : /myqueue\n"); + + // Envoyer un message + sprintf(buffer, "Hello from PID %d", getpid()); + if (mq_send(mq, buffer, strlen(buffer) + 1, 0) == -1) { + perror("mq_send"); + exit(EXIT_FAILURE); + } + + printf("Message envoyé : %s\n", buffer); + + // Recevoir le message + if (mq_receive(mq, buffer, 1024, NULL) == -1) { + perror("mq_receive"); + exit(EXIT_FAILURE); + } + + printf("Message reçu : %s\n", buffer); + + mq_close(mq); + mq_unlink("/myqueue"); + + return 0; +} +``` +
+ +::::: {.code} + +Pour compiler (nécessite la bibliothèque `librt`) : + +
+```bash +42sh$ gcc -o mqueue_demo mqueue_demo.c -lrt +42sh$ ./mqueue_demo +File de messages POSIX créée : /myqueue +Message envoyé : Hello from PID 12345 +Message reçu : Hello from PID 12345 +``` +
+ +Les files de messages POSIX peuvent être listées dans `/dev/mqueue/` : + +
+```bash +42sh$ ls -l /dev/mqueue/ +total 0 +-rw-r--r-- 1 alice alice 80 Nov 15 10:30 myqueue +``` +
+ +Dans un nouveau *namespace* IPC, ce répertoire sera vide. + +::::: + + +### Combinaison avec d'autres *namespaces* + +En pratique, le *namespace* IPC est souvent combiné avec d'autres *namespaces* +pour une isolation complète : + +
+```bash +42sh# unshare --ipc --pid --mount --fork --mount-proc /bin/bash + incontainer# # Conteneur isolé avec IPC, PID et mount namespaces +``` +
+ + +### Nettoyage des objets IPC + +Les objets IPC persistent généralement après la terminaison des processus qui +les ont créés. Pour les nettoyer : + +
+```bash +# Supprimer une file de messages +42sh$ ipcrm -q + +# Supprimer un segment de mémoire partagée +42sh$ ipcrm -m + +# Supprimer un sémaphore +42sh$ ipcrm -s + +# Ou supprimer par clé +42sh$ ipcrm -Q 0x41000001 +``` +
+ +Lorsqu'un *namespace* IPC est détruit (tous les processus terminés), tous ses +objets IPC sont automatiquement nettoyés. + + +### Aller plus loin {-} + +Pour plus d'informations : + +- `ipc_namespaces(7)` - page de manuel +- `ipcs(1)` - lister les objets IPC +- `ipcrm(1)` - supprimer les objets IPC +- `svipc(7)` - aperçu de System V IPC +- `mq_overview(7)` - aperçu des files de messages POSIX diff --git a/tutorial/4/mountns.md b/tutorial/4/mountns.md index 4fa7f09..acf7816 100644 --- a/tutorial/4/mountns.md +++ b/tutorial/4/mountns.md @@ -189,7 +189,7 @@ On considère préalablement que l'environnement est propice à la réalisation ``` 42sh# mkdir -p /mnt/newroot 42sh# mount -t tmpfs none /mnt/newroot -42sh# wget https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-minirootfs-3.14.8-x86_64.tar.gz +42sh# wget https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/alpine-minirootfs-3.20.3-x86_64.tar.gz 42sh# tar xpf alpine-minirootfs-*.tar.gz -C /mnt/newroot 42sh# cd / ``` diff --git a/tutorial/4/namespaces-recap.md b/tutorial/4/namespaces-recap.md new file mode 100644 index 0000000..6267dbb --- /dev/null +++ b/tutorial/4/namespaces-recap.md @@ -0,0 +1,532 @@ +\newpage + +Récapitulatif des *namespaces* +=============================== + +Nous venons d'explorer en détail les huit types d'espaces de noms disponibles +dans le noyau Linux. Avant de conclure cette partie, récapitulons les concepts +clés et les meilleures pratiques pour utiliser efficacement ces mécanismes +d'isolation. + + +## Tableau comparatif des *namespaces* + +Le tableau suivant résume les caractéristiques principales de chaque type +d'espace de noms : + +| *Namespace* | Flag `clone()` | Depuis | Isole | Privilèges requis* | +|-------------|----------------|--------|-------|-------------------| +| **mount** | `CLONE_NEWNS` | 2.4.19 | Points de montage | Oui | +| **UTS** | `CLONE_NEWUTS` | 2.6.19 | Hostname, domaine NIS | Oui | +| **IPC** | `CLONE_NEWIPC` | 2.6.19 | Objets IPC System V et POSIX | Oui | +| **PID** | `CLONE_NEWPID` | 2.6.24 | Arbre de processus | Oui | +| **network** | `CLONE_NEWNET` | 2.6.29 | Interfaces, routes, ports | Oui | +| **user** | `CLONE_NEWUSER` | 3.8 | UIDs, GIDs, capabilities | **Non** | +| **cgroup** | `CLONE_NEWCGROUP` | 4.6 | Vue arborescence cgroup | Oui | +| **time** | `CLONE_NEWTIME` | 5.6 | Horloges monotones | Oui | + +*\* Sauf si combiné avec un *namespace* `user`* + + +## Ce que chaque *namespace* vous permet de faire + +### `mount` -- Systèmes de fichiers isolés + +**Fonctionnalité :** Isole l'arborescence des points de montage. + +**Permet de :** +- Créer un système de fichiers racine différent (`pivot_root`, `switch_root`) +- Monter/démonter des partitions sans affecter l'hôte +- Implémenter un `chroot` sécurisé (impossible de s'échapper) +- Utiliser des systèmes de fichiers en couches (OverlayFS) + +**Cas d'usage typiques :** +- Conteneurs avec leur propre filesystem +- Environnements de build isolés +- Systèmes d'installation et de récupération + + +### `UTS` -- Identité système + +**Fonctionnalité :** Isole le nom d'hôte et le domaine NIS. + +**Permet de :** +- Donner un nom unique à chaque conteneur +- Éviter les conflits de nommage +- Faciliter l'identification des conteneurs + +**Cas d'usage typiques :** +- Conteneurs avec des noms de machine distincts +- Environnements multi-tenants +- Tests de configurations réseau + + +### `IPC` -- Communication inter-processus + +**Fonctionnalité :** Isole les objets IPC (files de messages, sémaphores, +mémoire partagée). + +**Permet de :** +- Empêcher la communication IPC entre conteneurs +- Isoler les applications utilisant IPC System V ou POSIX +- Protéger contre les fuites d'informations via IPC + +**Cas d'usage typiques :** +- Isolation de sécurité entre conteneurs +- Applications legacy utilisant IPC System V +- Environnements de test pour applications IPC + + +### `PID` -- Arbre de processus virtualisé + +**Fonctionnalité :** Isole l'arbre des processus avec renumérotation. + +**Permet de :** +- Avoir un processus `init` (PID 1) par conteneur +- Masquer les processus de l'hôte et des autres conteneurs +- Gérer le cycle de vie des processus indépendamment +- Récolter les processus orphelins proprement + +**Cas d'usage typiques :** +- Conteneurs avec gestion complète du cycle de vie +- Isolation de sécurité (masquage des processus) +- Environnements avec plusieurs niveaux d'`init` + +**Particularité :** Le processus doit forker après `unshare(CLONE_NEWPID)` +pour que l'isolation soit effective. + + +### `network` -- Pile réseau dédiée + +**Fonctionnalité :** Isole les interfaces réseau, routes, règles de pare-feu et +ports. + +**Permet de :** +- Donner une pile réseau complète à chaque conteneur +- Réutiliser les mêmes ports dans différents conteneurs +- Configurer des routes et pare-feu indépendants +- Créer des topologies réseau complexes (bridges, VLAN, MACVLAN) + +**Cas d'usage typiques :** +- Conteneurs avec leur propre IP +- Tests réseau isolés +- Micro-services avec ports identiques +- Simulations de topologies réseau + +**Note :** Nécessite généralement des interfaces virtuelles (`veth`, `macvlan`, +etc.) pour connecter les conteneurs. + + +### `user` -- Privilèges virtualisés + +**Fonctionnalité :** Isole les UIDs, GIDs et les capabilities. + +**Permet de :** +- Être root dans le conteneur sans être root sur l'hôte +- Lancer des conteneurs sans privilèges (rootless containers) +- Mapper des plages d'UIDs entre conteneur et hôte +- Déléguer des capacités limitées + +**Cas d'usage typiques :** +- Conteneurs rootless (podman, systemd-nspawn) +- Environnements multi-utilisateurs sécurisés +- Délégation contrôlée de privilèges + +**Particularité :** Seul *namespace* créable sans privilèges. Permet ensuite de +créer tous les autres types de *namespaces*. + +**Attention :** Historiquement source de vulnérabilités ; à utiliser avec +précaution. + + +### `cgroup` -- Vue filtrée des control groups + +**Fonctionnalité :** Virtualise la vue de l'arborescence des cgroups. + +**Permet de :** +- Masquer l'organisation des cgroups de l'hôte +- Faciliter la migration de conteneurs +- Empêcher la fuite d'informations système via `/sys/fs/cgroup` +- Déléguer la gestion de sous-arbres de cgroups + +**Cas d'usage typiques :** +- Renforcement de l'isolation de sécurité +- Migration de conteneurs (CRIU) +- Systèmes multi-tenants + +**Note :** Souvent combiné avec un *namespace* `mount` pour remonter +`/sys/fs/cgroup`. + + +### `time` -- Horloges virtualisées + +**Fonctionnalité :** Virtualise `CLOCK_MONOTONIC` et `CLOCK_BOOTTIME`. + +**Permet de :** +- Décaler les horloges monotones pour un conteneur +- Préserver l'état temporel lors de migrations +- Accélérer le temps pour les tests + +**Cas d'usage typiques :** +- Migration de conteneurs avec CRIU +- Tests d'applications sensibles au temps +- Simulations temporelles + +**Limitation :** Ne virtualise **pas** l'heure système (CLOCK_REALTIME). + +**Particularité :** Les offsets doivent être configurés avant de créer le +premier processus enfant. + + +## Combinaisons recommandées + +Les *namespaces* sont rarement utilisés seuls. Voici les combinaisons courantes +selon les besoins d'isolation : + + +### Isolation minimale (développement) + +Pour un environnement de développement simple avec un filesystem isolé : + +
+```bash +unshare --mount --pid --fork --mount-proc /bin/bash +``` +
+ +**Isolation :** Filesystem et processus +**Avantages :** Rapide, simple, suffisant pour tester des installations +**Limitations :** Partage le réseau, les utilisateurs, IPC avec l'hôte + + +### Conteneur standard (production light) + +Pour une isolation raisonnable sans réseau séparé : + +
+```bash +unshare --mount --uts --ipc --pid --fork --mount-proc /bin/bash +``` +
+ +**Isolation :** Filesystem, processus, IPC, hostname +**Avantages :** Bonne isolation, partage le réseau de l'hôte +**Cas d'usage :** Services système, environnements de build + + +### Conteneur avec réseau isolé + +Pour une isolation complète incluant le réseau : + +
+```bash +unshare --mount --uts --ipc --net --pid --fork --mount-proc /bin/bash +``` +
+ +**Isolation :** Filesystem, processus, IPC, hostname, réseau +**Avantages :** Isolation réseau complète +**Note :** Nécessite configuration réseau supplémentaire (veth, bridge, etc.) + + +### Conteneur rootless (sans privilèges) + +Pour lancer un conteneur en tant qu'utilisateur normal : + +
+```bash +unshare --user --map-root-user \ + --mount --uts --ipc --net --pid \ + --fork --mount-proc /bin/bash +``` +
+ +**Isolation :** Complète + virtualisation des privilèges +**Avantages :** Aucun privilège requis, sécurité renforcée +**Cas d'usage :** Environnements multi-utilisateurs, CI/CD non-privilégiée + + +### Conteneur type Docker (isolation maximale) + +Pour une isolation complète similaire à Docker : + +
+```bash +unshare --user --map-root-user \ + --mount --uts --ipc --net --pid --cgroup \ + --fork --mount-proc /bin/bash +``` +
+ +**Isolation :** Tous les namespaces (sauf `time`) +**Avantages :** Isolation maximale +**Note :** Équivalent approximatif de `docker run --rm -it` + + +## Ordre de création des *namespaces* + +L'ordre dans lequel les *namespaces* sont créés peut être important : + +1. **`user` en premier** : Si vous voulez créer des *namespaces* sans + privilèges, commencez toujours par le *namespace* `user`. + +2. **`mount` avant `pid`** : Pour pouvoir remonter `/proc` correctement avec + l'option `--mount-proc`. + +3. **`pid` avec `--fork`** : N'oubliez jamais l'option `--fork` avec le + *namespace* `pid`, sinon le processus actuel ne sera pas réellement isolé. + +4. **`time` et `cgroup` avant le fork** : Ces deux namespaces nécessitent des + configurations avant la création du premier processus enfant. + + +## Commandes essentielles + +Voici un récapitulatif des commandes les plus utiles pour travailler avec les +*namespaces* : + +### Création et entrée dans des *namespaces* + +
+```bash +# Créer de nouveaux namespaces et exécuter une commande +unshare [options] [commande] + +# Principales options : +# -m, --mount Namespace mount +# -u, --uts Namespace UTS +# -i, --ipc Namespace IPC +# -n, --net Namespace network +# -p, --pid Namespace PID +# -U, --user Namespace user +# -C, --cgroup Namespace cgroup +# -T, --time Namespace time +# -f, --fork Fork avant d'exécuter la commande (requis avec --pid) +# --mount-proc Monter /proc après création du namespace + +# Entrer dans les namespaces d'un processus existant +nsenter [options] [commande] +nsenter --target --all [commande] +``` +
+ +### Inspection des *namespaces* + +
+```bash +# Lister tous les namespaces du système +lsns + +# Lister les namespaces d'un processus spécifique +lsns -p + +# Voir les namespaces d'un processus +ls -l /proc//ns/ + +# Comparer les namespaces de deux processus +readlink /proc//ns/net +readlink /proc//ns/net +``` +
+ +### Gestion réseau (namespace network) + +
+```bash +# Créer un namespace network nommé +ip netns add + +# Lister les namespaces network +ip netns list + +# Exécuter une commande dans un namespace network +ip netns exec + +# Créer une paire veth +ip link add veth0 type veth peer name veth1 + +# Déplacer une interface dans un namespace +ip link set veth1 netns +``` +
+ + +## Appels système + +Pour les développeurs, voici les appels système principaux : + +
+```c +// Créer un nouveau processus dans de nouveaux namespaces +pid_t clone(int (*fn)(void *), void *stack, int flags, void *arg); +// flags: CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWPID, +// CLONE_NEWNET, CLONE_NEWUSER, CLONE_NEWCGROUP, CLONE_NEWTIME + +// Se dissocier de namespaces actuels +int unshare(int flags); + +// Rejoindre les namespaces d'un autre processus +int setns(int fd, int nstype); +// fd: file descriptor de /proc//ns/ +// nstype: 0 ou CLONE_NEW* pour vérification de type + +// Obtenir un file descriptor vers un processus (pour setns) +int pidfd_open(pid_t pid, unsigned int flags); +``` +
+ + +## Bonnes pratiques + +### Sécurité + +1. **Privilèges minimaux** : Utilisez le *namespace* `user` quand possible pour + éviter d'exécuter des conteneurs en tant que root. + +2. **Combinaison d'isolations** : Un seul namespace ne suffit généralement pas + pour une isolation sécurisée. Combinez plusieurs namespaces. + +3. **User namespace avec précaution** : Bien que pratique, le *namespace* + `user` a été source de nombreuses vulnérabilités. Assurez-vous d'utiliser un + noyau récent et correctement patché. + +4. **Nettoyage des ressources** : Les namespaces persistent tant qu'ils sont + référencés. Utilisez `umount` pour les bind mounts qui maintiennent des + namespaces actifs. + +5. **Capabilities** : Même dans un *namespace* `user`, les capabilities sont + limitées à l'intérieur du namespace. Ne comptez pas sur elles pour des + actions hors namespace. + + +### Performance + +1. **Coût minimal** : La création de namespaces a un coût négligeable en termes + de performance. N'hésitez pas à les utiliser. + +2. **Réseau** : Le type d'interface virtuelle utilisé (`veth`, `macvlan`, + `ipvlan`) peut avoir un impact significatif sur les performances réseau. + +3. **OverlayFS vs device-mapper** : Pour le stockage, OverlayFS est + généralement plus performant que les snapshots LVM (device-mapper). + + +### Débogage + +1. **`lsns` est votre ami** : Utilisez `lsns` pour comprendre rapidement + l'organisation des namespaces sur votre système. + +2. **Inspecter /proc** : Les fichiers dans `/proc//ns/` sont essentiels + pour comprendre dans quels namespaces se trouve un processus. + +3. **Bind mounts pour persistence** : Utilisez `mount --bind` sur les fichiers + de `/proc//ns/` pour maintenir un namespace actif même après la + terminaison du processus. + +4. **Logs et `strace`** : En cas de problème, `strace` peut vous montrer + exactement quels appels système échouent et pourquoi. + + +## Limitations et pièges courants + +### Namespace `PID` + +- **Oubli du `--fork`** : Sans fork, le processus actuel reste dans l'ancien + namespace PID. +- **Bash et PID 1** : Bash peut avoir des comportements inattendus en tant que + PID 1 (voir pidns.md pour les détails). +- **`/proc` doit être remonté** : Sinon `ps`, `top` montrent tous les processus + du système. + + +### Namespace `mount` + +- **Propagation des montages** : Attention aux politiques `shared`, `slave`, + `private`. Par défaut, utilisez `mount --make-rslave /` pour éviter les + fuites. +- **`pivot_root` vs `chroot`** : `pivot_root` est plus sûr mais plus complexe à + mettre en œuvre. + + +### Namespace `network` + +- **Pas d'interface par défaut** : Un nouveau namespace network ne contient + qu'une interface loopback désactivée. Il faut configurer le réseau + manuellement. +- **Complexité de la configuration** : Bridges, veth, routes, NAT... la + configuration réseau peut devenir complexe rapidement. + + +### Namespace `user` + +- **MappingUID/GID limité** : Sans privilèges, vous ne pouvez mapper qu'un + seul UID (le vôtre vers root). +- **Fichiers setuid** : Ne fonctionnent pas correctement dans un namespace + user. +- **Restrictions par distribution** : Certaines distributions désactivent le + namespace user par défaut (voir setup.md). + + +### Namespace `time` + +- **Configuration unique** : Les offsets ne peuvent être configurés qu'une fois, + avant le premier fork. +- **Pas d'heure réelle** : Ne virtualise pas `CLOCK_REALTIME`, seulement les + horloges monotones. + + +## Pour aller plus loin + +### Documentation officielle + +- Pages de manuel : `namespaces(7)`, `pid_namespaces(7)`, `user_namespaces(7)`, + `mount_namespaces(7)`, `network_namespaces(7)`, `ipc_namespaces(7)`, + `uts_namespaces(7)`, `cgroup_namespaces(7)`, `time_namespaces(7)` + +- Documentation du noyau : + + + +### Articles de référence + +- [Namespaces in operation (série LWN)](https://lwn.net/Articles/531114/) : + série d'articles exhaustive par Michael Kerrisk + + +- [Anatomy of a user namespaces vulnerability](https://lwn.net/Articles/543273/) : + pour comprendre les enjeux de sécurité + + + +### Projets utilisant les namespaces + +- **Docker/Podman/containerd** : Containerisation d'applications +- **systemd-nspawn** : Conteneurs légers pour systemd +- **LXC/LXD** : Conteneurs système complets +- **Flatpak/Snap** : Sandboxing d'applications +- **Chrome/Firefox** : Sandboxing de processus de rendu +- **bubblewrap** : Outil de sandboxing générique + + +## Conclusion + +Les *namespaces* Linux constituent une brique fondamentale de la virtualisation +légère moderne. Leur conception modulaire permet de créer des niveaux +d'isolation sur mesure, depuis un simple environnement de développement isolé +jusqu'à des conteneurs de production complets. + +La maîtrise des *namespaces* nécessite de comprendre : + +1. **Ce que chaque type isole** et dans quel contexte l'utiliser +2. **Comment les combiner** pour atteindre le niveau d'isolation souhaité +3. **Leurs interactions** et dépendances mutuelles +4. **Leurs limitations** et les cas particuliers à gérer + +Combinés avec les *cgroups* (pour la limitation de ressources) et les *security +modules* (AppArmor, SELinux pour les politiques de sécurité), les *namespaces* +permettent de construire des environnements d'exécution sûrs, isolés et +performants. + +Que vous développiez des outils de containerisation, construisiez des +plateformes cloud, ou cherchiez simplement à mieux isoler vos applications, les +*namespaces* sont un outil incontournable de l'écosystème Linux moderne. diff --git a/tutorial/4/networkns.md b/tutorial/4/networkns.md index 8fe702d..62065dd 100644 --- a/tutorial/4/networkns.md +++ b/tutorial/4/networkns.md @@ -82,7 +82,7 @@ virli 42sh# ip netns foo virli 42sh# ip netns exec foo ip link -1: lo: mut 65536 qdisc noop state DOWN mode DEFAULT group default +1: lo: mtu 65536 qdisc noop state DOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 ```
@@ -99,7 +99,7 @@ des interfaces :
``` 42sh# ip netns exec virli ip link -1: lo: mut 65536 qdisc noop state DOWN mode DEFAULT group default +1: lo: mtu 65536 qdisc noop state DOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 ```
@@ -175,11 +175,13 @@ struct nlmsghdr { ```
-Parmi les fonctionnalités de Netlink, nous allons utiliser le module NIS -(Network Interface Service)[^RFC3549NIS]. Il spécifie le format par lequel +Parmi les fonctionnalités de Netlink, nous allons utiliser RTNetlink +(Routing Netlink)[^RFC3549RTNETLINK]. Il spécifie le format par lequel doivent commencer les données liées à l'administration d'interfaces réseau. +Le module RTNetlink utilise la famille `NETLINK_ROUTE` pour communiquer avec +le noyau concernant les interfaces, routes et règles de routage. -[^RFC3549NIS]: Network Interface Service Module +[^RFC3549RTNETLINK]: RTNetlink - Linux Routing Socket
```c diff --git a/tutorial/4/timens.md b/tutorial/4/timens.md new file mode 100644 index 0000000..acf4167 --- /dev/null +++ b/tutorial/4/timens.md @@ -0,0 +1,263 @@ +Le *namespace* `time` {#time-ns} +--------------------- + +### Introduction + +L'espace de noms `time`, introduit dans Linux 5.6, permet de virtualiser les +horloges `CLOCK_MONOTONIC` et `CLOCK_BOOTTIME` pour des processus. Cela est +particulièrement utile pour la migration de conteneurs ou pour tester des +applications sensibles au temps. + +::::: {.warning} + +Contrairement à ce que son nom pourrait suggérer, le *namespace* `time` ne +permet **pas** de virtualiser l'heure système (l'horloge temps réel). Il ne +virtualise que les compteurs monotones. + +::::: + + +### Utilisation pratique + +Voyons comment utiliser le *namespace* `time` pour modifier le temps +d'exécution perçu par un processus. + + +#### Lire les horloges monotones\ + +Commençons par observer les valeurs actuelles de nos horloges : + +
+```bash +42sh$ cat /proc/uptime +123456.78 987654.32 +``` +
+ +Le premier nombre représente le temps depuis le démarrage du système (équivalent +à `CLOCK_BOOTTIME`), et le second le temps CPU cumulé en mode idle. + +On peut également utiliser un petit programme C pour afficher les horloges : + +
+```c +#include +#include + +int main(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + printf("CLOCK_MONOTONIC: %ld.%09ld\n", ts.tv_sec, ts.tv_nsec); + + clock_gettime(CLOCK_BOOTTIME, &ts); + printf("CLOCK_BOOTTIME: %ld.%09ld\n", ts.tv_sec, ts.tv_nsec); + + return 0; +} +``` +
+ +::::: {.code} + +Pour compiler ce programme : + +
+```bash +42sh$ gcc -o show_clocks show_clocks.c +``` +
+ +::::: + + +#### Créer un *namespace* `time` avec décalage\ + +Pour créer un nouveau *namespace* `time`, il faut d'abord le dissocier puis +configurer les décalages (offsets) avant de lancer un processus enfant. + +Le fichier `/proc//timens_offsets` permet de configurer les décalages pour +les horloges. Le format est le suivant : + +
+``` + +``` +
+ +Où `` peut être : +- `monotonic` pour `CLOCK_MONOTONIC` +- `boottime` pour `CLOCK_BOOTTIME` + +Voici un script shell pour créer un conteneur avec un temps décalé de 10 jours +dans le futur : + +
+```bash +42sh# unshare --time /bin/bash + intimens# echo "monotonic 864000 0" > /proc/self/timens_offsets + intimens# echo "boottime 864000 0" > /proc/self/timens_offsets + intimens# exec /bin/bash + intimens-child# ./show_clocks + CLOCK_MONOTONIC: 987654.123456789 + CLOCK_BOOTTIME: 987654.123456789 +``` +
+ +::::: {.warning} + +**Important :** Les décalages doivent être configurés **avant** de créer le +premier processus enfant. Une fois qu'un processus enfant existe dans le +*namespace*, les offsets ne peuvent plus être modifiés. C'est pourquoi nous +utilisons `exec` pour remplacer le shell actuel. + +::::: + + +#### Exemple en C\ + +Voici un exemple complet en C pour créer un *namespace* `time` avec un décalage : + +
+```c +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +static int child_func(void *arg) +{ + struct timespec ts; + + // Attendre que le parent configure les offsets + sleep(1); + + clock_gettime(CLOCK_MONOTONIC, &ts); + printf("Child - CLOCK_MONOTONIC: %ld.%09ld\n", + ts.tv_sec, ts.tv_nsec); + + clock_gettime(CLOCK_BOOTTIME, &ts); + printf("Child - CLOCK_BOOTTIME: %ld.%09ld\n", + ts.tv_sec, ts.tv_nsec); + + return 0; +} + +#define STACK_SIZE (1024 * 1024) +static char child_stack[STACK_SIZE]; + +int main(void) +{ + pid_t pid; + int fd; + char path[256]; + struct timespec ts; + + // Afficher les horloges du parent + clock_gettime(CLOCK_MONOTONIC, &ts); + printf("Parent - CLOCK_MONOTONIC: %ld.%09ld\n", + ts.tv_sec, ts.tv_nsec); + + // Se dissocier du namespace time + if (unshare(CLONE_NEWTIME) == -1) { + perror("unshare"); + exit(EXIT_FAILURE); + } + + // Configurer les offsets (décalage de 1000 secondes) + fd = open("/proc/self/timens_offsets", O_WRONLY); + if (fd == -1) { + perror("open timens_offsets"); + exit(EXIT_FAILURE); + } + + if (write(fd, "monotonic 1000 0\n", 17) != 17) { + perror("write monotonic offset"); + exit(EXIT_FAILURE); + } + + if (write(fd, "boottime 1000 0\n", 16) != 16) { + perror("write boottime offset"); + exit(EXIT_FAILURE); + } + + close(fd); + + // Créer un processus enfant qui verra les nouvelles horloges + pid = clone(child_func, child_stack + STACK_SIZE, + SIGCHLD, NULL); + if (pid == -1) { + perror("clone"); + exit(EXIT_FAILURE); + } + + waitpid(pid, NULL, 0); + + return 0; +} +``` +
+ +::::: {.code} + +Pour compiler : + +
+```bash +42sh$ gcc -o time_ns_demo time_ns_demo.c +42sh$ ./time_ns_demo +Parent - CLOCK_MONOTONIC: 123456.789012345 +Child - CLOCK_MONOTONIC: 124456.789012345 +Child - CLOCK_BOOTTIME: 124456.789012345 +``` +
+ +On voit bien le décalage de 1000 secondes entre le parent et l'enfant. + +::::: + + +### Cas d'usage pratiques + +#### Migration de conteneurs\ + +Lors de la migration d'un conteneur d'une machine à une autre, les processus +peuvent avoir des timers ou des alarmes basées sur `CLOCK_MONOTONIC`. Si on ne +virtualise pas ces horloges, tous ces timers seraient incorrects après la +migration. + +Le *namespace* `time` permet de restaurer l'état des horloges monotones lors +de la restauration d'un conteneur. + + +#### Tests et simulation\ + +Pour tester des applications qui utilisent des timeouts ou des mécanismes de +retry avec backoff exponentiel, il peut être utile de virtualiser le temps pour +accélérer les tests sans modifier le code de l'application. + + +### Limitations + +- Seules les horloges `CLOCK_MONOTONIC` et `CLOCK_BOOTTIME` peuvent être + virtualisées +- L'heure système (`CLOCK_REALTIME`) reste identique pour tous les processus +- Les offsets ne peuvent être configurés qu'une seule fois, avant la création + du premier processus enfant +- Les décalages ne peuvent pas être négatifs (on ne peut pas remonter dans le + temps) + + +### Aller plus loin {-} + +Pour plus d'informations sur le *namespace* `time`, consultez : + +- `time_namespaces(7)` - page de manuel +- [Time Namespace support](https://lwn.net/Articles/766089/) : +- [Checkpoint/Restore and Time Namespace](https://lwn.net/Articles/801652/) : From 51d964d0bcb67f2aaab0bc0efefeb5bfb3effc2b Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 7 Jan 2026 22:46:57 +0700 Subject: [PATCH 07/11] docker-orchestration: Fix spelling --- tutorial/docker-orchestration/setup.md | 2 +- tutorial/docker-orchestration/stack.md | 25 ++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/tutorial/docker-orchestration/setup.md b/tutorial/docker-orchestration/setup.md index 40db57e..a113b80 100644 --- a/tutorial/docker-orchestration/setup.md +++ b/tutorial/docker-orchestration/setup.md @@ -11,7 +11,7 @@ pour un projet. Ainsi, il est possible de provisionner et gérer des machines hôtes sur les plates-formes de cloud habituelles. C'est également ce projet qui est à la base -de *Docker Dektop*, en permettant de lancer via, respectivement, VirtualBox ou +de *Docker Desktop*, en permettant de lancer via, respectivement, VirtualBox ou Hyper-V, un environnement Linux prêt à être utilisé avec Docker. ### Par la distribution binaire diff --git a/tutorial/docker-orchestration/stack.md b/tutorial/docker-orchestration/stack.md index 0a358bc..9219bc0 100644 --- a/tutorial/docker-orchestration/stack.md +++ b/tutorial/docker-orchestration/stack.md @@ -156,19 +156,18 @@ version: '3' services: redis: image: redis:alpine - - deploy: - replicas: 6 - update_config: - parallelism: 2 - delay: 10s - restart_policy: - condition: on-failure - placement: - constraints: - - node.role == manager - resources: - memory: 50M + deploy: + replicas: 6 + update_config: + parallelism: 2 + delay: 10s + restart_policy: + condition: on-failure + placement: + constraints: + - node.role == manager + resources: + memory: 50M ```
From 593fbe314824e3ec0a9aff0dd2f46e6e64546691 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 7 Jan 2026 23:03:01 +0700 Subject: [PATCH 08/11] k8s: Fix spelling --- tutorial/k8s/discover.md | 2 +- tutorial/k8s/scaling.md | 66 ++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/tutorial/k8s/discover.md b/tutorial/k8s/discover.md index c8de70d..bc8dd58 100644 --- a/tutorial/k8s/discover.md +++ b/tutorial/k8s/discover.md @@ -223,7 +223,7 @@ Pour résumer : `kubectl` a créé une tâche de déploiement `rs/pingpong-xxxx`. Ce *replicatset* a créé un *pod* `po/pingpong-yyyy`. -#### Pasage à l'échelle : facile ? +#### Passage à l'échelle : facile ? Pour lancer 3 `ping`s en parallèle, modifions la tâche de déploiement comme suit : diff --git a/tutorial/k8s/scaling.md b/tutorial/k8s/scaling.md index f8b6965..56d04b5 100644 --- a/tutorial/k8s/scaling.md +++ b/tutorial/k8s/scaling.md @@ -39,41 +39,41 @@ metadata: name: fluentd-elasticsearch namespace: kube-system labels: - k8s-app: fluentd-logging + k8s-app: fluentd-logging spec: selector: - matchLabels: - name: fluentd-elasticsearch + matchLabels: + name: fluentd-elasticsearch template: - metadata: - labels: - name: fluentd-elasticsearch - spec: - tolerations: - - key: node-role.kubernetes.io/master - effect: NoSchedule - containers: - - name: fluentd-elasticsearch - image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 - resources: - limits: - memory: 200Mi - requests: - cpu: 100m - memory: 200Mi - volumeMounts: - - name: varlog - mountPath: /var/log - - name: varlibdockercontainers - mountPath: /var/lib/docker/containers - readOnly: true - terminationGracePeriodSeconds: 30 - volumes: - - name: varlog - hostPath: - path: /var/log - - name: varlibdockercontainers - hostPath: + metadata: + labels: + name: fluentd-elasticsearch + spec: + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + containers: + - name: fluentd-elasticsearch + image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 + resources: + limits: + memory: 200Mi + requests: + cpu: 100m + memory: 200Mi + volumeMounts: + - name: varlog + mountPath: /var/log + - name: varlibdockercontainers + mountPath: /var/lib/docker/containers + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - name: varlog + hostPath: + path: /var/log + - name: varlibdockercontainers + hostPath: path: /var/lib/docker/containers ``` @@ -127,7 +127,7 @@ Après avoir appliqué la nouvelle spec, on constate qu'il y a beaucoup de *pod* toujours là. -##### Botleneck résolu ? {-} +##### Bottleneck résolu ? {-} Admirez maintenant dans Chronograf si vous avez réussi à augmenter votre nombre de pépites ! From 54c3aa3643e9ca4474158d494d06eb2aa800bbd0 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 7 Jan 2026 23:09:57 +0700 Subject: [PATCH 09/11] lxc: Fix spelling and sentence construction --- tutorial/lxc/lxc.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/tutorial/lxc/lxc.md b/tutorial/lxc/lxc.md index c33fe4a..1b16f0e 100644 --- a/tutorial/lxc/lxc.md +++ b/tutorial/lxc/lxc.md @@ -13,8 +13,8 @@ Avec le paquet `lxc` que nous avons précédemment installé, nous avons égalem récupéré un certain nombre de *modèles* de système (souvent installés dans le dossier `/usr/share/lxc/templates/`) : il s'agit d'une suite de commandes (principalement des `wget`, `chroot` ou `debootstrap`) permettant d'obtenir un -système basic fonctionnel, en suivant les étapes d'installation habituelle de -la distribution. +système de base fonctionnel, en suivant les étapes d'installation habituelles +de la distribution. La méthode la plus simple pour lancer un conteneur `lxc` est d'utiliser l'un de ces modèles pour obtenir un nouveau système. On utilise pour cela la commande @@ -45,11 +45,11 @@ s'attendre à trouver dans n'importe quelle machine virtuelle (et même physique plus classique (la seule différence réside donc dans le fait que le noyau est partagé avec l'hôte). -Généralement on lance `lxc-start` avec l'option `--daemon`, car on n'a pas -vraiment envie d'avoir un conteneur bloquant un terminal. En mode daemon, on va -utiliser la commande `lxc-console` pour nous attacher aux conteneurs. À tout -moment, nous pouvons nous détacher de la console (sans que cela n'affecte -l'état du conteneur) en pressant les touches : `^A q`. +Généralement on lance `lxc-start` avec l'option `--daemon`, car sans cette +option le conteneur monopolise le terminal. En mode daemon, on utilise la +commande `lxc-console` pour s'attacher aux conteneurs. À tout moment, nous +pouvons nous détacher de la console (sans que cela n'affecte l'état du +conteneur) en pressant les touches : `^A q`. Connectons-nous, lançons quelques commandes puis éteignons la machine en lançant la commande `poweroff` dans le conteneur. Il est également possible de @@ -122,8 +122,9 @@ veth, avec un côté placé dans la machine hôte et l'autre côté placé dans conteneur. `lxc` configure l'interface dans le conteneur, il nous appartient ensuite de configurer la machine hôte. -Commençons par attribuer une IP à cette nouvelle interface, en adaptant à votre -identifiant d'interface : +Commençons par attribuer une IP à cette nouvelle interface. L'identifiant de +l'interface veth créée côté hôte peut être trouvé avec la commande `ip link`. +Adaptez l'exemple suivant avec votre identifiant d'interface :
```bash @@ -136,10 +137,10 @@ machine hôte : `ping 172.23.42.2`. Notre conteneur ne peut cependant pas encore accéder à Internet. Pour cela, la machine hôte doit faire office de routeur et donc router les paquets d'un -réseau à l'autre : en l'occurence, du réseau 172.23.42.1 vers Internet +réseau à l'autre : en l'occurrence, du réseau 172.23.42.0/24 vers Internet via 10.0.0.0/8, le réseau de l'école. -Pour que notre machine hôte route les paquets, exécuter la commande : +Pour que notre machine hôte route les paquets, exécutez la commande :
```bash @@ -151,9 +152,9 @@ Cette variable, que nous retrouvons dans `/proc/sys/net/ipv4/ip_forward`, indique au noyau qu'il peut faire passer les paquets réseau d'une interface à l'autre. Sans plus de directives, les paquets vont conserver leur adresse source (172.23.42.2 pour les paquets en provenance du conteneur). Cette adresse -est une adresse privée, non routable sur Internet, ni même par le bocal. Il -faut donc ajouter une couche de NAT/PAT pour réécrire les adresses sources -avant d'envoyer les paquets sur internet : +est une adresse privée, non routable sur Internet. Il faut donc ajouter une +couche de NAT/PAT pour réécrire les adresses sources avant d'envoyer les +paquets sur Internet (en adaptant le nom de l'interface veth) :
```bash @@ -162,7 +163,7 @@ iptables -t nat -A POSTROUTING ! -o vethYJWD6R -s 172.23.42.0/24 -j MASQUERADE
Dernière étape, dans notre conteneur, nous devons indiquer la route à utiliser -pour accéder à internet : +pour accéder à Internet :
```bash @@ -170,7 +171,7 @@ ip route add default via 172.23.42.1 ```
-Nous avons maintenant internet dans notre conteneur ! +Nous avons maintenant Internet dans notre conteneur ! ## Utilisation du conteneur From 8c3ea223e5969c623a420a89d5c4b947d3972a81 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 7 Jan 2026 23:11:36 +0700 Subject: [PATCH 10/11] containers: Fix spelling --- tutorial/containers/overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tutorial/containers/overview.md b/tutorial/containers/overview.md index 7de7f6c..97e71b4 100644 --- a/tutorial/containers/overview.md +++ b/tutorial/containers/overview.md @@ -22,7 +22,7 @@ Il existe différentes typologies d'images : MongoDB, ... - certaines contiennent un programme spécifique : on peut vouloir utiliser `git`, le client `MySQL`, `emacs` ou bien encore le navigateur Chrome ; -- d'autes enfin servent pour développer et étendre les possibilités. Ce sont +- d'autres enfin servent pour développer et étendre les possibilités. Ce sont souvent des images utilisées comme bases pour les deux types que l'on a vus : Debian, Alpine, Windows, ... @@ -68,7 +68,7 @@ aux seules données de l'image. Les conteneurs sont par nature **immuables** : on exécute le contenu d'une image déjà construite, on n'y change pas le code qui est exécuté et on n'y fait -pas de changements qui pourrait altérer son fonctionnement. L'idée directrice dans +pas de changements qui pourraient altérer son fonctionnement. L'idée directrice dans le design des conteneurs est de toujours être en mesure de pouvoir relancer un conteneur ailleurs et s'attendre exactement au même comportement. From 25aef1af172880e6dee4ddf0fc995707c2e62e4e Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 10 Apr 2026 16:19:05 +0700 Subject: [PATCH 11/11] New spelling fixes --- tutorial/3/capabilities.md | 10 ++++----- tutorial/3/cgroups.md | 4 ++-- tutorial/3/chroot.md | 4 ++-- tutorial/3/oom.md | 6 ++--- tutorial/3/project-rendu.md | 2 +- tutorial/3/rendu.md | 2 +- tutorial/4/filesystem.md | 4 ++-- tutorial/4/howto.md | 6 ++--- tutorial/4/intro.md | 6 ++--- tutorial/4/lesson.md | 2 +- tutorial/4/lsns.md | 2 +- tutorial/4/mount.md | 2 +- tutorial/4/networkns.md | 4 ++-- tutorial/4/pidns.md | 2 +- tutorial/4/project-intro.md | 2 +- tutorial/4/rendu.md | 2 +- tutorial/4/setns-samples.md | 2 +- tutorial/4/tutorial.md | 2 +- tutorial/containers/overview.md | 8 +++---- tutorial/devops/ci-about-webhook.md | 4 ++-- tutorial/devops/ci-tags.md | 2 +- tutorial/devops/devops.md | 6 ++--- tutorial/devops/publish-docker-end-gistre.md | 2 +- tutorial/devops/publish-docker-end.md | 2 +- tutorial/devops/renovate-cmd.md | 2 +- tutorial/devops/renovate-end.md | 8 +++---- tutorial/devops/renovate.md | 4 ++-- tutorial/devops/run-gistre.md | 2 +- tutorial/devops/tools-drone-runner-ansible.md | 2 +- tutorial/devops/what-gistre.md | 8 +++---- tutorial/devops/what.md | 2 +- tutorial/docker-advanced/manual.md | 2 +- tutorial/docker-advanced/security.md | 2 +- tutorial/docker-advanced/setup.md | 4 ++-- tutorial/docker-advanced/what.md | 2 +- tutorial/docker-basis/debug.md | 4 ++-- tutorial/docker-basis/ex-flask-volume.md | 4 ++-- tutorial/docker-basis/ex-flask.md | 6 ++--- tutorial/docker-basis/first.md | 6 ++--- tutorial/docker-basis/installation.md | 2 +- tutorial/docker-basis/linking-ex-fic.md | 2 +- tutorial/docker-basis/volumes.md | 4 ++-- tutorial/docker-basis/what.md | 8 +++---- tutorial/docker-internals/clair.md | 4 ++-- tutorial/docker-internals/oci.md | 6 ++--- tutorial/docker-internals/setup.md | 2 +- tutorial/docker-internals/tini.md | 8 +++---- .../docker-internals/vulnerability-scan.md | 4 ++-- tutorial/docker-orchestration/setup.md | 2 +- tutorial/docker-orchestration/stack.md | 10 ++++----- tutorial/docker-orchestration/swarm.md | 2 +- tutorial/k8s/discover.md | 22 +++++++++---------- tutorial/k8s/overview.md | 14 ++++++------ tutorial/k8s/setup.md | 9 ++++---- 54 files changed, 123 insertions(+), 122 deletions(-) diff --git a/tutorial/3/capabilities.md b/tutorial/3/capabilities.md index 3b8882f..d23be45 100644 --- a/tutorial/3/capabilities.md +++ b/tutorial/3/capabilities.md @@ -14,7 +14,7 @@ privilégiés outrepassaient ces tests, tandis que les autres devaient passer le tests de l'*effective UID*, *effective GID*, et autres groupes supplémentaires... -Dans les années 90, ce système s'est rélévé être un peu trop basique et +Dans les années 90, ce système s'est révélé être un peu trop basique et conduisait régulièrement à des abus, au moyen de vulnérabilités trouvées dans les programmes *setuid root*. @@ -41,7 +41,7 @@ contient les hashs des mots de passe). C'est ainsi qu'est apparu le `suid-bit` parmi les modes de fichiers. Lorsque ce bit est défini sur un binaire exécutable, au moment de l'exécution, le contexte passe à celui du propriétaire du fichier (`root` si le propriétaire -est `root`, mais cela fonctionne quelque soit le propriétaire du fichier : on +est `root`, mais cela fonctionne quel que soit le propriétaire du fichier : on ne devient pas `root`, mais bien l'utilisateur propriétaire).\ @@ -158,7 +158,7 @@ Tout d'abord, il faut noter que chaque *thread* dispose de 5 ensembles de - ***inheritable*** (I) : est utilisé au moment de la résolution des *capabilities* lors de l'exécution d'un nouveau processus. Il s'agit des *capabilities* qui - seront transmises au processus fil. À moins d'avoir la *capability* + seront transmises au processus fils. À moins d'avoir la *capability* `CAP_SETPCAP`, cet ensemble ne peut pas avoir plus de *capability* que celles présentent dans l'ensemble *permitted* ; @@ -331,7 +331,7 @@ struct vfs_cap_data { La valeur `magic` contient la version sur 1 octet, puis 3 octets sont réservés pour des *flags*. Actuellement un seul *flag* existe, il s'agit de `VFS_CAP_FLAGS_EFFECTIVE` qui détermine si la liste effective de *capabilities* -du programme doit être remplie avec les *capabilities* *permitted* si elle doit +du programme doit être remplie avec les *capabilities* *permitted* ou si elle doit rester vide (auquel cas ce sera au programme de s'ajouter les *capabilities* au cours de l'exécution).\ @@ -698,5 +698,5 @@ Et de ces quelques articles : * [Linux Capabilities on HackTricks](https://book.hacktricks.xyz/linux-unix/privilege-escalation/linux-capabilities) :\ -- [POSIX Access Control Lists on Linux](https://www.usenix.org/legacy/publications/library/proceedings/usenix03/tech/freenix03/full_papers/gruenbacher/gruenbacher_html/main.html) :\ +* [POSIX Access Control Lists on Linux](https://www.usenix.org/legacy/publications/library/proceedings/usenix03/tech/freenix03/full_papers/gruenbacher/gruenbacher_html/main.html) :\ diff --git a/tutorial/3/cgroups.md b/tutorial/3/cgroups.md index 08466cd..6ebc113 100644 --- a/tutorial/3/cgroups.md +++ b/tutorial/3/cgroups.md @@ -88,7 +88,7 @@ La principale différence entre les deux est la fusion des différents sous-systèmes au sein d'une même arborescence. Dans la première version, chaque sous-système disposait de sa propre arborescence et il fallait créer les groupes et associer les tâches pour chaque sous-système. Avec la seconde -version, une seule création est nécessaire, quelque soit le nombre de +version, une seule création est nécessaire, quel que soit le nombre de sous-systèmes que l'on souhaite utiliser. ::::: @@ -360,7 +360,7 @@ max ```
-Chaque *cgroup*s définit de nombreux indicateurs et possède de nombreux +Chaque *cgroup* définit de nombreux indicateurs et possède de nombreux limiteurs, n'hésitez pas à consulter la documentation associée à chaque *cgroup*. diff --git a/tutorial/3/chroot.md b/tutorial/3/chroot.md index 30db29d..db792de 100644 --- a/tutorial/3/chroot.md +++ b/tutorial/3/chroot.md @@ -58,7 +58,7 @@ d'avoir de quoi bidouiller : un shell sera amplement suffisant pour commencer. ### `busybox` -Queques mots, pour commencer, à propos du projet Busybox : c'est un programme +Quelques mots, pour commencer, à propos du projet Busybox : c'est un programme couteau-suisse qui implémente tous les binaires vitaux pour avoir un système fonctionnel et utilisable : `ls`, `sh`, `cat`, mais aussi `init`, `mdev` (un `udev`-like, cela permet de découvrir les périphériques attachés afin de les @@ -171,7 +171,7 @@ chroot newroot/ bash
```bash -tar xpf alpine-minirootfs-*.tar.xz -C newroot/ +tar xpf alpine-minirootfs-*.tar.gz -C newroot/ ```
diff --git a/tutorial/3/oom.md b/tutorial/3/oom.md index 596157a..511edfe 100644 --- a/tutorial/3/oom.md +++ b/tutorial/3/oom.md @@ -6,7 +6,7 @@ Gestion de la mémoire Linux a une gestion de la mémoire bien particulière[^vm-overcommit] : en effet, par défaut, `malloc(3)` ne retournera jamais `NULL`. En se basant sur l'euristique qu'un bloc mémoire demandé ne sera pas utilisé directement et que -de nombreux process ne feront pas un usage total des blocs qu'ils ont alloués, +de nombreux processus ne feront pas un usage total des blocs qu'ils ont alloués, le noyau permet d'allouer plus de mémoire qu'il n'y en a réellement disponible. La mémoire est ainsi utilisée de manière plus efficace. @@ -21,7 +21,7 @@ trouve dans l'impossibilité d'attribuer un bloc physiquement disponible, car il n'y en a tout simplement plus (y compris via le swap). Puisque le noyau ne peut pas honorer sa promesse et qu'il n'a plus la -possibilité de retourner `NULL` au programme qui réclamme sa mémoire (il s'agit +possibilité de retourner `NULL` au programme qui réclame sa mémoire (il s'agit sans doute d'une simple assignation de variable à ce stade), il faut trouver une solution si l'on veut pouvoir continuer l'exécution du programme. @@ -107,7 +107,7 @@ mémoire autorisée au sein du `cgroup` ? ::::: Eh oui, l'OOM-killer passe également lorsqu'un `cgroup` atteint la limite de -mémoire qui lui est réservé. Dans ce cas évidemment, les processus pris en +mémoire qui lui est réservée. Dans ce cas évidemment, les processus pris en compte sont ceux contenus dans le `cgroup`. diff --git a/tutorial/3/project-rendu.md b/tutorial/3/project-rendu.md index d59d3d4..84905d8 100644 --- a/tutorial/3/project-rendu.md +++ b/tutorial/3/project-rendu.md @@ -5,7 +5,7 @@ Rendu Est attendu d'ici le TP suivant : -- le rendu des exercice de ce TP ; +- le rendu des exercices de ce TP ; - vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/14). Pour les GISTRE (et en bonus pour les SRS), [un diff --git a/tutorial/3/rendu.md b/tutorial/3/rendu.md index ad17990..67e45c8 100644 --- a/tutorial/3/rendu.md +++ b/tutorial/3/rendu.md @@ -69,4 +69,4 @@ sur `rendu3`, ... ce qui vous permet d'avoir une arborescence correspondant à ce qui est demandé, sans pour autant perdre votre travail (ou le rendre plus difficile d'accès). -:::: +::::: diff --git a/tutorial/4/filesystem.md b/tutorial/4/filesystem.md index 18a9cd0..16936da 100644 --- a/tutorial/4/filesystem.md +++ b/tutorial/4/filesystem.md @@ -31,7 +31,7 @@ combinaison de chaque couche. ### Historique -Les premières implémentations de ce type de systèmes de fichiers est apparu +Les premières implémentations de ce type de systèmes de fichiers sont apparues avec les LiveCD : on disposait d'une distribution Linux complètement opérationnelle sur un support en lecture seule, mais on pouvait dédier un espace de stockage sur son disque dur (ou en RAM, au travers d'un `tmpfs`) pour @@ -42,7 +42,7 @@ Historiquement, le noyau Linux devait être *patché* pour supporter ce type de système de fichiers (que ce soit `unionfs` ou `aufs`, les deux principaux *patch* apportant cette fonctionnalité). Les systèmes BSD disposent d'une implémentation depuis au moins 1995 et c'est SunOS qui fut le premier OS à -développer cette technique dès 1986 (pour un système de fichier appelé +développer cette technique dès 1986 (pour un système de fichiers appelé *Translucent File Service*). Pour Linux, il aura fallu attendre 2014 pour voir l'arrivée du système de fichier OverlayFS dans un noyau sans *patch*. diff --git a/tutorial/4/howto.md b/tutorial/4/howto.md index 2f6eb9b..517581d 100644 --- a/tutorial/4/howto.md +++ b/tutorial/4/howto.md @@ -79,7 +79,7 @@ processus se fait en fonction des *flags* qui sont passés. On retrouve donc : Le nom du *flag* `CLONE_NEWNS` est historique et assez peu explicite contrairement aux autres : il désigne en fait l'espace de nom `mount`. -Au départ, les *namespace*s ont étés pensés pour former un tout : une couche +Au départ, les *namespace*s ont été pensés pour former un tout : une couche d'isolation complète pour les processus. Mais lors des développements suivants, il s'est avéré pratique de pouvoir choisir finement de quels aspects on souhaitait se dissocier. @@ -108,7 +108,7 @@ semblable à : #define STACKSIZE (1024 * 1024) static char child_stack[STACKSIZE]; -int clone_flags = CLONE_CGROUP | CLONE_NEWNET | SIGCHLD; +int clone_flags = CLONE_NEWCGROUP | CLONE_NEWNET | SIGCHLD; pid_t pid = clone(do_execvp, // First function executed by child child_stack + STACKSIZE, // Assume stack grows downward @@ -155,7 +155,7 @@ extensions GNU : \ Lorsque l'on crée un nouveau processus, on ajoute l'option `SIGCHLD` afin -d'être notifié par signal lorsque notre processus fil a terminé son +d'être notifié par signal lorsque notre processus fils a terminé son exécution. Cela permet d'être réveillé de notre `wait(2)`. ::::: diff --git a/tutorial/4/intro.md b/tutorial/4/intro.md index 4e3ce96..9e97562 100644 --- a/tutorial/4/intro.md +++ b/tutorial/4/intro.md @@ -89,7 +89,7 @@ processus est rendu orphelin dans ce *namespace*, il devient un fils de ce processus, et non un fils de l'`init` de l'arbre global. -#### L'espace de nom `network` {.unnumbered} +#### L'espace de noms `network` {.unnumbered} Depuis Linux 2.6.29. @@ -149,9 +149,9 @@ Lorsque l'on souhaite mesurer un écoulement de temps, la méthode naïve consis soustraction avec l'heure de fin. Cette technique fonctionne bien, à partir du moment où l'on est sûr que l'horloge ne remontera pas dans le temps, parce qu'elle se synchronise ou que le changement d'heure été/hiver -intervient, ... Pour palier ces situations imprévisibles, le noyau expose une +intervient, ... Pour pallier ces situations imprévisibles, le noyau expose une horloge dite monotone (`CLOCK_MONOTONIC`) : cette horloge démarre à un entier -abstrait et s'incrèmente chaque seconde qui passe, sans jamais sauter de +abstrait et s'incrémente chaque seconde qui passe, sans jamais sauter de secondes, ni revenir en arrière. C'est une horloge fiable pour calculer des intervalles de temps. diff --git a/tutorial/4/lesson.md b/tutorial/4/lesson.md index e8d4cbc..fabd2c9 100644 --- a/tutorial/4/lesson.md +++ b/tutorial/4/lesson.md @@ -8,5 +8,5 @@ abstract: | Le but de cette seconde partie sur les mécanismes internes du noyau va nous permettre d'utiliser les commandes et les appels système relatifs aux espaces de noms du noyau Linux ainsi que d'appréhender - la complexité des sytèmes de fichiers. + la complexité des systèmes de fichiers. ... diff --git a/tutorial/4/lsns.md b/tutorial/4/lsns.md index ec99913..720a09f 100644 --- a/tutorial/4/lsns.md +++ b/tutorial/4/lsns.md @@ -40,7 +40,7 @@ Cette commande nous dévoile déjà de nombreuses choses : contenerisé » (dans un *namespace*). Le processus initial de la machine se retrouve donc dans des espaces de nom, tout comme les processus d'un conteneur. -- On aperçoit un genre de hiérarchie dans certain cas. +- On aperçoit un genre de hiérarchie dans certains cas. - La première colonne nous renseigne sur l'identifiant du *namespace*. diff --git a/tutorial/4/mount.md b/tutorial/4/mount.md index b40d33d..d882f63 100644 --- a/tutorial/4/mount.md +++ b/tutorial/4/mount.md @@ -168,7 +168,7 @@ esclave ne propagera pas ses nouveaux points de montage à son *maître*.
```bash # Suite de l'exemple précédent -cd /mnt/test-slave +mkdir /mnt/test-slave # Duplication de l'accroche, sans s'occuper des éventuels sous-accroches mount --bind /mnt/test-shared /mnt/test-slave diff --git a/tutorial/4/networkns.md b/tutorial/4/networkns.md index 62065dd..8adcd84 100644 --- a/tutorial/4/networkns.md +++ b/tutorial/4/networkns.md @@ -30,7 +30,7 @@ l'autre. ::::: Afin d'amener du réseau à notre nouvel espace de nom, il va falloir lui -attribuer des interface. En fait, nous allons pouvoir déplacer nos interfaces +attribuer des interfaces. En fait, nous allons pouvoir déplacer nos interfaces réseaux, dans le *namespace* vers lequel elle doit être accessible. Une interface donnée ne peut se trouver que dans un seul *namespace* à la fois. @@ -88,7 +88,7 @@ foo virli
Les fichiers utilisés par `ip netns` ne sont donc rien de plus que des -*bind-mount*. Ce qui explique qu'ils soient persistant même sans processus +*bind-mount*. Ce qui explique qu'ils soient persistants même sans processus s'exécutant à l'intérieur. ::::: diff --git a/tutorial/4/pidns.md b/tutorial/4/pidns.md index 418b992..21ec24e 100644 --- a/tutorial/4/pidns.md +++ b/tutorial/4/pidns.md @@ -98,7 +98,7 @@ donc été alloué à un processus d'initialisation de `bash`, qui s'est termin depuis.\ Le comportement du noyau, lorsque le PID 1 se termine, est de lancer un *kernel -panic* (car c'est un processus indispensable, notamment de part son rôle de +panic* (car c'est un processus indispensable, notamment de par son rôle de parent pour tous les processus orphelin). Au sein d'un *namespace* `PID` qui n'est pas le *namespace* racine, le noyau appelle la fonction `disable_pid_allocation` qui retire le *flag* `PIDNS_HASH_ADDING` de l'espace diff --git a/tutorial/4/project-intro.md b/tutorial/4/project-intro.md index 91105a3..a6255b8 100644 --- a/tutorial/4/project-intro.md +++ b/tutorial/4/project-intro.md @@ -12,7 +12,7 @@ Vous allez continuer aujourd'hui le projet qui s'étendra depuis le TP précéde et qui consistera à réaliser la partie d'isolation de la moulinette des ACUs ! Cette semaine, il faudra faire en sorte de restreindre un groupe de processus -pour qu'il s'exécute indépendemment de votre système. +pour qu'il s'exécute indépendamment de votre système. Il n'y a pas de restriction sur le langage utilisé, vous pouvez tout aussi bien utiliser du C, du C++, du Python, du shell, etc. diff --git a/tutorial/4/rendu.md b/tutorial/4/rendu.md index ca1c02f..b6c9f23 100644 --- a/tutorial/4/rendu.md +++ b/tutorial/4/rendu.md @@ -62,4 +62,4 @@ sur `rendu4`, ... ce qui vous permet d'avoir une arborescence correspondant à ce qui est demandé, sans pour autant perdre votre travail (ou le rendre plus difficile d'accès). -:::: +::::: diff --git a/tutorial/4/setns-samples.md b/tutorial/4/setns-samples.md index 0152800..9ee4f87 100644 --- a/tutorial/4/setns-samples.md +++ b/tutorial/4/setns-samples.md @@ -38,7 +38,7 @@ main(int argc, char *argv[]) Ce programme prend au minimum deux arguments : - le chemin d'un fichier d'espace de nom que l'on souhaite rejoindre (le chemin vers le lien symbolique donc) ; -- le programme (et ses arguments) que l'on souhaite souhaite exécuter une fois +- le programme (et ses arguments) que l'on souhaite exécuter une fois que l'on a rejoint l'espace de noms ciblé. Dans un premier temps, on ouvre le fichier passé en paramètre afin d'obtenir un diff --git a/tutorial/4/tutorial.md b/tutorial/4/tutorial.md index 478a477..9dc69ee 100644 --- a/tutorial/4/tutorial.md +++ b/tutorial/4/tutorial.md @@ -14,6 +14,6 @@ abstract: | Les exercices de ce cours sont à rendre au plus tard le mardi 15 novembre 2022 à 23 h 42. Consultez les sections matérialisées par un - bandeau jaunes et un engrenage pour plus d'informations sur les + bandeau jaune et un engrenage pour plus d'informations sur les éléments à rendre. ... diff --git a/tutorial/containers/overview.md b/tutorial/containers/overview.md index 97e71b4..908b339 100644 --- a/tutorial/containers/overview.md +++ b/tutorial/containers/overview.md @@ -62,9 +62,9 @@ Les conteneurs On parle d'un conteneur pour désigner une instance en cours d'exécution. -Lorsqu'on lance un conteneur, une copie de l'image est créée sur le disque, -puis le système crée une isolation, pour contenir et restreindre l'exécution -aux seules données de l'image. +Lorsqu'on lance un conteneur, une couche lecture/écriture est créée à partir +de l'image, puis le système crée une isolation, pour contenir et restreindre +l'exécution aux seules données de l'image. Les conteneurs sont par nature **immuables** : on exécute le contenu d'une image déjà construite, on n'y change pas le code qui est exécuté et on n'y fait @@ -90,6 +90,6 @@ avec son historique (la manière dont il a été installé, les mises à jour qu ont été appliquées, les configurations modifiées et les données qui ont été apportées au fil du temps ...). On ne peut pas dans ces circonstances remplacer un conteneur système par un autre, tout comme on ne peut pas -remplacer une machine virtuelle que l'on a installée et configuré à la main. +remplacer une machine virtuelle que l'on a installée et configurée à la main. ::::: diff --git a/tutorial/devops/ci-about-webhook.md b/tutorial/devops/ci-about-webhook.md index b47a42f..e661836 100644 --- a/tutorial/devops/ci-about-webhook.md +++ b/tutorial/devops/ci-about-webhook.md @@ -3,7 +3,7 @@ #### Que fait Drone pour « surveiller » un dépôt ? {-} \ -Grâce aux permissions de que Drone a récupéré lors de la connexion OAuth à +Grâce aux permissions que Drone a récupéré lors de la connexion OAuth à Gitea, il peut non seulement lire et récupérer le code des différents dépôts auxquels vous avez accès, mais il peut aussi changer certains paramètres. @@ -17,5 +17,5 @@ dépôt, sous l'onglet *Déclencheurs Web*. À chaque fois qu'un événement va se produire sur le dépôt, Gitea va prévenir Drone qui décidera si l'évènement doit conduire à lancer l'intégration continue -ou non, selon les instructions qu'on lui a donné dans la configuration du +ou non, selon les instructions qu'on lui a données dans la configuration du dépôt. diff --git a/tutorial/devops/ci-tags.md b/tutorial/devops/ci-tags.md index 4be06dc..a9a8d05 100644 --- a/tutorial/devops/ci-tags.md +++ b/tutorial/devops/ci-tags.md @@ -6,7 +6,7 @@ lors que la compilation est terminée, car nous n'en faisons rien. ::::: {.exercice} -Ajoutons donc une nouvelle règle à notre `.droneci.yml` pour placer le binaire +Ajoutons donc une nouvelle règle à notre `.drone.yml` pour placer le binaire au sein de la liste des fichiers téléchargeables aux côtés des tags. Vous aurez sans doute besoin de : diff --git a/tutorial/devops/devops.md b/tutorial/devops/devops.md index 3628dea..41cebc1 100644 --- a/tutorial/devops/devops.md +++ b/tutorial/devops/devops.md @@ -13,7 +13,7 @@ en tête.\ Ces contraintes : tant liées à la **sécurité** (il faut s'assurer qu'un service n'utilise pas une bibliothèque vulnérable par exemple, donc soit utilisé sur un système à jour, et qu'il ne tourne pas en `root`), qu'à la -**disponibilité** (si le service est mal codé est contient beaucoup de fuites +**disponibilité** (si le service est mal codé et contient beaucoup de fuites mémoire, il ne faut pas que les autres services présents sur la même machine en pâtissent). @@ -29,7 +29,7 @@ Le même principe est aussi valable pour Python, Ruby, ... : les développeurs ont toujours eu tendance à vouloir utiliser les dernières améliorations d'un langage, mais les administrateurs système n'ont alors pas de paquets stables dans la distribution. En effet, les distributions stables telles que Debian, -RedHat ou CentOS ont des cycles de vie assez long et se concentrent plus sur la +RedHat ou CentOS ont des cycles de vie assez longs et se concentrent plus sur la stabilité.\ Cette stabilité est obtenue grâce à l'utilisation de versions éprouvées des langages et des bibliothèques, qui assurent un temps de maintenance et de @@ -197,6 +197,6 @@ conçu par Netflix, qui est un programme qui va casser de manière aléatoire de éléments de l'environnement de production. Le but est de provoquer sciemment des pannes, des latences, ... à n'importe quel niveau du produit, afin d'en tester (brutalement certes) sa résilience. Cela oblige les développeurs, les -opérationnels et les architectes à concevoir des services hautement tolérant +opérationnels et les architectes à concevoir des services hautement tolérants aux pannes, ce qui fait que le jour où une véritable panne survient, elle n'a aucun impact sur la production (enfin on espère !). diff --git a/tutorial/devops/publish-docker-end-gistre.md b/tutorial/devops/publish-docker-end-gistre.md index 4130bb6..e1ce34a 100644 --- a/tutorial/devops/publish-docker-end-gistre.md +++ b/tutorial/devops/publish-docker-end-gistre.md @@ -1,4 +1,4 @@ ### Et ensuite ? Nous avons vu une manière possible de distribuer notre projet. Essayons-en une -autre parmis celles proposées. +autre parmi celles proposées. diff --git a/tutorial/devops/publish-docker-end.md b/tutorial/devops/publish-docker-end.md index f9473d3..b63846c 100644 --- a/tutorial/devops/publish-docker-end.md +++ b/tutorial/devops/publish-docker-end.md @@ -7,7 +7,7 @@ Vous pouvez néanmoins tester les plugins [`scp`](http://plugins.drone.io/appleboy/drone-scp/) ou [`ansible`](http://plugins.drone.io/drone-plugins/drone-ansible/) si vous avez une machine virtuelle avec une connexion SSH. N'hésitez pas à l'ajouter à votre -`.droneci.yml`. +`.drone.yml`. ### Profitons ! diff --git a/tutorial/devops/renovate-cmd.md b/tutorial/devops/renovate-cmd.md index cc54e01..a3d5552 100644 --- a/tutorial/devops/renovate-cmd.md +++ b/tutorial/devops/renovate-cmd.md @@ -12,7 +12,7 @@ La commande que nous allons utiliser pour lancer Renovatebot est la suivante :
```shell docker container run --name renovate --network my_ci_net \ - -e RENOVATE_ENDPOINT="http://gitea:3000/api/v1/" RENOVATE_PLATFORM=gitea \ + -e RENOVATE_ENDPOINT="http://gitea:3000/api/v1/" -e RENOVATE_PLATFORM=gitea \ -e RENOVATE_TOKEN -e RENOVATE_GIT_AUTHOR="Renovatebot " \ -e RENOVATE_AUTODISCOVER=true -e RENOVATE_LOG_LEVEL=info -d \ renovate/renovate diff --git a/tutorial/devops/renovate-end.md b/tutorial/devops/renovate-end.md index 348ca59..8201cc4 100644 --- a/tutorial/devops/renovate-end.md +++ b/tutorial/devops/renovate-end.md @@ -2,7 +2,7 @@ Dès que le conteneur sera lancé, nous devrions voir apparaître une ou plusieu *pull-requests* pour le projet `youp0m`. Si votre CI est configurée correctement, des tests automatiques seront lancés. -Le conteneur s'arrête dès qu'il a terminé d'analysé tous les dépôts. Vous +Le conteneur s'arrête dès qu'il a terminé d'analyser tous les dépôts. Vous devrez le relancer si vous attendez une nouvelle action de la part de Renovatebot. Il est courant de le lancer entre chaque heure et 2 ou 4 fois par jour. @@ -18,7 +18,7 @@ consultez la liste des éléments de configuration : Ne soyez pas effrayé par la liste interminable d'options. Il est vrai que la première fois, on peut se sentir submergé de possibilités, mais il faut noter -que le projet arriver avec des options par défaut plutôt correctes, et que l'on +que le projet arrive avec des options par défaut plutôt correctes, et que l'on peut facilement avoir une configuration commune pour tous nos dépôts, à travers les *presets*. @@ -26,7 +26,7 @@ Un certain nombre de *presets* sont distribués par défaut, voici la liste (humainement lisible cette fois) : -Voici un exemple de configuration que vous pouvez utilisé comme base de tous +Voici un exemple de configuration que vous pouvez utiliser comme base de tous vos projets :
@@ -69,7 +69,7 @@ Voici un exemple de fichier `default.json` que vous pourriez vouloir utiliser : Attention, on ne le répétera jamais assez, mais Renovatebot peut vite devenir infernal, car il va créer de nombreuses *pull-requests*, inlassablement. Il convient de rapidement activer la fusion automatique des mises à jour pour -lesquelles vous avez confiances et pour lesquelles vous ne feriez qu'appuyer +lesquelles vous avez confiance et pour lesquelles vous ne feriez qu'appuyer sur le bouton de fusion, sans même tester vous-même. La fonctionnalité est décrite en détail dans la documentation[^RENOVATE_AUTOMERGE] et explique les différentes stratégies. Néanmoins, il est nécessaire d'avoir une bonne suite de diff --git a/tutorial/devops/renovate.md b/tutorial/devops/renovate.md index a97a123..11a33e3 100644 --- a/tutorial/devops/renovate.md +++ b/tutorial/devops/renovate.md @@ -1,13 +1,13 @@ Autres outils indispensables ---------------------------- -### Maintient à jour des dépendances +### Maintien à jour des dépendances Une opération fastidieuse, souvent oubliée sitôt le projet envoyé en production, c'est la mise à jour des dépendances applicatives. Fastidieux car il faut d'une part être informé qu'une mise à jour est disponible, c'est-à-dire qu'il faut suivre les mails, parfois nombreux, informant des nouvelles -*releases*, parfois il s'agir de newslettre, ou encore parfois aucune +*releases*, parfois il s'agit de newsletters, ou encore parfois aucune notification ne peut être programmée, il faut se rendre régulièrement sur un site pour savoir si oui ou non une mise à jour est disponible. diff --git a/tutorial/devops/run-gistre.md b/tutorial/devops/run-gistre.md index fbd71fd..0acc286 100644 --- a/tutorial/devops/run-gistre.md +++ b/tutorial/devops/run-gistre.md @@ -64,7 +64,7 @@ accès au périphérique correspondant au compteur. ### Conteneur LXC -LXC peut s'utiliser de multiple manière différentes, y compris avec des images +LXC peut s'utiliser de multiples manières différentes, y compris avec des images OCI. Choisissez la méthode qui vous semble la plus appropriée, il est attendu au moins un script pour lancer notre conteneur, s'il est différent d'un diff --git a/tutorial/devops/tools-drone-runner-ansible.md b/tutorial/devops/tools-drone-runner-ansible.md index 945aab6..0f4db91 100644 --- a/tutorial/devops/tools-drone-runner-ansible.md +++ b/tutorial/devops/tools-drone-runner-ansible.md @@ -2,7 +2,7 @@ Voici à quoi pourrait ressembler le playbook Ansible démarrant notre agent Dro
```yaml -- name: Launch drone runer +- name: Launch drone runner docker_container: name: droneci-runner image: "drone/drone-runner-docker:1" diff --git a/tutorial/devops/what-gistre.md b/tutorial/devops/what-gistre.md index f0f0a89..92a7c01 100644 --- a/tutorial/devops/what-gistre.md +++ b/tutorial/devops/what-gistre.md @@ -44,10 +44,10 @@ fundation*, notamment les [Compute Module 3 et 4](https://www.raspberrypi.com/products/compute-module-4/) et les [Raspberry Pi Zero 2 W](https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/), ainsi que de nombreux PCB fait par l'entreprise, à base de micro-contrôleurs AVR, -lorsqu'il est nécessaire de pour s'interfacer avec des équipements +lorsqu'il est nécessaire pour s'interfacer avec des équipements propriétaires non prévu pour l'immotique. -Une grosse partie des travaux est donc réalisé avec un noyau Linux, sur du +Une grosse partie des travaux est donc réalisée avec un noyau Linux, sur du matériel très performant, pour de l'embarqué. \ @@ -68,7 +68,7 @@ entraver la stabilité de la plate-forme en cas de déploiement d'un module défaillant. Vous êtes également chargés de jeter les bases du système d'intégration continu -des modules. (La partie déploiement continu, sera réalisé plus tard par +des modules. (La partie déploiement continu, sera réalisée plus tard par l'équipe développant le nouveau système de base, suivant le meilleur outil que vous retiendrez.) \ @@ -90,5 +90,5 @@ quelques tests automatiques. Puis nous publierons automatiquement le binaire `linky2influx` comme fichier associé à un tag au sein de l'interface web du gestionnaire de versions. -Nous testerons enfin différentes solution pour déployer notre binaire, afin +Nous testerons enfin différentes solutions pour déployer notre binaire, afin d'établir quelle est la solution adéquate. diff --git a/tutorial/devops/what.md b/tutorial/devops/what.md index 2b8cb33..6264ef7 100644 --- a/tutorial/devops/what.md +++ b/tutorial/devops/what.md @@ -13,7 +13,7 @@ le projet `youp0m`, que l'on connaît déjà bien. \ Dans un premier temps, on voudra juste compiler notre projet, pour s'assurer -que chaque *commmit* poussé ne contient pas d'erreur de compilation (dans +que chaque *commit* poussé ne contient pas d'erreur de compilation (dans l'environnement défini comme étant celui de production, donc avec une version précise des outils de compilation). Ensuite, nous ajouterons quelques tests automatiques, puis nous publierons automatiquement le binaire `youp0m` comme diff --git a/tutorial/docker-advanced/manual.md b/tutorial/docker-advanced/manual.md index a63c5f9..f34bb9b 100644 --- a/tutorial/docker-advanced/manual.md +++ b/tutorial/docker-advanced/manual.md @@ -32,7 +32,7 @@ docker container run -p 8086:8086 -d --name mytsdb influxdb:1.8 ::::: {.warning} Remarquez que nous n'utilisons pas la version 2 d'InfluxDB. Sa mise en -place est plus contraignantes pour faire de simples tests. Si vous +place est plus contraignante pour faire de simples tests. Si vous souhaitez tout de même utiliser la dernière version de la stack TICK, vous pouvez consulter le `README` du conteneur sur le Docker Hub :\ diff --git a/tutorial/docker-advanced/security.md b/tutorial/docker-advanced/security.md index b819899..9cfb724 100644 --- a/tutorial/docker-advanced/security.md +++ b/tutorial/docker-advanced/security.md @@ -59,7 +59,7 @@ difficulté du rebond. Un certain nombre de capabilities Linux sont retirées par Docker au moment de l'exécution du conteneur, on peut utiliser les options -`--cap-add` et `--cap-drop` pour respectivement ajouter et retirer une +`--cap-add` et `--cap-drop` pour respectivement ajouter et retirer des capabilities. Notez que l'option `--privileged` ne retire aucune capabilities à diff --git a/tutorial/docker-advanced/setup.md b/tutorial/docker-advanced/setup.md index f522390..3de172e 100644 --- a/tutorial/docker-advanced/setup.md +++ b/tutorial/docker-advanced/setup.md @@ -12,7 +12,7 @@ communauté, et parfois même appropriées par Docker. Dans cette partie, nous allons avoir besoin du plugin `docker-compose`. L'équipe en charge du projet met à disposition un exécutable que nous pouvons -téléchargeant depuis . +télécharger depuis . Ajoutez l'exécutable dans le dossier des plugins : `$HOME/.docker/cli-plugins` (sans oublier de `chmod +x` !). @@ -21,7 +21,7 @@ Ajoutez l'exécutable dans le dossier des plugins : `$HOME/.docker/cli-plugins` Autrefois, `docker-compose` était un script tiers que l'on utilisait indépendamment de Docker. Le projet, historiquement écrit en Python, a été -entièrement réécrit récemment afin qu'il s'intégre mieux dans l'écosystème. +entièrement réécrit récemment afin qu'il s'intègre mieux dans l'écosystème. Vous trouverez encore de nombreux articles vous incitant à utiliser `docker-compose`. Dans la plupart des cas, vous pouvez simplement remplacer par diff --git a/tutorial/docker-advanced/what.md b/tutorial/docker-advanced/what.md index 63511e3..b86558e 100644 --- a/tutorial/docker-advanced/what.md +++ b/tutorial/docker-advanced/what.md @@ -44,5 +44,5 @@ s'agit d'un mécanisme de séries temporelles (*Time Series*) moderne, que l'on peut utiliser pour stocker toute sorte de données liées à un indice temporel. La pile logicielle TICK propose de collecter des métriques, en les enregistrant -dans une base de données adaptées et permet ensuite de les ressortir sous +dans une base de données adaptée et permet ensuite de les ressortir sous forme de graphiques ou de les utiliser pour faire des alertes intelligentes. diff --git a/tutorial/docker-basis/debug.md b/tutorial/docker-basis/debug.md index 26a82c9..875e9b1 100644 --- a/tutorial/docker-basis/debug.md +++ b/tutorial/docker-basis/debug.md @@ -13,7 +13,7 @@ Consulter les journaux ---------------------- La première étape consiste bien souvent à regarder ce que le conteneur affiche -sur ses sorties standard et d'erreur. Lorsqu'il est lancé en monde *daemon*, il +sur ses sorties standard et d'erreur. Lorsqu'il est lancé en mode *daemon*, il convient d'utiliser la commande :
@@ -76,7 +76,7 @@ docker container top cntr_name ```
-Cela liste tous les processus rattaché au conteneur nommé : à la fois les +Cela liste tous les processus rattachés au conteneur nommé : à la fois les processus démarrés par le `run`, mais également les éventuels processus rattachés par `exec`. diff --git a/tutorial/docker-basis/ex-flask-volume.md b/tutorial/docker-basis/ex-flask-volume.md index a64d22a..5a9c4ee 100644 --- a/tutorial/docker-basis/ex-flask-volume.md +++ b/tutorial/docker-basis/ex-flask-volume.md @@ -38,9 +38,9 @@ ici, puisque c'est ce volume qui assure la persistance des images. ::::: -Nos images sont bien persistantes d'une instance à l'autre de notre contenu. +Nos images sont bien persistantes d'une instance à l'autre de notre conteneur. -Nous voici prêt à déployer en production notre service, sans crainte de perdre +Nous voici prêts à déployer en production notre service, sans crainte de perdre les jolies contributions. Mais... est-ce que ce sera suffisant pour répondre aux milliers de visiteurs attendus ? diff --git a/tutorial/docker-basis/ex-flask.md b/tutorial/docker-basis/ex-flask.md index 1fa7159..31426c7 100644 --- a/tutorial/docker-basis/ex-flask.md +++ b/tutorial/docker-basis/ex-flask.md @@ -42,16 +42,16 @@ docker container run --publish 8080:8080 registry.nemunai.re/youp0m
Cet argument va faire effectuer à Docker une étape supplémentaire lorsqu'il -démarerra le conteneur : il va devoir mettre en place une redirection du port +démarrera le conteneur : il va devoir mettre en place une redirection du port de notre système local (8080) vers le port 8080 du conteneur. ![Le port 8080 est redirigé vers le conteneur](published-ports.png "Le port 8080 est redirigé vers le conteneur"){ width=70% } ::::: {.question} -#### Peut-on démarrer plusieurs conteurs utilisant le même port de notre système local ? {-} +#### Peut-on démarrer plusieurs conteneurs utilisant le même port de notre système local ? {-} -Si l'on essai de lancer deux fois la commande de notre dernier `run`, nous +Si l'on essaie de lancer deux fois la commande de notre dernier `run`, nous obtenons l'erreur suivante :
diff --git a/tutorial/docker-basis/first.md b/tutorial/docker-basis/first.md index 170e21c..d2ace99 100644 --- a/tutorial/docker-basis/first.md +++ b/tutorial/docker-basis/first.md @@ -33,7 +33,7 @@ Le daemon assemble ensuite l'image et met en place les différents éléments d'isolation pour préparer l'exécution de notre conteneur. Enfin, il lance la commande qui sera le premier processus du conteneur. Cette -commande fait parti des métadonnées de l'image. Le processus ainsi lancé est un +commande fait partie des métadonnées de l'image. Le processus ainsi lancé est un peu particulier : il obtient les mêmes caractéristiques que le PID 1 de notre système ('init'). @@ -57,7 +57,7 @@ afficher beaucoup de contenu pour faire son choix. Aussi, il est souvent plus pratique d'aller explorer les registres en passant directement par leur interface web. -Vous trouverez forcément votre bonheur parmi les images proposées par les deux +Vous trouverez forcément votre bonheur parmi les images proposées par les trois principaux registres : - @@ -358,7 +358,7 @@ c'est toujours le daemon qui exécute directement les commandes et gère les entrées et sorties standards et d'erreur. Avec l'option `--interactive`, on s'assure que l'entrée standard ne sera pas fermée (`close(2)`). Nous demandons également l'allocation d'un TTY, sans quoi `bash` ne se lancera pas en mode -interractif[^bashnointer]. +interactif[^bashnointer]. [^bashnointer]: Mais il sera possible de l'utiliser sans allouer de TTY, comme dans cet exemple : diff --git a/tutorial/docker-basis/installation.md b/tutorial/docker-basis/installation.md index c3f2bea..493eedd 100644 --- a/tutorial/docker-basis/installation.md +++ b/tutorial/docker-basis/installation.md @@ -54,7 +54,7 @@ distribution : ### Sous Windows et macOS -Bien que les fonctionnalités de contenerisation de Docker que nous utiliserons +Bien que les fonctionnalités de conteneurisation de Docker que nous utiliserons ne soient disponibles que sous Linux, il est possible d'utiliser Docker de manière déportée : le daemon Docker tournera dans une machine virtuelle Linux, mais vous pourrez interagir avec lui via votre ligne de commande habituelle. diff --git a/tutorial/docker-basis/linking-ex-fic.md b/tutorial/docker-basis/linking-ex-fic.md index 003c83c..18f2200 100644 --- a/tutorial/docker-basis/linking-ex-fic.md +++ b/tutorial/docker-basis/linking-ex-fic.md @@ -8,7 +8,7 @@ indiquent que le service cherche à se connecter à une base de données. Il va donc falloir lier notre interface d'administration à [un conteneur MariaDB](https://hub.docker.com/_/mariadb). -Ne vous embêtez pas avec les mots de passes des services, initialisez la base +Ne vous embêtez pas avec les mots de passe des services, initialisez la base de données avec le nom d'utilisateur et le mot de passe par défaut. Vous les obtiendrez en lisant la documentation de l'image fic-admin : diff --git a/tutorial/docker-basis/volumes.md b/tutorial/docker-basis/volumes.md index 882538a..ddceb85 100644 --- a/tutorial/docker-basis/volumes.md +++ b/tutorial/docker-basis/volumes.md @@ -3,12 +3,12 @@ Stockage de données applicatives ================================ -Il est généralement toujours possible d'écrire dans le système de fichier de +Il est généralement toujours possible d'écrire dans le système de fichiers de notre conteneur. (Cela n'affecte pas l'image, chaque conteneur est démarré à partir de l'image originale.) Cependant, il n'est pas recommandé de chercher à stocker des données ainsi. En effet, il n'est pas aisé de récupérer ces données une fois l'exécution du conteneur terminée ; les données peuvent même être -détruite si on a lancé le conteneur avec l'option `--rm`. +détruites si on a lancé le conteneur avec l'option `--rm`. Docker met donc à notre disposition plusieurs mécanismes pour que les données de nos applications persistent et soient prêtes à être migrées d'un conteneur à diff --git a/tutorial/docker-basis/what.md b/tutorial/docker-basis/what.md index 567b48b..eee7cda 100644 --- a/tutorial/docker-basis/what.md +++ b/tutorial/docker-basis/what.md @@ -3,14 +3,14 @@ Composition de Docker Docker est une suite d'outils de haut niveau, permettant d'utiliser des *conteneurs*. Le projet en lui-même utilise de nombreuses dépendances, -originellement développées par l'entreprise Docker Inc., puis laissé dans le +originellement développées par l'entreprise Docker Inc., puis laissées dans le domaine public lors des efforts de standardisation en 2015. Commençons par planter le décor, en détaillant les principes de base de Docker. ### Séparation des compétences -Le projet s'article autour d'un daemon lancé au démarrage de la machine, avec +Le projet s'articule autour d'un daemon lancé au démarrage de la machine, avec lequel on interagit via un client (le programme `docker`). La communication entre le daemon et le client s'effectuant sur une API REST généralement au travers d'une socket. @@ -71,7 +71,7 @@ de nombreuses directions, chacun voulant tirer la couverture vers soi, et l'équipe maintenant le projet a parfois eu du mal à arbitrer les bonnes choses à ajouter ou non au projet. -Afin de pallier aux besoins complémentaires, parfois accessoires, parfois +Afin de pallier les besoins complémentaires, parfois accessoires, parfois salvateurs, un système de plugins a été intégré. Il permet d'appeler d'autres programmes comme s'il s'agissait de composants de Docker. @@ -85,7 +85,7 @@ utilisateurs de notre machine ou dans `$HOME/.docker/` si l'on veut l'installer seulement pour nous. Par exemple, les plugins ajoutant des commandes iront dans -`$HOME/.docker/cli-plugins`. Par exemple, si l'on souhaite pouvoir disposer de +`$HOME/.docker/cli-plugins`. Si l'on souhaite pouvoir disposer de la commande `docker compose`, on téléchargera le plugin vers l'emplacement : `$HOME/.docker/cli-plugins/docker-compose`. diff --git a/tutorial/docker-internals/clair.md b/tutorial/docker-internals/clair.md index 6fad5c5..7f2c0be 100644 --- a/tutorial/docker-internals/clair.md +++ b/tutorial/docker-internals/clair.md @@ -2,7 +2,7 @@ Un outil complet pour indexer et chercher des vulnérabilités est [`Clair`](https://github.com/coreos/clair/), du projet CoreOS. À partir des -informations mises à disposition par les équipes de sécurités des principales +informations mises à disposition par les équipes de sécurité des principales distributions, cela alimente en continu une base de données qui sera accédé au moment de l'analyse. @@ -57,7 +57,7 @@ export POSTGRES_PASSWORD=$(openssl rand -base64 16) Parmi les volumes partagés avec `clair`, il y a un dossier `./clair_config`. Notez le `./` au début, qui indique que le dossier sera -recherché relativement par rapport à l'emplacement du `docker-compsose.yml`. +recherché relativement par rapport à l'emplacement du `docker-compose.yml`. Dans ce dossier, vous devez placer un exemplaire du fichier de configuration dont un [exemple se trouve dans le dépôt du diff --git a/tutorial/docker-internals/oci.md b/tutorial/docker-internals/oci.md index 06cd5c9..1737319 100644 --- a/tutorial/docker-internals/oci.md +++ b/tutorial/docker-internals/oci.md @@ -4,7 +4,7 @@ Open Container Initiative ========================= 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 +standard commun aux programmes de conteneurisation, afin d'éviter une fragmentation de l'écosystème. ## Spécifications @@ -101,7 +101,7 @@ est utilisé pour sélectionner le bon manifest correspondant au système. Le format des [couches de système de fichiers](https://github.com/opencontainers/image-spec/blob/master/layer.md) -sont spécifiées : il est nécessaire de passer par des formats standards (comme +est spécifié : il est nécessaire de passer par des formats standards (comme les tarballs), contenant éventuellement des fichiers et dossiers spéciaux représentant les modifications ou les suppressions éventuelles de la couche. @@ -125,5 +125,5 @@ Cela permet de récupérer des images, mais aussi d'en envoyer, en gérant \ -Nous allons voir plus en détails, dans les chapitres suivantes, ce que l'on +Nous allons voir plus en détails, dans les chapitres suivants, ce que l'on peut tirer de ces spécifications, en décortiquant des usages précis. diff --git a/tutorial/docker-internals/setup.md b/tutorial/docker-internals/setup.md index c24d492..6e8f6c1 100644 --- a/tutorial/docker-internals/setup.md +++ b/tutorial/docker-internals/setup.md @@ -3,7 +3,7 @@ Mise en place ============= -Les exercices suivants nécessiteront l'installation de plusieurs outils.. +Les exercices suivants nécessiteront l'installation de plusieurs outils. - `docker-compose` - `venv` diff --git a/tutorial/docker-internals/tini.md b/tutorial/docker-internals/tini.md index 17e8788..f108166 100644 --- a/tutorial/docker-internals/tini.md +++ b/tutorial/docker-internals/tini.md @@ -14,7 +14,7 @@ exécution. Puis, lorsqu'il aura terminé, celui-ci sera passé dans un statut Parmi ses attributions, `init`, le PID 1 de notre système, est le processus qui récupère les processus orphelins du système. Lorsque le parent direct d'un -processus meurt, ses fils sont reparenté sous le processus `init` et ils +processus meurt, ses fils sont reparentés sous le processus `init` et ils obtiennent alors comme `ppid` 1. Ils ne conservent pas le PID de leur défunt parent. @@ -29,7 +29,7 @@ l'argument `PR_SET_CHILD_SUBREAPER`. ::::: Docker procure une isolation, notamment au travers du *namespace* PID : les -processus faisant parti du même *namespace* ne voient seulement qu'une partie +processus faisant partie du même *namespace* ne voient seulement qu'une partie de l'arbre de processus de l'hôte, et notamment, un PID 1 est recréé, il s'agit du premier processus à s'exécuter dans le *namespace*. @@ -107,7 +107,7 @@ shell. 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. +retournera pas le code d'erreur de la commande que l'on a lancée, mais plutôt 0. ## Intégration dans les `Dockerfile` @@ -121,7 +121,7 @@ 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 +pas être gérés 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 diff --git a/tutorial/docker-internals/vulnerability-scan.md b/tutorial/docker-internals/vulnerability-scan.md index f224578..7c40863 100644 --- a/tutorial/docker-internals/vulnerability-scan.md +++ b/tutorial/docker-internals/vulnerability-scan.md @@ -152,7 +152,7 @@ the selected base image
Ce dernier exemple est sans appel : `mysql` est une image officielle, et sa -dernière version à l'écriture de ses lignes contient pas moins de 24 +dernière version à l'écriture de ces lignes contient pas moins de 24 vulnérabilités dont 9 *high* (pourtant corrigées dans des versions suivantes). @@ -216,7 +216,7 @@ Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0) ```
-Nous pouvons remarque que Trivy, en plus de faire l'analyse statique des +Nous pouvons remarquer que Trivy, en plus de faire l'analyse statique des vulnérabilités de l'image, a aussi fait une analyse des dépendances du binaire `/srv/youp0m`. diff --git a/tutorial/docker-orchestration/setup.md b/tutorial/docker-orchestration/setup.md index a113b80..1ed3bfd 100644 --- a/tutorial/docker-orchestration/setup.md +++ b/tutorial/docker-orchestration/setup.md @@ -33,7 +33,7 @@ chmod +x /usr/bin/docker-machine ### Support de KVM -Le programme support de base de nombreux environnement, dont VirtualBox et +Le programme supporte de base de nombreux environnements, dont VirtualBox et Hyper-V. Bien d'autres environnements peuvent être supportés, au moyen de plug-ins. diff --git a/tutorial/docker-orchestration/stack.md b/tutorial/docker-orchestration/stack.md index 9219bc0..c8cb5ad 100644 --- a/tutorial/docker-orchestration/stack.md +++ b/tutorial/docker-orchestration/stack.md @@ -54,7 +54,7 @@ iyue3rgd0ohs myWebS replicated 1/1 nginx:latest
Vous pouvez constater que sur l'un des nœuds, sur lequel votre serveur aura été -déployé, le tâche apparaît dans la liste des conteneurs ! +déployé, la tâche apparaît dans la liste des conteneurs ! Rien de très excitant pour le moment, car nous ne pouvons pas vraiment accéder @@ -86,8 +86,8 @@ particulièrement. Essayons de nous connecter aux ports 80 des deux IP correspondant à nos deux nœuds. Vous devriez voir la même page. -Lorsque plusieurs tâches s'exécutent pour ce service, le nœud d'entrée choisi -selon un round-robin à quelle tâche il va diriger la requête. C'est grâce à ce +Lorsque plusieurs tâches s'exécutent pour ce service, le nœud d'entrée choisit +selon un round-robin vers quelle tâche il va diriger la requête. C'est grâce à ce mécanisme qu'il est possible de faire de la répartition de charge très simplement. @@ -103,7 +103,7 @@ consulter la documentation à ce sujet :\ On parle depuis tout à l'heure de lancer plusieurs tâches pour le même service. La mise à l'échelle, c'est ça : exécuter plusieurs conteneurs pour la -même tâche afin de mieux répartir la charge, idéalement sur des machines +même service afin de mieux répartir la charge, idéalement sur des machines physiques différentes. Ce qui se fait souvent avec beaucoup de douleur hors de Docker, se résume ici @@ -172,5 +172,5 @@ services:
Certaines informations comme les ressources, permettent à l'orchestrateur de -mieux choisir le *workers* de destination, en fonction de certaines de ses +mieux choisir le *worker* de destination, en fonction de certaines de ses caractéristiques. diff --git a/tutorial/docker-orchestration/swarm.md b/tutorial/docker-orchestration/swarm.md index e2f2ae6..ea18eca 100644 --- a/tutorial/docker-orchestration/swarm.md +++ b/tutorial/docker-orchestration/swarm.md @@ -7,7 +7,7 @@ Regroupés au sein d'un cluster (on parle de *swarm* pour Docker), chaque *Docker engine* représente un nœud (*node*) dans lequel on va déployer des *services*. -Certain nœuds ont un rôle de *manager*, parmi ceux-ci, un seul est élu leader et +Certains nœuds ont un rôle de *manager*, parmi ceux-ci, un seul est élu leader et prendra les décisions d'orchestration. Les autres sont là pour prendre le relais en cas de dysfonctionnement sur le manager élu. diff --git a/tutorial/k8s/discover.md b/tutorial/k8s/discover.md index bc8dd58..eab74d1 100644 --- a/tutorial/k8s/discover.md +++ b/tutorial/k8s/discover.md @@ -26,7 +26,7 @@ Les `type`s que vous pouvez découvrir sont ceux que l'on a vu à la section précédente : `node`, `pod`, ... La commande `describe` permet d'afficher l'état tel qu'il est attendu -et tel qu'il est actuellement (cela permet de se rendre lorsque les +et tel qu'il est actuellement (cela permet de se rendre compte lorsque les deux divergent). @@ -110,7 +110,7 @@ kindnet-2gwlp 1/1 Running 0 13m ``` Eh oui ! De nombreux services de base de Kubernetes tournent dans des -conteneurs... qu'il gèren lui-même ! Notamment : +conteneurs... qu'il gère lui-même ! Notamment : - `etcd` : notre base de données clef/valeur, - `kube-apiserver` : l'API REST avec qui communique `kubectl`, @@ -166,7 +166,7 @@ kubectl logs -f pingpong Notez ici l'option -f qui permet de suivre les logs en direct. -Notre premier test ayant réussi, nous pouvons arrêter de DDos Cloudflare : +Notre premier test ayant réussi, nous pouvons arrêter de DDoS Cloudflare : ```bash kubectl delete pods pingpong @@ -211,16 +211,16 @@ haut niveau et sont là pour s'assurer que les migrations se font en douceur : elles vont permettre de basculer progressivement les *pod*s d'une version X à une version Y (par exemple si l'on change notre ping d'alpine 3.16 vers alpine edge), mais éventuellement de revenir sur la version X si besoin, en cours de -migration. Elles délèguent ensuite aux *replicatsets* la gestion des *pod*s. +migration. Elles délèguent ensuite aux *replicasets* la gestion des *pod*s. -Le *replicatset* est là pour indiquer le nombre de *pod*s que l'on désire et +Le *replicaset* est là pour indiquer le nombre de *pod*s que l'on désire et s'assurer que le nombre de *pod*s actuellement lancé est bien en adéquation avec le nombre de *pod*s attendu. \ Pour résumer : `kubectl` a créé une tâche de déploiement -`deploy/pingpong`. Cette tâche de déploiement a créé elle-même un *replicatset* -`rs/pingpong-xxxx`. Ce *replicatset* a créé un *pod* `po/pingpong-yyyy`. +`deploy/pingpong`. Cette tâche de déploiement a créé elle-même un *replicaset* +`rs/pingpong-xxxx`. Ce *replicaset* a créé un *pod* `po/pingpong-yyyy`. #### Passage à l'échelle : facile ? @@ -232,8 +232,8 @@ kubectl scale deploy/pingpong --replicas 3 ``` À ce stade, comme nous ne modifions que le nombre de replicats, Kubernetes va -tout simplement propager ce nombre au *replicatset* existant. Puis, le -*replicatset* voyant un décalage entre le nombre de *pod*s attendus et le nombre +tout simplement propager ce nombre au *replicaset* existant. Puis, le +*replicaset* voyant un décalage entre le nombre de *pod*s attendus et le nombre de *pod*s en cours d'exécution, il va en lancer de nouveaux, afin de répondre à la demande. \ @@ -245,11 +245,11 @@ kubectl delete pod pingpong-yyyy-zzz ``` Cela supprime bien un *pod*, mais un autre est relancé instantanément car le -*replicatset* constate une différence dans le nombre attendu. +*replicaset* constate une différence dans le nombre attendu. Si nous voulons arrêter de DDoS Google/Cloudflare, il ne s'agit pas de tuer chacun des *pod*s un par un, car de nouveaux seraient créés par le -*replicatset*. Si l'on supprime le *replicatset*, la tâche de déploiement en +*replicaset*. Si l'on supprime le *replicaset*, la tâche de déploiement en recréera un similaire (avec de nouveaux *pod*s). Pour arrêter nos conteneurs, il convient donc de supprimer la tâche de diff --git a/tutorial/k8s/overview.md b/tutorial/k8s/overview.md index efd5b7e..6edc811 100644 --- a/tutorial/k8s/overview.md +++ b/tutorial/k8s/overview.md @@ -4,7 +4,7 @@ Vue d'ensemble de Kubernetes *Kubernetes* (prononcé Ku-ber-né-tice[^prononciation-k8s] en grec) est un système *open source* d'orchestration et de gestion de conteneurs. C'est-à-dire qu'il se charge de faire coller constamment la liste des conteneurs qu'il voit -vivant aux spécifications qu'on lui aura demandées. +vivants aux spécifications qu'on lui aura demandées. [^prononciation-k8s]: @@ -37,7 +37,7 @@ d’une série de nœuds *workers*. Le(s) *control-plane(s)* sont en charge de prendre des décisions globales sur le déroulement des opérations du cluster : cela va de la détection d'anomalies -sur le cluster ou encore le traiter d'événements et l'organisation de leur +sur le cluster ou encore le traitement d'événements et l'organisation de leur réponse, ... On retrouve sur ces nœuds centraux les composants suivants : @@ -52,7 +52,7 @@ L'ordonnanceur disponibles. Les contrôleurs -: Ils vont contrôler l'état des différents composants déployées au sein du +: Ils vont contrôler l'état des différents composants déployés au sein du cluster, pour s'assurer d'être dans l'état désiré. Il y a en fait plusieurs contrôleurs ayant chacun la responsabilité de veiller sur une partie des objets, ainsi que le `cloud-controller-manager` lorsque le cluster se trouve @@ -65,11 +65,11 @@ Les contrôleurs \ -Chaque nœud (généralement, le nœud *master* est également *worker*) est utilisé +Chaque nœud (généralement, le nœud *control-plane* est également *worker*) est utilisé via deux composants : `kubelet` -: C'est l'agent qui va se charger de créer les conteneurs et les manager, afin +: C'est l'agent qui va se charger de créer les conteneurs et les gérer, afin de répondre aux spécifications demandées par les *control-planes*. `kube-proxy` @@ -109,14 +109,14 @@ supprimer ou de vérifier qu'une interface va bien. Ainsi, à la création d'un conteneur, Kubernetes va laisser aux plugins CNI le loisir d'ajouter les interfaces réseaux adéquates, d'allouer l'adresse IP, de -configurer les routes, les règles de pare-feu, ... quelque soit +configurer les routes, les règles de pare-feu, ... quelle que soit l'infrastructure et la complexité du réseau utilisé derrière. \ Terminons en ajoutant qu'un serveur DNS faisant autorité est nécessaire pour que, de la même manière que Docker, il soit possible d'accéder aux autres conteneurs via leur nom (sans qu'il ne soit nécessaire de le déclarer sur un -serveur de noms public). Il n'y a pas de projet de porté par Kubernetes pour +serveur de noms public). Il n'y a pas de projet porté par Kubernetes pour cela, mais cette tâche est généralement assurée par [CoreDNS](https://coredns.io/). diff --git a/tutorial/k8s/setup.md b/tutorial/k8s/setup.md index 8cf76db..5e969ac 100644 --- a/tutorial/k8s/setup.md +++ b/tutorial/k8s/setup.md @@ -17,7 +17,7 @@ leurs infrastructures, choisissent de passer par un prestataire. L'entreprise délègue donc la gestion de son/ses cluster(s) à une autre entreprise, dont c'est le cœur de métier. La plupart du temps, il va s'agir d'Amazon (via [Elastic Kubernetes Service](https://aws.amazon.com/fr/eks/)), d'Azure -[Kubernetes +([Kubernetes Service](https://azure.microsoft.com/fr-fr/services/kubernetes-service/)) ou Google ([Kubernetes Engine](https://cloud.google.com/kubernetes-engine/)), mais d'autres acteurs plus petits existent aussi @@ -38,7 +38,7 @@ fonctionne.\ Chaque distribution de *Kubernetes* aura donc pris soin de mettre à disposition des composants pour un usage plus ou moins spécifique. En dehors des composants strictement nécessaires qui ne changent pas, on verra d'une distribution à -l'autre des choix quant au moteur d'exécution de conteneurs (tantot CRI-O, +l'autre des choix quant au moteur d'exécution de conteneurs (tantôt CRI-O, Containerd, KataContainers, ...), le réseau sera géré par une brique spécifique (Flannel, Calico, Canal, Wave, ...), le stockage peut également faire l'objet de choix.\ @@ -147,8 +147,9 @@ Server Version: Version.Info{Major:"1", Minor:"21", GitVersion:"v1.25.3", [...] ```
-Par défaut, `kubectl` va tenter de contacter le port local 2375, `kind` aura -pris soin de l'exposer pour vous au moment de la création du cluster. +Par défaut, `kubectl` va utiliser le fichier `~/.kube/config` pour contacter +l'API du cluster, `kind` aura pris soin de le configurer pour vous au moment +de la création du cluster. ::::: {.warning}