Add content for missing namespaces
This commit is contained in:
parent
ab3341bc54
commit
822dc619b8
7 changed files with 1650 additions and 6 deletions
532
tutorial/4/namespaces-recap.md
Normal file
532
tutorial/4/namespaces-recap.md
Normal file
|
|
@ -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é :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
unshare --mount --pid --fork --mount-proc /bin/bash
|
||||
```
|
||||
</div>
|
||||
|
||||
**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é :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
unshare --mount --uts --ipc --pid --fork --mount-proc /bin/bash
|
||||
```
|
||||
</div>
|
||||
|
||||
**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 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
unshare --mount --uts --ipc --net --pid --fork --mount-proc /bin/bash
|
||||
```
|
||||
</div>
|
||||
|
||||
**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 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
unshare --user --map-root-user \
|
||||
--mount --uts --ipc --net --pid \
|
||||
--fork --mount-proc /bin/bash
|
||||
```
|
||||
</div>
|
||||
|
||||
**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 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
unshare --user --map-root-user \
|
||||
--mount --uts --ipc --net --pid --cgroup \
|
||||
--fork --mount-proc /bin/bash
|
||||
```
|
||||
</div>
|
||||
|
||||
**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*
|
||||
|
||||
<div lang="en-US">
|
||||
```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 <PID> --all [commande]
|
||||
```
|
||||
</div>
|
||||
|
||||
### Inspection des *namespaces*
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
# Lister tous les namespaces du système
|
||||
lsns
|
||||
|
||||
# Lister les namespaces d'un processus spécifique
|
||||
lsns -p <PID>
|
||||
|
||||
# Voir les namespaces d'un processus
|
||||
ls -l /proc/<PID>/ns/
|
||||
|
||||
# Comparer les namespaces de deux processus
|
||||
readlink /proc/<PID1>/ns/net
|
||||
readlink /proc/<PID2>/ns/net
|
||||
```
|
||||
</div>
|
||||
|
||||
### Gestion réseau (namespace network)
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
# Créer un namespace network nommé
|
||||
ip netns add <nom>
|
||||
|
||||
# Lister les namespaces network
|
||||
ip netns list
|
||||
|
||||
# Exécuter une commande dans un namespace network
|
||||
ip netns exec <nom> <commande>
|
||||
|
||||
# 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 <nom>
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
## Appels système
|
||||
|
||||
Pour les développeurs, voici les appels système principaux :
|
||||
|
||||
<div lang="en-US">
|
||||
```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/<PID>/ns/<type>
|
||||
// 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);
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
## 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/<PID>/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/<PID>/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 :
|
||||
<https://www.kernel.org/doc/Documentation/admin-guide/namespaces/>
|
||||
|
||||
|
||||
### Articles de référence
|
||||
|
||||
- [Namespaces in operation (série LWN)](https://lwn.net/Articles/531114/) :
|
||||
série d'articles exhaustive par Michael Kerrisk
|
||||
<https://lwn.net/Articles/531114/>
|
||||
|
||||
- [Anatomy of a user namespaces vulnerability](https://lwn.net/Articles/543273/) :
|
||||
pour comprendre les enjeux de sécurité
|
||||
<https://lwn.net/Articles/543273/>
|
||||
|
||||
|
||||
### 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue