% Virtualisation légère % Pierre-Olivier Mercier % Samedi 29 novembre 2014 # Rappels & historique ## Rappels sur la virtualisation classique ### Prémices #### Au départ Exécuter simultanément plusieurs environnements distinct sur un mainframe IBM. #### IBM System/370 * Virtualisation grâce au système CP/CMS ; * permis par la présence d'une MMU et par l'ajout d'un mode *supervisor* au processeur. ### Vocabulaire * Machine hôte/host machine * Machine invité/guest machine #### Virtualisation vs. émulation * Émulation : simulation logiciel de matériel (potentiellement une architecture différente) : pas d'accès direct au matériel ; * Virtualisation : accès direct, mais restrint au matériel. #### Technologies de virtualisation matérielle * Intel VT-x/AMD-V/ARM Virtualization Extensions * partitionne le processeur pour exécuter plusieurs système d'exploitation via le même processeur. ### Hyperviseurs ![](hyperv.png) ### Hyperviseurs Contrôlent l'utilisation faite des ressources de la machine hôte par les machines virtuelles. #### Type 1 * L'hyperviseur contrôle directement le matériel ; * Tous les systèmes lancés par la suite passent par l'hyperviseur. * Microsoft Hyper-V, XenServer, VMware ESX, ... #### Type 2 * L'hyperviseur s'appuie sur le système d'exploitation déjà lancé pour accéder au matériel ; * Linux KVM, VirtualBox, BHyVe, ... ### Paravirtualisation #### Caractéristiques * Nécessite un noyau patché ; * l'hôte expose une API accessible aux invités ; * les invités accèdent au matériel via l'API de l'hôte. #### Exemple * Xen ## Virtualisation légère ### Conteneur ![](cntnr.png) ### Conteneur #### Caractéristiques * Isolation faite par le noyau du système d'exploitation ; * le noyau est partagé entre tous les invités ; * les périphériques sont déjà en place (pas besoin d'en émuler) ; * l'invité démarre à partir de `/sbin/init`. ### Conteneurs applicatifs ![](cntrapp.png) ### Conteneurs applicatifs #### Caractéristiques * Noyau est partagé avec l'hôte ; * on utilise tout en place : fs, sockets, périphériques ; * lance directement une application, pas `init`. #### Versus chroot * Simple isolation d'une partie du système de fichier ; * pas de limitation sur les ressources utilisés ; * pas d'isolation de l'arbre des processus ; * implémentations douteuses (GrSecurity !). ## Différentes implémentations ### Points communs #### Environnement virtualisé * Arborescence de fichiers séparé ; * arbre de processus isolé ; * comptes utilisateurs distincts ; * pile réseau et nom de machine propre. ### Diversité #### Unix * **FreeBSD :** Jails lancées en 1998 ; * **Solaris :** Zones lancées en 2005 ; #### GNU/Linux * **OpenVZ :** 2005, nécessite de patcher son kernel ; * **Linux Containers (LXC) :** 2008, basé sur les namespaces et les cgroups ; * **Docker :** 2013, en pleine croissance ! ### Et Windows ? #### Isolation * Parallels Virtuozzo Containers ; * Sandboxie. #### Dérivés * **Boot2Docker :** Docker dans une VM. # GNU/Linux ## Namespaces & cgroups ### Isolation du système #### Mount Namespace Isole la vue des partitions montées. #### UTS Namespace Identification du système : nom de machine et de domaine. #### PID Namespace Crée un arbre d'exécution parallèle où le premier process à être exécuté devient le PID 1 de cet arbre. ### Isolation du système #### Network Namespace Isole la pile réseau ; crée un nouveau groupe d'interfaces. #### User Namespace Crée une liste d'utilisateurs et de groupe distincte. #### IPC Namespace Isolation des files de messages de communication interprocessus (IPC). ### Implémentation ```c #include #define STACKSIZE (1024*1024) static char child_stack[STACKSIZE]; int clone_flags = CLONE_NEWNET | SIGCHLD; pid_t pid = clone(do_execvp, child_stack + STACKSIZE, clone_flags, &args); ``` ### cgroups `/sys/fs/cgroup/` #### Block I/O * Limitation de la bande passante lecture/écriture ; * poids d'un groupe ; * métriques: IOPS, latence, file d'attente. #### CPU * Poids d'utilisation du CPU ; * statistiques d'utilisation ### cgroups `/sys/fs/cgroup/` #### Mémoire * Limite de taille ; * métriques : total rss, swap, nb pages in/out #### Autres Réseau, périphériques, gel de processus, ... ## Capabilities ### Résumé #### Historiquement * Processus privilégiés : `UID == 0`. * Processus non-privilégiés : `UID != 0`. #### Depuis Linux 2.2 * Séparation des privilèges de l'UID 0. * Chaque thread peut posséder ses propres capacités. * `prctl(2)`, `execve(2)`, `clone(2)`, ... ### Principales capacités #### Ne pas oublier de désactiver * `CAP_MKNOD` : `mknod` * `CAP_NET_RAW` : permet d'écouter tout le réseau * `CAP_SYS_MODULE` : charge et décharge des modules noyau * `CAP_SYS_RAWIO` : accès brut aux entrées/sorties * `CAP_SYS_RESOURCE` : dépassement des quotas, utilisation de l'espace réservé, ... * `CAP_SYS_TIME` : changer l'heure de la machine * `CAP_SYS_ADMIN` : misc * ... ## Isolateurs ### Systemd * Chaque service est démarré dans un cgroup ; * on peut appliquer des limites au groupe en modifiant le `.service` ; * `systemd-nspawn` pour créer manuellement un nouveau namespace. ```ini [Service] CPUShares=1500 MemoryLimit=1G BlockIOWeight=500 ``` ### LXC * Lance un système complet à partir de `/sbin/init` ; * se configure via un fichier de conf : ```ini lxc.rootfs = /var/lib/lxc/toto/rootfs lxc.utsname = toto lxc.network.type = veth lxc.network.hwaddr = 00:16:3e:c6:0e:04 lxc.network.flags = up lxc.network.link = tap0 lxc.network.name = eth0 lxc.tty = 4 lxc.pts = 1024 lxc.cap.drop = mac_admin mac_override ``` ### Docker * Lance une application, packagé dans un environnement ; * création d'environnement possible à partir de `Dockerfile` : ``` FROM debian:wheezy RUN groupadd -r mysql && useradd -r -g mysql mysql RUN apt-get update && apt-get install -y perl ENV MYSQL_MAJOR 5.7 VOLUME /var/lib/mysql COPY docker-entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] EXPOSE 3306 CMD ["mysqld", "--datadir=/var/lib/mysql"] ``` ## Réseau ### Réseaux physiques #### empty Loopback uniquement, n'ajoute aucune interface. #### phys Utilisation d'une interface physique directement. #### vlan Assignation d'un VLAN à chaque conteneur. ### Réseaux virtuels #### veth On crée une interface virtuelle sur l'hôte que l'on connecte à un bridge. #### MAC VLAN * **VEPA :** tous les paquets sortants sortent, y compris ceux à destination d'une autre machine locale. Le switch derrière doit rerouter les paquets vers la machine. * **Bridge :** le noyau analyse les paquets avant de les transmettre. # En production ### LXC API ```python import lxc import sys # Setup the container object c = lxc.Container("apicontainer") # Create the container rootfs c.create("download", lxc.LXC_CREATE_QUIET, {"dist": "ubuntu", "release": "trusty", "arch": "i386"}) # Start the container if not c.start(): print("Failed to start the container") sys.exit(1) ``` ### Projets naissants #### Core OS * Système d'exploitation minimaliste ; * fleet : systemd administrable à distance ; * lance des conteneur via fichiers de service Systemd. #### Citadel * Interaction avec un cluster Docker ; * schedule l'emplacement d'exécution des conteneurs. #### Shipyard * Interface web pour gérer son cluster Docker.