This feed contains pages in the "kernel" category.

L'année dernière, le noyau Linux a vu un nombre impressionnant de patches avec le mot "namespace" dedans, tout s'est vu "namespacisé" : de l'espace des PID, aux points de montages en passant par les politiques IPSec.

Dans ce post, on va se focaliser sur la partie réseau et son utilisation dans le cadre d'un processus qu'on voudrait restreindre (au sens d'une chroot améliorée). On utilisera indifférement les termes machines virtuelles (VM), container, jail, etc.

Chacun cherche son chat

La partie réseau a été particulièrement polémique chez les développeurs du noyau car il y a de nombreuses façons de réaliser cet espace de nommage : il y a autant de façons que de couches protocolaires comme le détaille l'article de J. Corbet.

Il y a les partisans d'une approche légère où la virtualisation est simplement faite au niveau des sockets et d'autre qui voudraient pouvoir complétement virtualiser la pile TCP/IP afin d'avoir des interfaces, adresses IP, routes et politiques IPSec complétement distinctes entre les machines virtuelles.

La solution qui a été finalement choisie est celle virtualisant la couche 2, cela permet ainsi d'avoir des interfaces complétement indépendantes entre les VM (et donc d'adresses IP, routages, etc.) et l'hôte.

Cette fonctionnalité est disponible dans le noyau Linux depuis le 2.6.27.

La création d'un namespace

Au niveau du noyau, il n'y a qu'un seul moyen de déclarer un nouvel espace de nommage, c'est via l'appel système unshare() (ou via clone() de manière indirecte). Cette fonction a pour effet de désassocier un namespace de son contexte d'exécution.

Son seul argument est le composant que l'on veut désassocier (réseau, système de fichier, descripteurs de fichiers). Cela signifie donc qu'un processus désirant se créér un nouvel espace de nommage est obligé d'être modifié afin d'appeller cet appel système. Un workaround est l'utilisation d'un programme qui va faire cet appel à unshare() puis faire un execve() du programme cible.

Néanmoins, cela implique alors la distribution de deux fichiers (un programme qui exécute l'autre) car il n'existe pas de logiciel standards pour cette tâche, on pourra toujours utiliser netunshare extrait de la suite lxc.

Gestion des interfaces

Lorsqu'on créé un nouvel espace de nommage, le processus se retrouve avec une seule interface, un nouveau loopback uniquement. Pour enrichir sa collection d'interface, il est donc nécessaire de soit créér une nouvelle interface virtuelle, soit transférer une interface déjà existante.

Création d'interface

La création d'une interface virtuelle unique n'a de sens que si elle est connectée à quelque chose (de la même façon qu'un tunnel, il faut qu'il y ait un bout dans la VM, l'autre vers l'extérieur), il faut donc choisir autre chose qu'une interface du style 'dummy' qui peut être considéré comme un puit sans fond.

Une solution de tunnel existe depuis longtemps sous Linux, les tunnels TUN/TAP, or ils ont pour but de fournir un tunnel entre un descripteur de fichier et une interface réseau. Il faudrait donc créér un programme qui ouvrirait deux tunnels et qui passerait son temps à passer les paquets d'un côté à l'autre.

C'est pour cette raison qu'a été implémenté les interfaces de type Virtual Ethernet (veth) qui crééent une paire d'interfaces liées entre elles : ce qui rentre par l'une sort par l'autre et vice versa.

# ip link
4: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# ip link add type veth
# ip link
4: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
9: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether fe:d8:a2:71:23:ae brd ff:ff:ff:ff:ff:ff
10: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 3e:3e:90:3b:3f:c0 brd ff:ff:ff:ff:ff:ff

Si on créé une telle paire d'interface, on reste toujours avec le même problème : on a bien deux interfaces, mais elles restent confinées dans le container, il est donc nécessaire d'avoir un moyen de transférer une interface entre des espaces de nommage, ça tombe bien, c'est supporté :)

Transfert d'interfaces

Lorsqu'on transfère une interface, plutôt que de désigner explicitement un namespace, on précise à la place un PID, l'interface sera alors attachée au namespace de ce PID.

ip link set veth1 netns PID_DESTINATION

Lorsqu'un espace de nommage est détruit, toutes ses interfaces (sauf loopback) sont transférées automatiquement au namespace parent.

Possibilité

À l'intérieur d'un namespace, il est possible de faire tout ce que vous pouvez attendre d'un système normal : changement des routes, des adresses IP, etc.

L'intérêt de ce genre de cloisonnement est qu'une jail n'a qu'un seul point d'entrée et de sortie : l'interface réseau qui a été déportée par l'hôte.

C'est la grande différence avec vserver qui ne permet pas d'identifier clairement les flux entre VM en écrivant vos règles en terme d'interfaces (vous vous retrouvez obligé de jouer sur les adresses sources).

Ce qui n'est pas encore supporté

Pour le moment, Netfilter n'a pas encore le support des namespaces. Cela signifie qu'un container ne peut pas avoir ses propres règles de firewall, mais le problème principal est que Netfilter ne peut voir passer que les paquets sur l'espace de nommage initial. Cela signifie que si vous mettez en place un tunnel entre deux espaces de nommages, Netfilter ne pourra pas pas voir passer les paquets entre eux.

C'est pour cette raison qu'il est préférable de ne pas dédier une VM à la tâche de routeur : tout doit passer à travers l'hôte qui peut alors appliquer une politique de filtrage assurant le cloisonnement. Il faut alors travailler dans la cible FORWARD qui décidera de la politique à adopter.

Posted Tue 28 Apr 2009 05:38:45 PM CEST Tags: kernel

En redémarrant mon laptop, j'ai eu la chance de voir un beau message qui ressemblait à ça :

primary superblock features different from backup, check forced

Suivi d'un fsck qui a eu la bonne idée de faire un segfault lorsqu'il a terminé, rebootant le bousin.

Même s'il était tôt le matin, je me suis tout de suite rappelé que quelques jours avant, j'avais mis à jour les outils e2fs & Co. Le deuxième reboot a été un grand moment de solitude... Mais s'est passé sans problème.

Visiblement, tout ça (sauf le segfault qui ne s'est pas reproduit sur une deuxième machine) est normal, on peut être rassuré par Theodore Tso lui-même dans un rapport de bug.

Toujours est-il que cela signifie que si vous avez des serveurs avec de très gros disques en ext[23]fs, il va falloir prévoir un downtime assez important pour faire le fsck.

Posted Mon 17 Dec 2007 08:52:55 PM CET Tags: kernel

Oh thanks God, c'est jour de fête : le nombre d'arguments dans la ligne de commande est enfin dynamique, il n'y a plus de limitation à 4096 paramètres ! Dites adieu à votre find /foo/bar/ -print0 | xargs -0 que vous utilisiez pour contourner cette limitation stupide ou autres boucle shell.

Posted Thu 23 Aug 2007 08:05:24 PM CEST Tags: kernel