{"action":"created","comment":{"url":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/comments/81538333","pull_request_review_id":2508922,"id":81538333,"diff_hunk":"@@ -0,0 +1,1130 @@\n+##############\n+LXC démystifié\n+##############\n+\n+:date: 2013-03-04 13:00\n+:tags: linux\n+:category: Linux\n+:author: James Pic\n+:lang: fr\n+:slug: lxc-demystification\n+\n+Cet article décortique l'installation de `LXC\n+<https://linuxcontainers.org/>`_. Le but est de pouvoir créer des conteneurs\n+qui ont accès à internet, et qu'on peut résoudre en ``nom-de-conteneur.lxc``.\n+Je vais faire de mon mieux pour avoir une approche aussi instructive que\n+ludique, un petit peu dans le style du site du zéro pour ceux qui l'ont connu,\n+même si le sujet reste peut-être un chouilla poilu pour ceux qui comme moi\n+apprennent le réseau.\n+\n+Les conteneurs\n+***************\n+\n+Un conteneur est un outil basique qui consiste en un dispositif qui enferme un\n+espace partiellement ou complètement pour être utilisé pour contenir, stocker\n+et transporter des objets ou matériels. Les choses gardées à l'intérieur du\n+conteneur sont protégées en étant à l'intérieur de sa structure.\n+\n+Les Humains utilisent des conteneurs depuis au moins 100 000 ans. Les premiers\n+furent probablement inventés pour stocker de la nourriture, permettant aux\n+premiers humains de garder leur nourriture plus longtemps, la transporter plus\n+facilement, et la protéger des autres animaux.\n+\n+Le développement des conteneurs à nourriture était d'une \"immense importance\n+pour l'évolution des populations\", ainsi qu'une \"attitude complètement\n+innovante\", jamais vu chez aucun autre primate.\n+\n+LXC\n+***\n+\n+LXC est une méthode de conteneurisation de système d'exploitation pour faire\n+tourner plusieurs systèmes Linux isolés (conteneurs) sur un hôte de contrôle en\n+utilisant un seul kernel.\n+\n+La différence avec Docker, c'est que Docker est une méthode de conteneurisation\n+d'application. Le premier processus que Docker exécute dans un conteneur, c'est\n+celui de l'application. Pour LXC, c'est le logiciel d'init du système\n+d'exploitation. Par exemple pour un conteneur Debian Jessie, le PID 1 est\n+systemd.\n+\n+En terme d'utilisation, LXC est plutôt comparable aux méthodes de\n+virtualization. C'est à dire qu'on lance un système d'exploitation complet de\n+manière isolée du système hôte.\n+\n+Installation de LXC\n+*******************\n+\n+Il suffit d'installer le paquetage lxc pour installer les commandes sur son\n+système::\n+\n+    # Alpine Linux\n+    apk add lxc lxc-templates\n+    # Arch Linux\n+    pacman -S lxc\n+    # Fedora\n+    dnf install lxc lxc-templates lxc-extra\n+    # Gentoo\n+    emerge app-emulation/lxc\n+    # Ubuntu linux\n+    apt-get install lxc lxc-net\n+\n+Voila pour le petit tour des gestionnaires de paquetage. En aucun cas ceci ne\n+doit être considéré comme exhaustif et à jour et vous devez donc aussi regarder\n+la `doc de votre distro au sujet de lxc\n+<http://lmgtfy.com/?q=lxc+votre+distro>`_.\n+\n+Si vous n'avez pas encore choisi de distribution Linux, ou pour celles qui ne\n+savent pas pourquoi on m'appelle \"le roi des trolls\" et parce qu'on avait dit\n+que cet article devait avoir un coté ludique, voici un petit guide:\n+\n+- `Gentoo\n+  <https://wiki.gentoo.org/wiki/LXC>`_ pour détruire la couche d'ozone,\n+- `SourceMage\n+  <https://sourcemage.org/>`_ pour faire l'originale,\n+- `Fedora\n+  <https://fedoraproject.org/wiki/LXC>`_ pour le kiffe de Red Hat,\n+- `Debian\n+  <https://wiki.debian.org/LXC>`_ pour apprendre Linux,\n+- `Ubuntu\n+  <https://linuxcontainers.org/lxc/getting-started/>`_ pour s'en servir,\n+- `Arch linux\n+  <https://wiki.archlinux.org/index.php/Linux_Containers>`_ pour roxey du poney,\n+- `Alpine\n+  <https://wiki.alpinelinux.org/wiki/LXC>`_ pour roxey du poney sans tête\n+  (\"headless\" server),\n+\n+Comme je le disais, tout ce que vous avez à faire pour vous service de lxc sur\n+Ubuntu est::\n+\n+    sudo add-apt-repository --yes ppa:ubuntu-lxc/stable\n+    sudo apt-get update\n+    sudo apt-get install lxc dnsmasq lxc-dev\n+\n+    sudo sed -i 's/^#LXC_DOMAIN=\"lxc\"/LXC_DOMAIN=\"lxc\"/' /etc/default/lxc-net\n+    sudo service lxc-net restart\n+\n+    echo server=/lxc/10.0.30.1 | sudo tee -a /etc/NetworkManager/dnsmasq.d/lxc\n+    sudo service NetworkManager restart\n+\n+Création de conteneur\n+**********************\n+\n+La commande ``lxc-create`` permet de créer un conteneur. Cette commande prend\n+en argument, notamment:\n+\n+- le nom du conteneur,\n+- le nom du template (script bash) à utiliser pour le provisionner.\n+- les arguments à passer au template, après un double tiret (``--``).\n+\n+Par exemple, pour créer un conteneur Debian jessie, on peut utiliser une\n+commande telle que::\n+\n+    lxc-create --name test --template debian -- --release jessie\n+\n+.. danger:: Attention tout de même au nom du conteneur. La commande ``lxc-create`` ne\n+            valide pas le nom qui doit pourtant respecter la `RFC 952\n+            <https://tools.ietf.org/html/rfc952>`_ pour que tout roule niveau\n+            réseau ``[a-z0-9.-]{1,24}``. Exit donc les underscores et les noms\n+            trop longs.\n+\n+Rootfs\n+======\n+\n+C'est le script de template qui provisionne le rootfs, par défaut avec le\n+backend ``dir`` dans ``/var/lib/lxc/nom-du-conteneur/rootfs/``.\n+\n+A noter que l'une des techniques que nous avions utilisé pour accélérer\n+l'exécution des tests automatiques est de créer le conteneur dans un\n+``tmpfs``, qui est un système de fichier temporaire stocké en RAM.\n+\n+D'autres backends de stockages sont disponibles, notamment LVM, Ceph RBD et\n+ZFS. Ceux-ci ne seront pas couverts par cet article.\n+\n+Templates\n+=========\n+\n+Dans l'exemple ci-dessus, c'est le template\n+``/usr/share/lxc/templates/lxc-debian`` qui sera utilisé avec l'option\n+``--release jessie`` pour créer le conteneur ``test``.\n+\n+Pour consulter la liste des options disponibles pour un template on peut\n+utiliser ``-- --help``::\n+\n+    lxc-create -n test -t debian --help\n+\n+On obtient donc en sortie l'aide pour ``lxc-create`` et pour le template debian\n+à la suite::\n+\n+    Usage: lxc-create --name=NAME --template=TEMPLATE [OPTION...]\n+\n+    lxc-create creates a container\n+\n+    Options :\n+      -n, --name=NAME               NAME of the container\n+      -f, --config=CONFIG           Initial configuration file\n+      -t, --template=TEMPLATE       Template to use to setup container\n+      -B, --bdev=BDEV               Backing store type to use\n+          --dir=DIR                 Place rootfs directory under DIR\n+\n+      BDEV options for LVM (with -B/--bdev lvm):\n+          --lvname=LVNAME           Use LVM lv name LVNAME\n+                                    (Default: container name)\n+          --vgname=VG               Use LVM vg called VG\n+                                    (Default: lxc)\n+          --thinpool=TP             Use LVM thin pool called TP\n+                                    (Default: lxc)\n+\n+      BDEV options for Ceph RBD (with -B/--bdev rbd) :\n+          --rbdname=RBDNAME         Use Ceph RBD name RBDNAME\n+                                    (Default: container name)\n+          --rbdpool=POOL            Use Ceph RBD pool name POOL\n+                                    (Default: lxc)\n+\n+      BDEV option for ZFS (with -B/--bdev zfs) :\n+          --zfsroot=PATH            Create zfs under given zfsroot\n+                                    (Default: tank/lxc)\n+\n+      BDEV options for LVM or Loop (with -B/--bdev lvm/loop) :\n+          --fstype=TYPE             Create fstype TYPE\n+                                    (Default: ext3)\n+          --fssize=SIZE[U]          Create filesystem of\n+                                    size SIZE * unit U (bBkKmMgGtT)\n+                                    (Default: 1G, default unit: M)\n+\n+    Common options :\n+      -o, --logfile=FILE               Output log to FILE instead of stderr\n+      -l, --logpriority=LEVEL          Set log priority to LEVEL\n+      -q, --quiet                      Don't produce any output\n+      -P, --lxcpath=PATH               Use specified container path\n+      -?, --help                       Give this help list\n+          --usage                      Give a short usage message\n+          --version                    Print the version number\n+\n+    Mandatory or optional arguments to long options are also mandatory or optional\n+    for any corresponding short options.\n+\n+    See the lxc-create man page for further information.\n+\n+    Template specific options can be passed to lxc-create after a '--' like this:\n+\n+      lxc-create --name=NAME [-lxc-create-options] -- [-template-options]\n+\n+    Usage: /usr/share/lxc/templates/lxc-debian -h|--help -p|--path=<path> [-c|--clean] [-a|--arch=<arch>] [-r|--release=<release>]\n+                                         [--mirror=<mirror>] [--security-mirror=<security mirror>]\n+                                         [--packages=<package_name1,package_name2,...>]\n+\n+    Options :\n+\n+      -h, --help             print this help text\n+      -p, --path=PATH        directory where config and rootfs of this VM will be kept\n+      -a, --arch=ARCH        The container architecture. Can be one of: i686, x86_64,\n+                             amd64, armhf, armel, powerpc. Defaults to host arch.\n+      -r, --release=RELEASE  Debian release. Can be one of: wheezy, jessie, stretch, sid.\n+                             Defaults to current stable.\n+      --mirror=MIRROR        Debian mirror to use during installation. Overrides the MIRROR\n+                             environment variable (see below).\n+      --security-mirror=SECURITY_MIRROR\n+                             Debian mirror to use for security updates. Overrides the\n+                             SECURITY_MIRROR environment variable (see below).\n+      --package=PACKAGE_NAME1,PACKAGE_NAME2,...\n+                             List of additional packages to install. Comma separated, without space.\n+      -c, --clean            only clean up the cache and terminate\n+      --enable-non-free      include also Debian's contrib and non-free repositories.\n+\n+    Environment variables:\n+\n+      MIRROR                 The Debian package mirror to use. See also the --mirror switch above.\n+                             Defaults to 'http://httpredir.debian.org/debian'\n+      SECURITY_MIRROR        The Debian package security mirror to use. See also the --security-mirror switch above.\n+                             Defaults to 'http://security.debian.org/'\n+\n+On regarde bien, et on voie donc les deux aides, celle de ``lxc-create`` et\n+celle du template debian l'une à la suite de l'autre.\n+\n+Aperçu du template debian\n+-------------------------\n+\n+On voie à la fin du script de template ``/usr/share/lxc/templates/lxc-debian``\n+que ces fonctions sont appelées dans l'ordre::\n+\n+    install_debian \"$rootfs\" \"$release\" \"$arch\" \"$LXC_CACHE_PATH\"\n+    configure_debian \"$rootfs\" \"$name\" $num_tty\n+    copy_configuration \"$path\" \"$rootfs\" \"$name\" $arch $num_tty\n+    configure_debian_systemd \"$path\" \"$rootfs\" \"$config\" $num_tty\n+    post_process \"${rootfs}\" \"${release}\" \"${arch}\" \"${hostarch}\" \"${packages}\"\n+\n+On va regarder un peu tout ça histoire de se rendre compte de tout le boulot\n+qu'il y derrière et désillusionner celles qui croient que tout ça c'est\n+magique.\n+\n+install_debian\n+--------------\n+\n+Cette première étape met en cache le rootfs de base pour ce template et ces\n+options si il n'existe pas. Dans notre exemple, il s'agit de\n+``/var/cache/lxc/debian/rootfs-jessie-amd64/``.\n+\n+D'abord il importe la clefs GPG de la release si ``debian-archive-keyring``\n+n'est pas installé, dans notre exemple il utiliserait\n+``https://ftp-master.debian.org/keys/archive-key-8.asc`` pour provisionner\n+``/usr/share/keyrings/debian-archive-keyring.gpg`` manuellement si\n+``debian-archive-keyring`` n'est pas installé.\n+\n+Ensuite, ``debootstrap`` télécharge les paquetages minimaux pour debian\n+(``--variant=minbase``) dans le dossier de cache\n+``/var/cache/lxc/debian/rootfs-jessie-amd64/``. Cette étape de téléchargement,\n+de validation et d'extraction de binaires prend un petit peu de temps, mais\n+n'est exécutée qu'une fois.\n+\n+Enfin, ``/var/cache/lxc/debian/rootfs-jessie-amd64/`` est copié pour devenir le\n+rootfs du conteneur, par exemple dans ``/var/lib/lxc/test/rootfs/``.\n+\n+configure_debian\n+----------------\n+\n+Cette fonction provisionne le rootfs ainsi:\n+\n+- ``mknod $rootfs/dev/tty{0,4}``,\n+- écriture de ``$rootfs/etc/inittab``,\n+- lien de ``/proc/self/mounts`` de l'hôte vers ``$rootfs/etc/mtab``.\n+- désactivation de selinux avec ``echo 0 > \"$rootfs/selinux/enforce\"``,\n+- configuration de eth0 en dhcp dans ``$rootfs/etc/network/interfaces``,\n+- régénération des locales avec ``chroot \"$rootfs\" locale-gen`` et ``chroot\n+  \"$rootfs\" update-locale`` après avoir écrit ``\"$rootfs/etc/locale.gen\"`` soit\n+  pour n'avoir que ``en_US.UTF-8`` soit pour avoir ``$LANG``,\n+- désactivation des services inutiles dans le conteneur: checkroot.sh,\n+  umountfs, hwclock.sh, hwclockfirst.sh.\n+- régénération des clefs d'hôte ssh,\n+- copie de la timezone de l'hôte dans ``$rootfs/etc/timezone``,\n+- génération et output d'un mot de passe root.\n+\n+Celles qui ont l'habitude installer des OS assez manuellement de type `Gentoo\n+Linux <https://wiki.gentoo.org/wiki/Handbook:AMD64/Full/Installation>`_ ou\n+`Arch <https://wiki.archlinux.org/index.php/installation_guide>`_ reconnaitront\n+globalement les étapes.\n+\n+copy_configuration\n+------------------\n+\n+Cette fonction génère la configuration du conteneur, soit\n+``/var/lib/lxc/test/config`` dans notre exemple, en plusieurs étapes:\n+\n+- si il n'y a qu'une seule interface réseau en veth dans la configuration, il\n+  s'assure qu'elle a une adresse MAC générée aléatoirement,\n+- inclusion des fichiers ``/usr/share/lxc/config/debian.common.conf`` et\n+  ``/usr/share/lxc/config/debian.jessie.conf`` si ils existent en ajoutant\n+  ``lxc.include``,\n+- utilisation de ``/etc/lxc/default.conf``, je n'ai pas trouvé le code source\n+  qui l'utilise (w00t ?) mais une chose est certaine c'est que les\n+  configurations de conteneurs incluent le contenu de ce fichier.\n+- définition du nombre de ttys, du hostname et de l'arch dans la config.\n+\n+configure_debian_systemd\n+------------------------\n+\n+Cette étape cuisine systemd dans le rootfs avec chroot, notamment en\n+désactivant un certain nombre de services tels que udev et en fixant la\n+configuration de ttys.\n+\n+post_process\n+------------\n+\n+Installe l'architecture nécessaire si différente de l'hôte, écrit\n+``$rootfs/etc/apt/sources.list`` et installe les paquetages spécifiés en argument\n+du template.\n+\n+Conclusion\n+----------\n+\n+Ce n'est pas de tout repos que de créer un rootfs, on est bien content que LXC\n+mette à disposition une variété de templates, notamment pour la\n+distribution de serveur la plus light et sécurisée, qui est, comme chacune\n+d'entre nous le sait, indéniablement: Alpine Linux.\n+\n+Pour plus d'information, on peut consulter la `liste des templates\n+<https://github.com/lxc/lxc/tree/master/templates>`_.\n+\n+Configuration du conteneur\n+***************************\n+\n+La config va par défaut à coté du rootfs, c'est à dire\n+``/var/lib/lxc/nom-du-conteneur/config``. Il suffit de redémarrer le\n+conteneur après l'avoir modifiée. Aussi, on peut changer les valeurs par\n+défaut dans ``/etc/lxc/default.conf``.\n+\n+lxc.network\n+===========\n+\n+C'est la configuration de l'interface réseau du conteneur. Pour avoir accès à\n+internet, les conteneurs doivent se connecter à une interface bridge sur\n+l'hôte.  Celle-ci peut avoir été créée par le paquetage (Ubuntu, paquetage\n+lxc-net), alors on peu la créer manuellement, ce qu'on verra en détail dans la\n+section \"Configuration du réseau\". Ici, nous nous contenterons d'examiner vite\n+fait une configuration qui marche.\n+\n+La commande ``brctl show`` permet d'obtenir la liste des interfaces bridges\n+sur l'hôte::\n+\n+    $ brctl show\n+    bridge name\tbridge id\t\tSTP enabled\tinterfaces\n+    docker0\t\t8000.02428c645c54\tno\n+    lxc\t\t    8000.fe29ecbfa16e\tno\t\tvethVH4RGS\n+    lxd\t\t    8000.fe0df36fbbe4\tno\t\tveth56DNQM\n+                                            veth5KN2AM\n+                                            vethB5A3P7\n+                                            vethIDUBK3\n+\n+Ici, on voie que j'ai trois interfaces bridges, une qui s'appelle ``lxc`` et\n+une autre qui s'appelle ``lxd``, et une pour docker. L'important, c'est d'avoir\n+la bonne configuration réseau ``lxc.network`` par défaut::\n+\n+    lxc.network.type = veth\n+    lxc.network.ipv4 = 0.0.0.0\n+    # L'interface bridge est le link\n+    lxc.network.link = lxc\n+\n+Bien souvent, on verra ``lxcbr0`` ou ``lxdbr0`` dans les documentations,\n+articles ou configurations par défaut. Personnellement, j'utilise Arch Linux et\n+je fais ma config moi-même, avec plein d'amour dedans, et je préfère nommer\n+mes interfaces ``lxc`` et ``lxd``, parce que ce sont les mots que j'utilise\n+partout dans mes configurations. Mais vous ferez bien comme vous voulez, car le\n+but ici n'est pas de vous donner des trucs à copier-coller en mode tuto mais\n+bel et bien s'instruire. On verra ça en détail dans le section de configuration\n+réseau.\n+\n+Ne vous inquiétez pas si vous n'avez pas d'interface bridge pour lxc, nous\n+étudierons cela dans la section de configuration de l'hôte.\n+\n+Démarrage du conteneur\n+***********************\n+\n+La commande ``lxc-start`` permet de démarrer un conteneur LXC. L'important\n+c'est de retenir que démarrer un conteneur LXC, c'est démarrer le programme\n+d'init de sa distribution (en l'occurrence systemd) en PID1 dans ses\n+namespaces:\n+\n+- mnt: mount point, systèmes de fichiers\n+- pid: processus,\n+- net: stack réseau,\n+- ipc: System V IPC,\n+- uts: nom d'hôte,\n+- user: uids.\n+\n+Concrètement, le PID1 du conteneur ne voie pas les mêmes mount points,\n+processus, stack réseau, utilisateurs et nom d'hôte que l'hôte.\n+\n+Pour plus de détails, je vous conseille la `présentation de Rami Rosen,\n+Resource Management: Linux kernel Namespaces and cgroups\n+<http://www.haifux.org/lectures/299/netLec7.pdf>`_.\n+\n+Executer dans le conteneur\n+***************************\n+\n+Le concept de conteneur est très abstrait ici, puisque finalement, on a ici\n+que des processus qui tournent dans des configurations différentes: root dir,\n+namespaces, cgroups ...\n+\n+On exécute pas vraiment une commande dans un conteneur, puisque c'est le\n+kernel qui démarre les processus. On démarre donc un processus sur l'hôte avec\n+le root fs du conteneur pour ensuite l'attacher aux bons namespaces et cgroups.\n+\n+La commande qui abstrait tout ça pour l'utilisateur est ``lxc-attach``::\n+\n+    lxc-attach -n nom-du-conteneur -- commande\n+\n+Depuis la version 0.9, l'option ``--keep-env`` est activée par défaut. Cette\n+option garde les variables d'environnement pour les processus attachés.\n+Attention à cela car cela peut causer une fuite d'information indésirables dans\n+le conteneur.\n+\n+Par exemple, les utilisateurs d'Arch Linux n'ont plus besoin d'avoir ``/bin``\n+dans le ``$PATH`` depuis bien longtemps. Résultat, il manque pas mal de\n+commandes quand on passe sur un conteneur d'une autre distro qui repose encore\n+beaucoup sur ``/bin`` !\n+\n+Cela dit, même si on en a pas *besoin*, je recommande tout de même de passer\n+systématiquement ``--clear-env``. Une autre raison de pratiquer cette option\n+est qu'elle est vouée à être activée par défaut dans le futur.\n+\n+Configuration du réseau\n+***********************\n+\n+Introduction\n+============\n+\n+Je serais franc avec vous: je ne suis pas expert réseau. Cela dit j'adore\n+apprendre et voyons la réalité en face: si on veut participer à la construction\n+d'internet, on sera plus crédible avec un minimum de compétences en réseau !\n+\n+Pour une développeuse ou un développeur, cela peut sembler plus difficile voire\n+être perçu comme un métier complètement différent qu'on ne peut pas faire parce\n+qu'on a pas reçu la formation. En fait, j'aimerais vous convaincre que c'est\n+presque plus facile que le développement, bien que l'approche soit\n+fondamentalement différente et beaucoup plus concrète qu'abstraite, car bien\n+entendu beaucoup plus bas niveau. On se retrouve plus à brancher des câbles\n+réseau, définir des subnets et des routes, à partager son pool d'adresse ip\n+qu'à instancier un objet de client http pour effectuer une requête et qui va\n+complètement abstraire toutes ces histoires de câbles et d'adresses ips. On a\n+pas le choix, on veut que les paquets réseaux aillent et viennent sur le\n+réseau, en clair (ou pas) le procédé mental est plutôt `zugzwang\n+<https://en.wikipedia.org/wiki/Zugzwang>`_ que\n+`zwischenzug\n+<https://en.wikipedia.org/wiki/Zwischenzug>`_.\n+\n+On veut donc avoir des conteneurs qui ont une adresse IP et donc qui soient\n+connectés sur un réseau. On a pas mal d'options ici, ``man 5\n+lxc.container.conf`` contient la liste exhaustive des options. On peut par\n+exemple donner une interface physique au conteneur::\n+\n+    lxc.network.type = phys\n+    lxc.network.link = eth2\n+\n+C'est simple: on démarre le conteneur et il a une interface réseau physique,\n+avec un vrai câble dedans, comme on a l'habitude. C'est sans doutes très bien\n+quand on a autant d'interface réseau et de câbles qu'on veut avoir de\n+conteneur. Dans ce cas, c'est terminé pour vous, vous pouvez arrêter de lire\n+et reprendre une activité normale. Pour celles qui veulent pouvoir créer et\n+détruire des conteneurs à tire larigot sans avoir à s'occuper de câblage\n+physique par exemple sur un ordinateur portable l'aventure ne fait que\n+commencer !\n+\n+Aperçu\n+======\n+\n+Pour que les conteneurs soient démarrés avec une interface ethernet virtuelle\n+avec le module veth, on utilise ``lxc.network.type=veth``. Comme ça lxc créée\n+une interface réseau de type veth par conteneur.  Comme il faut bien les\n+connecter quelque part, on va se créer une interface de type bridge sur l'hôte,\n+c'est à dire sur votre machine physique. Comme le dit ``man 8 brctl``:\n+\n+    An ethernet bridge is a device commonly used to connect different networks\n+    of ethernets together, so that these ethernets will appear as one ethernet\n+    to the participants.\n+\n+Une fois le bridge créé sur l'hôte, on peut demander à lxc de créer une\n+interface veth dans le namespace du conteneur, connectée à l'interface bridge\n+sur l'hôte par exemple ``lxcbr0``, avec une configuration telle que celle que\n+nous avons vu ci-dessus::\n+\n+    lxc.network.type = veth\n+    lxc.network.link = lxcbr0\n+\n+En faisant cela, c'est un peu comme si on branchait un câble entre l'interface\n+réseau du conteneur et l'interface bridge de l'hôte. On a un lien de données\n+ethernet niveau 2, mais toujours pas d'IP. C'est justement là qu'on a un choix\n+à faire et donc que ça devient intéressant:\n+\n+- soit on connecte l'interface bridge à une interface physique, dans ce cas les\n+  veths qui passent par l'interface bridge se connecteront sur le réseau de\n+  l'interface physique, comme si c'était de vrais interfaces connectées\n+  directement sur le réseau,\n+- soit, par soucis d'économie d'adresse ip, ou pour ne pas exposer les\n+  conteneurs sur le réseau physique, on peut choisir de ne connecter le bridge\n+  à aucune interface physique, et de faire router les paquets pas le kernel\n+  avec une configuration simple sur l'hôte: c'est comme si votre machine était\n+  une box / un router connecté sur internet et sur lequel se connectent\n+  différentes machines.\n+\n+C'est à dire, dans le premier cas on a cette topologie réseau, où lxcbr0 fait\n+le pont avec eth0, et donc toutes les interfaces veth connectées à l'interface\n+de bridge se connectent directement sur le réseau physique, elles se \"croient\"\n+câblées, on peut le représenter ainsi::\n+\n+                    [routeur physique]\n+                    [   192.168.0.1  ]\n+                    /        |        \\\n+               physique   virtuel   virtuel\n+                  /          |          \\\n+               eth0-bridge-[veth123-----veth124]\n+             laptop        containr0    containr1\n+        192.168.0.2        192.168.0.3  192.168.0.4\n+\n+Pour imager, on peut dire que les interfaces veth \"se croient\" branchées par\n+câble directement au routeur.\n+\n+Dans la deuxième configuration proposée, on utilise l'hôte comme routeur avec\n+un LAN virtuel de conteneurs::\n+\n+                   [routeur physique]\n+                   [   192.168.0.1  ]\n+                            |\n+                          eth0\n+                       192.168.0.2\n+                            |\n+                         laptop\n+                            |\n+                         lxcbr0\n+                        10.0.30.1\n+                        /      \\\n+                 containr0    containr1\n+                 10.0.30.2    10.0.30.3\n+\n+La première configuration n'étant pas très difficile, on va s'attaquer à la\n+deuxième qui est beaucoup plus fun, puisqu'on doit configurer son laptop en\n+router !\n+\n+Pratique\n+========\n+\n+Autoriser le kernel à router\n+----------------------------\n+\n+On arrivera à router aucun paquet si la sysconfig ``net.ipv4.ip_forward`` est\n+désactivée. Alors vérifions sa valeur::\n+\n+    $ sysctl net.ipv4.ip_forward\n+    net.ipv4.ip_forward = 0\n+\n+Donc on commence par activer cette conf, sur Arch Linux j'ai un petit fichier\n+tout mignon dans ``/etc/sysctl.d/40-ip-forward.conf``::\n+\n+    net.ipv4.ip_forward=1\n+\n+Après je redémarre le service qui gère ça pour moi::\n+\n+    $ sudo systemctl restart systemd-sysctl.service\n+\n+Et maintenant, je vérifie que ça marche::\n+\n+    $ sudo sysctl net.ipv4.ip_forward=1\n+    net.ipv4.ip_forward = 1\n+\n+Super, ça devrait même persister au reboot, contrairement à si on avait juste\n+activé cette conf en live avec une commande telle que::\n+\n+    $ sudo sysctl net.ipv4.ip_forward=1\n+\n+Création de l'interface bridge\n+------------------------------\n+\n+Certaines distributions telles que Ubuntu fournissent un service qui gère la\n+création et la destruction de l'interface bridge, il s'agit du service\n+``lxc-net`` qui gère également les règles de routage avec iptables.\n+\n+Sinon, on peut créer une interface bridge manuellement également::\n+\n+    sudo brctl addbr lxcbr0\n+    # On assigne une ip a l'interface\n+    sudo ip addr add 10.0.30.1 brd + dev lxcbr0\n+\n+Persister l'interface bridge\n+----------------------------\n+\n+Systemd+netctl (Arch Linux)\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Pour netctl, on crée un fichier de configuration pour l'interface dans ``/etc/netctl/lxcbr0``::\n+\n+    Description=\"LXD Bridge\"\n+    Interface=lxc\n+    Connection=bridge\n+    BindsToInterfaces=()\n+    IP=static\n+    Address=10.0.30.1/24\n+    SkipForwardingDelay=yes\n+\n+On peut ensuite la contrôler avec systemd::\n+\n+    sudo systemctl enable netctl@lxcbr0\n+    sudo systemctl start netctl@lxcbr0\n+\n+Debian\n+~~~~~~\n+\n+Sur debian, c'est le script de networking qui gère les interfaces. Soit on\n+ajoute la partie suivante dans ``/etc/network/interfaces``, soit on s'assure\n+que ``source-directory interfaces.d`` est présent dans ce fichier et on peut\n+utiliser un autre fichier pour l'interface tel que\n+``/etc/network/interfaces.d/lxcbr0``::\n+\n+    auto lxcbr0\n+    iface lxcbr0 inet static\n+        bridge_ports none\n+        address 10.0.30.1\n+        netmask 255.255.255.0\n+\n+On peut ensuite contrôler l'interface avec les scripts ``ifup`` et\n+``ifdown``::\n+\n+    sudo ifup lxcbr0\n+    sudo ifdown lxcbr0\n+\n+Mon petit serveur dhcp et dns: dnsmasq\n+--------------------------------------\n+\n+Comme on l'a vu, les conteneurs se connectent sur l'interface bridge, et le\n+service réseau des conteneurs est configuré pour exécuter un client DHCP par\n+défaut. Donc, il faut un serveur DHCP qui écoute sur cette interface et qui\n+puisse attribuer des IPs aux conteneurs qui démarrent. La chronologie\n+ressemblera à:\n+\n+- le PID1 du conteneur démarre dans le contexte du conteneur,\n+- il démarre le service réseau,\n+- le service réseau active l'interface virtuelle du bridge et lance un client\n+  dhcp dessus,\n+- le serveur dnsmasq qui tourne sur l'hôte et écoute sur le bridge fournit une\n+  l'adresse IP, un serveur DNS (lui-même) et une route par défaut.\n+\n+Puisque les conteneurs seront branchés sur l'interface bridge, ``lxcbr0``,\n+c'est également sur cette interface qu'il faut que le serveur dnsmasq qui\n+servira aux conteneurs lxc écoute.\n+\n+Donc la première étape est de s'assurer qu'on a bien un serveur dnsmasq qui\n+tourne sur l'hôte. J'aime bien faire un coup de ``ps aux | grep dnsmasq`` pour\n+cela, car c'est la pure vérité qui en sort, et là on voit tout de suite la\n+config de beaugosse des alpages::\n+\n+    dnsmasq   1881  0.0  0.0  48060  4092 ?        Ss   Sep27   0:04 /usr/bin/dnsmasq -k -C /etc/dnsmasq-lxc.conf --enable-dbus=uk.org.thekelleys.dnsmasq.lxc --user=dnsmasq --pid-file\n+    dnsmasq   1900  0.0  0.0  48060  4048 ?        Ss   Sep27   0:00 /usr/bin/dnsmasq -k -C /etc/dnsmasq-lxd.conf --user=dnsmasq --pid-file --enable-dbus=uk.org.thekelleys.dnsmasq.lxd\n+    nobody    2515  0.0  0.0  48060  4004 ?        S    Sep27   0:01 /usr/bin/dnsmasq --no-resolv --keep-in-foreground --no-hosts --bind-interfaces --pid-file=/var/run/NetworkManager/dnsmasq.pid --listen-address=127.0.0.1 --cache-size=400 --conf-file=/dev/null --proxy-dnssec --enable-dbus=org.freedesktop.NetworkManager.dnsmasq --conf-dir=/etc/NetworkManager/dnsmasq.d\n+    jpic     10538  0.0  0.0  10760  2268 pts/13   S+   11:29   0:00 grep --color=auto dnsmasq\n+\n+Retenez bien que la vérité est dans l'output de cette commande. On voie quels\n+dnsmasq tournent avec quelles options et quelles configs. C'est par là qu'on\n+commence à inspecter pour voir si tout correspond bien à ce qu'on veut. Vous\n+pouvez ignorer la config lxd pour l'instant, sachez juste que c'est la même que\n+celle pour lxc sauf qu'on remplace lxc par lxd et qu'on a une plage d'ips\n+différentes.\n+\n+On a donc ici 3 dnsmasq qui tournent:\n+\n+- un pour les conteneurs lxc,\n+- un pour les lxd,\n+- un pour l'hôte.\n+\n+Celui pour lxc permet donc aux conteneurs de se connecter, et d'avoir un nom\n+resolvable en ``.lxc``. Celui sur l'hôte permet d'\"aiguiller\" votre laptop:\n+\n+- transférer les demandes de résolutions de ``.lxc`` vers le dnsmasq de lxc,\n+- transférer les demandes de résolutions de ``.lxd`` vers le dnsmasq de lxc,\n+- transférer les demandes customs vers des serveurs dns custom, parfait si vous\n+  vous connectez parfois sur un vpn,\n+- transférer le reste des demandes vers un serveur dns de votre choix, si vous\n+  n'avez pas peur que google mange vos petits enfants alors peut-être\n+  opterez vous pour ``8.8.8.8``.\n+\n+A notter que dnsmasq n'a pas besoin de fichier de config, on peut setter toutes\n+les options en ligne de commande, c'est ce que le dnsmasq de l'hôte qui peut\n+être géré par la distribution peut faire, dans ce cas on ira toucher un fichier\n+plutôt dans ``/etc/default`` du style de ``/etc/default/dnsmasq`` pour\n+bidouiller, c'est notamment le cas sur Ubuntu.\n+\n+Nous étudierons en détail pourquoi cette config est si belle gosse au fur et à\n+mesure et vous apprendrez vous aussi à être des belles gosses du dnsmasq au\n+terme de ce chapitre. Pour commencer nous nous contenterons de démarrer dnsmasq\n+au premier plan (\"foreground\"). Vérifiez qu'à ce stade vous êtes bien capable\n+de faire des ``lxc-create``, ``lxc-start``, ``lxc-stop`` et que vous avez un\n+conteneur de test.\n+\n+dnsmasq: enable-dbus\n+~~~~~~~~~~~~~~~~~~~~\n+\n+Si vous comptez intégrer vos démons dnsmasq avec systemd, de l'amour et du\n+perfectionnisme, le premier truc à retenir c'est qu'on ne peut pas laisser\n+l'option ``enable-dbus`` par défaut sur les dnsmasq qu'on gère nous même.\n+L'option ``enable-dbus``, comme le dit si bien ``man 8 dnsmasq``::\n+\n+       -1, --enable-dbus[=<service-name>]\n+              Allow dnsmasq configuration to be updated via DBus method calls.\n+              The  configu‐ ration  which  can  be  changed  is  upstream  DNS\n+              servers (and corresponding domains) and cache clear. Requires\n+              that dnsmasq has been built with DBus  sup‐ port.  If  the\n+              service  name is given, dnsmasq provides service at that name,\n+              rather than the default which is uk.org.thekelleys.dnsmasq\n+\n+D'ailleurs, vous ne devrez **jamais** avoir plusieurs dnsmasq qui tournent sur\n+le même service-name dbus. Du coup, si vous avez un dnsmasq sur l'hôte pour\n+votre interface physique, et cela sera le cas comme nous le verrons plus loin,\n+vous devez soit:\n+\n+- désactiver l'option dbus sur les dnsmasq que vous gérer,\n+- l'activer avec un ``service-name`` bien unique pour qu'il n'y ait pas de\n+  conflit\n+\n+Pour l'instant on va pas s'en occuper, mais j'ai choisi de mettre ceci en\n+avant au début car c'est source d'un bon nombre de WTF quand on a pas fait ça\n+correctement.\n+\n+démarrer dsnmasq\n+~~~~~~~~~~~~~~~~\n+\n+On crée un conteneur de test::\n+\n+    $ sudo lxc-create -t debian -n foobar -- -r jessie\n+    debootstrap is /usr/bin/debootstrap\n+    Checking cache download in /var/cache/lxc/debian/rootfs-jessie-amd64 ...\n+    Copying rootfs to /var/lib/lxc/foobar/rootfs...Generating locales (this might take a while)...\n+      en_US.UTF-8... done\n+      en_US.UTF-8... done\n+    Generation complete.\n+    insserv: warning: current start runlevel(s) (empty) of script `checkroot.sh' overrides LSB defaults (S).\n+    insserv: warning: current stop runlevel(s) (S) of script `checkroot.sh' overrides LSB defaults (empty).\n+    insserv: warning: current start runlevel(s) (empty) of script `checkroot.sh' overrides LSB defaults (S).\n+    update-rc.d: error: umountfs Default-Start contains no runlevels, aborting.\n+    insserv: warning: current start runlevel(s) (empty) of script `hwclock.sh' overrides LSB defaults (S).\n+    insserv: warning: current stop runlevel(s) (0 6 S) of script `hwclock.sh' overrides LSB defaults (0 6).\n+    update-rc.d: error: cannot find a LSB script for hwclockfirst.sh\n+    Creating SSH2 RSA key; this may take some time ...\n+    2048 27:86:ec:14:5d:06:3d:85:3a:46:86:b8:2f:fa:e1:08 /etc/ssh/ssh_host_rsa_key.pub (RSA)\n+    Creating SSH2 DSA key; this may take some time ...\n+    1024 e4:17:74:ca:fc:e8:72:c1:13:1d:08:76:6c:61:23:3e /etc/ssh/ssh_host_dsa_key.pub (DSA)\n+    Creating SSH2 ECDSA key; this may take some time ...\n+    256 dd:c6:96:de:48:9a:de:4a:f0:f2:6e:ef:4e:5b:60:ff /etc/ssh/ssh_host_ecdsa_key.pub (ECDSA)\n+    Creating SSH2 ED25519 key; this may take some time ...\n+    256 24:0b:9d:0a:7b:00:db:f9:55:24:7e:74:32:8b:dc:c7 /etc/ssh/ssh_host_ed25519_key.pub (ED25519)\n+    Failed to read /proc/cmdline. Ignoring: No such file or directory\n+    invoke-rc.d: policy-rc.d denied exécution of start.\n+    Timezone in container is not configured. Adjust it manually.\n+    Root password is 'root', please change !\n+\n+On démarre le conteneur et on attache un shell dessus pour l'inspecter::\n+\n+    $ sudo lxc-start -n foobar\n+    $ sudo lxc-attach -n foobar --clear-env\n+\n+On voie que l'interface veth n'a pas d'ipv4::\n+\n+    root@foobar:/# ip a\n+    39: eth0@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000\n+    link/ether 00:16:3e:74:0f:e3 brd ff:ff:ff:ff:ff:ff\n+    inet6 fe80::216:3eff:fe74:fe3/64 scope link\n+       valid_lft forever preferred_lft forever\n+\n+    root@foobar:/# ifconfig\n+    eth0      Link encap:Ethernet  HWaddr 00:16:3e:74:0f:e3\n+              inet6 addr: fe80::216:3eff:fe74:fe3/64 Scope:Link\n+              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1\n+              RX packets:40 errors:0 dropped:0 overruns:0 frame:0\n+              TX packets:15 errors:0 dropped:0 overruns:0 carrier:0\n+              collisions:0 txqueuelen:1000\n+              RX bytes:4504 (4.3 KiB)  TX bytes:3042 (2.9 KiB)\n+\n+Qu'on a aucune route::\n+\n+    root@foobar:/# ip route\n+\n+Et qu'on arrive pas à résoudre internet::\n+\n+    root@foobar:/# getent hosts google.com\n+\n+Alors démarrons un dnsmasq sur l'hôte::\n+\n+    $ sudo dnsmasq \\\n+        --keep-in-foreground \\\n+        --log-queries \\\n+\t\t--log-dhcp \\\n+\t\t--log-facility=/tmp/dnsmasq-lxc.log \\\n+        --except-interface=lo \\ # toi pas binder 127.0.0.1\n+        --bind-interfaces \\     # toi binder que l'interface\n+        --interface=lxc \\       # l'interface que toi binder port 53 et 68\n+        --dhcp-leasefile=/tmp/dnsmasq-lxc.leases \\ # toi ranger leases\n+        --domain=lxc \\          # toi donner suffixe .lxc aux hostnames\n+        --local=/lxc/ \\         # toi résoudre que les .lxc par toi même\n+        --dhcp-range=10.0.30.2,10.0.30.254,12h # toi assigner ce range\n+\n+On redémarre le réseau dans le conteneur et là, surprise, ça ne marche\n+toujours pas::\n+\n+\troot@foobar:/# systemctl restart networking\n+\n+Pourtant, dans les logs du conteneur on voie bien qu'il essaye::\n+\n+    root@foobar:/# journalctl -f\n+    -- Logs begin at Fri 2016-09-30 10:14:14 UTC. --\n+    Sep 30 10:15:49 foobar dhclient[123]: Sending on   Socket/fallback\n+    Sep 30 10:15:49 foobar dhclient[123]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 4\n+    Sep 30 10:15:49 foobar networking[111]: Listening on LPF/eth0/00:16:3e:74:0f:e3\n+    Sep 30 10:15:49 foobar networking[111]: Sending on   LPF/eth0/00:16:3e:74:0f:e3\n+    Sep 30 10:15:49 foobar networking[111]: Sending on   Socket/fallback\n+    Sep 30 10:15:49 foobar networking[111]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 4\n+    Sep 30 10:15:53 foobar dhclient[123]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 7\n+    Sep 30 10:15:53 foobar networking[111]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 7\n+    Sep 30 10:16:00 foobar dhclient[123]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 9\n+    Sep 30 10:16:00 foobar networking[111]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 9\n+    Sep 30 10:16:09 foobar dhclient[123]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 19\n+    Sep 30 10:16:09 foobar networking[111]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 19\n+    ^C\n+\n+Et dans ceux du dnsmasq de l'hôte qu'il répond::\n+\n+    $ sudo tail -f /tmp/out\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 DHCPOFFER(lxc) 10.0.30.239 00:16:3e:74:0f:e3\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 requested options: 1:netmask, 28:broadcast, 2:time-offset, 3:router,\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 requested options: 15:domain-name, 6:dns-server, 119:domain-search,\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 requested options: 12:hostname, 44:netbios-ns, 47:netbios-scope,\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 requested options: 26:mtu, 121:classless-static-route, 42:ntp-server\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 next server: 10.0.30.1\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  1 option: 53 message-type  2\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  4 option: 54 server-identifier  10.0.30.1\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  4 option: 51 lease-time  12h\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  4 option: 58 T1  6h\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  4 option: 59 T2  10h30m\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  4 option:  1 netmask  255.255.255.0\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  4 option: 28 broadcast  10.0.30.255\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  4 option:  3 router  10.0.30.1\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  4 option:  6 dns-server  10.0.30.1\n+    Sep 30 12:16:41 dnsmasq-dhcp[14412]: 1302916205 sent size:  3 option: 15 domain-name  lxc\n+    ^C\n+\n+Si les paquets partent bien du conteneur vers le dnsmasq de lxc sur l'hôte, et\n+que celui-ci répond correctement, la première hypothèse a considérer est\n+simple: le client dhcp du conteneur ne reçoit pas les réponses.\n+\n+Ok, alors on va écouter ce qui se passe sur l'interface bridge par lequel tout\n+le réseau entre le conteneur et l'hôte se passe::\n+\n+    $ sudo tcpdump -i lxcbr0 -v\n+\n+On voie la requête DHCP qui part du conteneur vers le monde::\n+\n+    IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)\n+    0.0.0.0.bootpc > 255.255.255.255.bootps: [udp sum ok] BOOTP/DHCP, Request from 00:16:3e:74:0f:e3 (oui Unknown), length 300, xid 0x8cbae537, Flags [none] (0x0000)\n+\n+Super, dnsmasq reçoit la requête, et on voie vite sa réponse partir::\n+\n+    12:30:38.628059 IP (tos 0xc0, ttl 64, id 60890, offset 0, flags [none], proto UDP (17), length 328)\n+        lue.bootps > 10.0.30.239.bootpc: [bad udp cksum 0x5235 -> 0x3bc3!] BOOTP/DHCP, Reply, length 300, xid 0x8cbae537, Flags [none] (0x0000)\n+\n+Et là, surprise: ça ne fonctionne pas, le client dhcp tourne en boucle dans le\n+conteneur malgré les réponses répétées par dnsmasq. Nous allons d'abord fixer\n+cela, puis nous reviendrons sur la persistance de la configuration du dnsmasq\n+de lxc.\n+\n+Le drame du DHCP sur bridge\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Avez-vous eu l'oeil ?\n+\n+::\n+\n+    12:30:38.628059 IP (tos 0xc0, ttl 64, id 60890, offset 0, flags [none], proto UDP (17), length 328)\n+        lue.bootps > 10.0.30.239.bootpc: [bad udp cksum 0x5235 -> 0x3bc3!] BOOTP/DHCP, Reply, length 300, xid 0x8cbae537, Flags [none] (0x0000)\n+                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n+                                          et là c'est le drame\n+\n+En fait, dans chaque paquet UDP - ou même TCP si je ne m'abuse - on a un\n+checksum qui permet au receveur de vérifier qu'il a bien reçu le paquet\n+correctement: on ne sait jamais, peut-être qu'une souris grignote le câble\n+réseau et avale des bits sur le chemin. Du coup, le paquet n'est pas prit en\n+compte ou quelque chose comme ça, je ne suis pas sûr. Mais je suis sûr d'un\n+truc: il n'y a pas de petite souris avaleuse de bit dans votre laptop. Bref,\n+résultat des courses le client DHCP ne considère pas sa requête comme\n+satisfaite et réessaye::\n+\n+    12:30:41.091262 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)\n+        0.0.0.0.bootpc > 255.255.255.255.bootps: [udp sum ok] BOOTP/DHCP, Request from 00:16:3e:74:0f:e3 (oui Unknown), length 300, xid 0x8cbae537, secs 3, Flags [none] (0x0000)\n+\n+Le dnsmasq qui écoute sur le bridge, reçoit, répond à nouveau::\n+\n+    12:30:41.091692 IP (tos 0xc0, ttl 64, id 61447, offset 0, flags [none], proto UDP (17), length 328)\n+    lue.bootps > 10.0.30.239.bootpc: [bad udp cksum 0x5235 -> 0x3bc0!] BOOTP/DHCP, Reply, length 300, xid 0x8cbae537, secs 3, Flags [none] (0x0000)\n+\n+Et ainsi de suite, comme on dit \"sa marche pas\".\n+\n+C'est tout simplement parce que les interfaces bridges, aussi cools et fun\n+soient elles, se base sur un bon gros hack sorti de par derrière les fagots par","path":"content/lxc.rst","position":925,"original_position":925,"commit_id":"f190a7d5eeb6cf5fa07db7807039a7b2a11896fa","original_commit_id":"f190a7d5eeb6cf5fa07db7807039a7b2a11896fa","user":{"login":"ewjoachim","id":1457576,"avatar_url":"https://avatars.githubusercontent.com/u/1457576?v=3","gravatar_id":"","url":"https://api.github.com/users/ewjoachim","html_url":"https://github.com/ewjoachim","followers_url":"https://api.github.com/users/ewjoachim/followers","following_url":"https://api.github.com/users/ewjoachim/following{/other_user}","gists_url":"https://api.github.com/users/ewjoachim/gists{/gist_id}","starred_url":"https://api.github.com/users/ewjoachim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ewjoachim/subscriptions","organizations_url":"https://api.github.com/users/ewjoachim/orgs","repos_url":"https://api.github.com/users/ewjoachim/repos","events_url":"https://api.github.com/users/ewjoachim/events{/privacy}","received_events_url":"https://api.github.com/users/ewjoachim/received_events","type":"User","site_admin":false},"body":"basent","created_at":"2016-10-03T12:15:10Z","updated_at":"2016-10-03T12:15:10Z","html_url":"https://github.com/peopledoc/pelican_novapost/pull/42#discussion_r81538333","pull_request_url":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/42","_links":{"self":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/comments/81538333"},"html":{"href":"https://github.com/peopledoc/pelican_novapost/pull/42#discussion_r81538333"},"pull_request":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/42"}}},"pull_request":{"url":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/42","id":86547154,"html_url":"https://github.com/peopledoc/pelican_novapost/pull/42","diff_url":"https://github.com/peopledoc/pelican_novapost/pull/42.diff","patch_url":"https://github.com/peopledoc/pelican_novapost/pull/42.patch","issue_url":"https://api.github.com/repos/peopledoc/pelican_novapost/issues/42","number":42,"state":"open","locked":false,"title":"Lxc article","user":{"login":"jpic","id":94636,"avatar_url":"https://avatars.githubusercontent.com/u/94636?v=3","gravatar_id":"","url":"https://api.github.com/users/jpic","html_url":"https://github.com/jpic","followers_url":"https://api.github.com/users/jpic/followers","following_url":"https://api.github.com/users/jpic/following{/other_user}","gists_url":"https://api.github.com/users/jpic/gists{/gist_id}","starred_url":"https://api.github.com/users/jpic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpic/subscriptions","organizations_url":"https://api.github.com/users/jpic/orgs","repos_url":"https://api.github.com/users/jpic/repos","events_url":"https://api.github.com/users/jpic/events{/privacy}","received_events_url":"https://api.github.com/users/jpic/received_events","type":"User","site_admin":false},"body":null,"created_at":"2016-09-23T17:01:23Z","updated_at":"2016-10-03T12:22:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3dadaf217eb9033650104fa0777d3fa4dcbda737","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/42/commits","review_comments_url":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/42/comments","review_comment_url":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/comments{/number}","comments_url":"https://api.github.com/repos/peopledoc/pelican_novapost/issues/42/comments","statuses_url":"https://api.github.com/repos/peopledoc/pelican_novapost/statuses/f190a7d5eeb6cf5fa07db7807039a7b2a11896fa","head":{"label":"peopledoc:lxc","ref":"lxc","sha":"f190a7d5eeb6cf5fa07db7807039a7b2a11896fa","user":{"login":"peopledoc","id":1080062,"avatar_url":"https://avatars.githubusercontent.com/u/1080062?v=3","gravatar_id":"","url":"https://api.github.com/users/peopledoc","html_url":"https://github.com/peopledoc","followers_url":"https://api.github.com/users/peopledoc/followers","following_url":"https://api.github.com/users/peopledoc/following{/other_user}","gists_url":"https://api.github.com/users/peopledoc/gists{/gist_id}","starred_url":"https://api.github.com/users/peopledoc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peopledoc/subscriptions","organizations_url":"https://api.github.com/users/peopledoc/orgs","repos_url":"https://api.github.com/users/peopledoc/repos","events_url":"https://api.github.com/users/peopledoc/events{/privacy}","received_events_url":"https://api.github.com/users/peopledoc/received_events","type":"Organization","site_admin":false},"repo":{"id":5628024,"name":"pelican_novapost","full_name":"peopledoc/pelican_novapost","owner":{"login":"peopledoc","id":1080062,"avatar_url":"https://avatars.githubusercontent.com/u/1080062?v=3","gravatar_id":"","url":"https://api.github.com/users/peopledoc","html_url":"https://github.com/peopledoc","followers_url":"https://api.github.com/users/peopledoc/followers","following_url":"https://api.github.com/users/peopledoc/following{/other_user}","gists_url":"https://api.github.com/users/peopledoc/gists{/gist_id}","starred_url":"https://api.github.com/users/peopledoc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peopledoc/subscriptions","organizations_url":"https://api.github.com/users/peopledoc/orgs","repos_url":"https://api.github.com/users/peopledoc/repos","events_url":"https://api.github.com/users/peopledoc/events{/privacy}","received_events_url":"https://api.github.com/users/peopledoc/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/peopledoc/pelican_novapost","description":"Blog technique Novapost","fork":false,"url":"https://api.github.com/repos/peopledoc/pelican_novapost","forks_url":"https://api.github.com/repos/peopledoc/pelican_novapost/forks","keys_url":"https://api.github.com/repos/peopledoc/pelican_novapost/keys{/key_id}","collaborators_url":"https://api.github.com/repos/peopledoc/pelican_novapost/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/peopledoc/pelican_novapost/teams","hooks_url":"https://api.github.com/repos/peopledoc/pelican_novapost/hooks","issue_events_url":"https://api.github.com/repos/peopledoc/pelican_novapost/issues/events{/number}","events_url":"https://api.github.com/repos/peopledoc/pelican_novapost/events","assignees_url":"https://api.github.com/repos/peopledoc/pelican_novapost/assignees{/user}","branches_url":"https://api.github.com/repos/peopledoc/pelican_novapost/branches{/branch}","tags_url":"https://api.github.com/repos/peopledoc/pelican_novapost/tags","blobs_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/refs{/sha}","trees_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/trees{/sha}","statuses_url":"https://api.github.com/repos/peopledoc/pelican_novapost/statuses/{sha}","languages_url":"https://api.github.com/repos/peopledoc/pelican_novapost/languages","stargazers_url":"https://api.github.com/repos/peopledoc/pelican_novapost/stargazers","contributors_url":"https://api.github.com/repos/peopledoc/pelican_novapost/contributors","subscribers_url":"https://api.github.com/repos/peopledoc/pelican_novapost/subscribers","subscription_url":"https://api.github.com/repos/peopledoc/pelican_novapost/subscription","commits_url":"https://api.github.com/repos/peopledoc/pelican_novapost/commits{/sha}","git_commits_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/commits{/sha}","comments_url":"https://api.github.com/repos/peopledoc/pelican_novapost/comments{/number}","issue_comment_url":"https://api.github.com/repos/peopledoc/pelican_novapost/issues/comments{/number}","contents_url":"https://api.github.com/repos/peopledoc/pelican_novapost/contents/{+path}","compare_url":"https://api.github.com/repos/peopledoc/pelican_novapost/compare/{base}...{head}","merges_url":"https://api.github.com/repos/peopledoc/pelican_novapost/merges","archive_url":"https://api.github.com/repos/peopledoc/pelican_novapost/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/peopledoc/pelican_novapost/downloads","issues_url":"https://api.github.com/repos/peopledoc/pelican_novapost/issues{/number}","pulls_url":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls{/number}","milestones_url":"https://api.github.com/repos/peopledoc/pelican_novapost/milestones{/number}","notifications_url":"https://api.github.com/repos/peopledoc/pelican_novapost/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/peopledoc/pelican_novapost/labels{/name}","releases_url":"https://api.github.com/repos/peopledoc/pelican_novapost/releases{/id}","deployments_url":"https://api.github.com/repos/peopledoc/pelican_novapost/deployments","created_at":"2012-08-31T11:40:56Z","updated_at":"2016-06-15T13:40:57Z","pushed_at":"2016-10-03T10:38:33Z","git_url":"git://github.com/peopledoc/pelican_novapost.git","ssh_url":"git@github.com:peopledoc/pelican_novapost.git","clone_url":"https://github.com/peopledoc/pelican_novapost.git","svn_url":"https://github.com/peopledoc/pelican_novapost","homepage":"http://tech.novapost.fr","size":2207,"stargazers_count":4,"watchers_count":4,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":11,"forks":2,"open_issues":11,"watchers":4,"default_branch":"master"}},"base":{"label":"peopledoc:master","ref":"master","sha":"52f4dfad8b8ff620aadde129a98a05cd0fe7f20e","user":{"login":"peopledoc","id":1080062,"avatar_url":"https://avatars.githubusercontent.com/u/1080062?v=3","gravatar_id":"","url":"https://api.github.com/users/peopledoc","html_url":"https://github.com/peopledoc","followers_url":"https://api.github.com/users/peopledoc/followers","following_url":"https://api.github.com/users/peopledoc/following{/other_user}","gists_url":"https://api.github.com/users/peopledoc/gists{/gist_id}","starred_url":"https://api.github.com/users/peopledoc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peopledoc/subscriptions","organizations_url":"https://api.github.com/users/peopledoc/orgs","repos_url":"https://api.github.com/users/peopledoc/repos","events_url":"https://api.github.com/users/peopledoc/events{/privacy}","received_events_url":"https://api.github.com/users/peopledoc/received_events","type":"Organization","site_admin":false},"repo":{"id":5628024,"name":"pelican_novapost","full_name":"peopledoc/pelican_novapost","owner":{"login":"peopledoc","id":1080062,"avatar_url":"https://avatars.githubusercontent.com/u/1080062?v=3","gravatar_id":"","url":"https://api.github.com/users/peopledoc","html_url":"https://github.com/peopledoc","followers_url":"https://api.github.com/users/peopledoc/followers","following_url":"https://api.github.com/users/peopledoc/following{/other_user}","gists_url":"https://api.github.com/users/peopledoc/gists{/gist_id}","starred_url":"https://api.github.com/users/peopledoc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peopledoc/subscriptions","organizations_url":"https://api.github.com/users/peopledoc/orgs","repos_url":"https://api.github.com/users/peopledoc/repos","events_url":"https://api.github.com/users/peopledoc/events{/privacy}","received_events_url":"https://api.github.com/users/peopledoc/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/peopledoc/pelican_novapost","description":"Blog technique Novapost","fork":false,"url":"https://api.github.com/repos/peopledoc/pelican_novapost","forks_url":"https://api.github.com/repos/peopledoc/pelican_novapost/forks","keys_url":"https://api.github.com/repos/peopledoc/pelican_novapost/keys{/key_id}","collaborators_url":"https://api.github.com/repos/peopledoc/pelican_novapost/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/peopledoc/pelican_novapost/teams","hooks_url":"https://api.github.com/repos/peopledoc/pelican_novapost/hooks","issue_events_url":"https://api.github.com/repos/peopledoc/pelican_novapost/issues/events{/number}","events_url":"https://api.github.com/repos/peopledoc/pelican_novapost/events","assignees_url":"https://api.github.com/repos/peopledoc/pelican_novapost/assignees{/user}","branches_url":"https://api.github.com/repos/peopledoc/pelican_novapost/branches{/branch}","tags_url":"https://api.github.com/repos/peopledoc/pelican_novapost/tags","blobs_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/refs{/sha}","trees_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/trees{/sha}","statuses_url":"https://api.github.com/repos/peopledoc/pelican_novapost/statuses/{sha}","languages_url":"https://api.github.com/repos/peopledoc/pelican_novapost/languages","stargazers_url":"https://api.github.com/repos/peopledoc/pelican_novapost/stargazers","contributors_url":"https://api.github.com/repos/peopledoc/pelican_novapost/contributors","subscribers_url":"https://api.github.com/repos/peopledoc/pelican_novapost/subscribers","subscription_url":"https://api.github.com/repos/peopledoc/pelican_novapost/subscription","commits_url":"https://api.github.com/repos/peopledoc/pelican_novapost/commits{/sha}","git_commits_url":"https://api.github.com/repos/peopledoc/pelican_novapost/git/commits{/sha}","comments_url":"https://api.github.com/repos/peopledoc/pelican_novapost/comments{/number}","issue_comment_url":"https://api.github.com/repos/peopledoc/pelican_novapost/issues/comments{/number}","contents_url":"https://api.github.com/repos/peopledoc/pelican_novapost/contents/{+path}","compare_url":"https://api.github.com/repos/peopledoc/pelican_novapost/compare/{base}...{head}","merges_url":"https://api.github.com/repos/peopledoc/pelican_novapost/merges","archive_url":"https://api.github.com/repos/peopledoc/pelican_novapost/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/peopledoc/pelican_novapost/downloads","issues_url":"https://api.github.com/repos/peopledoc/pelican_novapost/issues{/number}","pulls_url":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls{/number}","milestones_url":"https://api.github.com/repos/peopledoc/pelican_novapost/milestones{/number}","notifications_url":"https://api.github.com/repos/peopledoc/pelican_novapost/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/peopledoc/pelican_novapost/labels{/name}","releases_url":"https://api.github.com/repos/peopledoc/pelican_novapost/releases{/id}","deployments_url":"https://api.github.com/repos/peopledoc/pelican_novapost/deployments","created_at":"2012-08-31T11:40:56Z","updated_at":"2016-06-15T13:40:57Z","pushed_at":"2016-10-03T10:38:33Z","git_url":"git://github.com/peopledoc/pelican_novapost.git","ssh_url":"git@github.com:peopledoc/pelican_novapost.git","clone_url":"https://github.com/peopledoc/pelican_novapost.git","svn_url":"https://github.com/peopledoc/pelican_novapost","homepage":"http://tech.novapost.fr","size":2207,"stargazers_count":4,"watchers_count":4,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":11,"forks":2,"open_issues":11,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/42"},"html":{"href":"https://github.com/peopledoc/pelican_novapost/pull/42"},"issue":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/issues/42"},"comments":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/issues/42/comments"},"review_comments":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/42/comments"},"review_comment":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/pulls/42/commits"},"statuses":{"href":"https://api.github.com/repos/peopledoc/pelican_novapost/statuses/f190a7d5eeb6cf5fa07db7807039a7b2a11896fa"}}}}
{"actor":{"display_login":"ewjoachim"}}