Uubu.org

Systèmes d'information: une approche OpenSource

  

Virtualisation - concepts et optimisation

La virtualisation en entreprise: optimisation des ressources

Le 17 mars 2015 , Aucun commentaire pour cet article


La virtualisation nécessite une optimisation à de nombreux niveaux pour obtenir des hautes performances. Que ce soit les paramètres de l'hôte, de l'invité, l'accélérations hardware, les optimisations de cache, les entrées/sorties, ou la présentation des périphériques, chaque paramètre a son importance. Bien évidemment, l'accélération hardware présents dans les micro-processeurs moderne supporte une grande partie du travail d'optimisation, mais nous allons voir comment optimiser Linux et qemu/kvm. Ce duo est en effet la solution la plus performante du marché, encore faut-il s'avoir exploiter tout son potentiel.

 

Technologie VMX

Le VMM gère les VMCS comme de simples tâches, et lance les vm avec les transitions vm-entries. Nous verrons plus loin comment les cgroups peuvent influencer l'application des VMCS. L'enjeu de la virtualisation est donc de réduire au maximum les vm-exits, et pour cela, nous avons plusieurs fonctionnalités à disposition. HAP et les APIC modernes (x2APIC) qui incluent EOI pour réduire les vm-exists. Ces 2 technologies devraient être systématiquement utilisées, il n'y a pas de raison de s'en priver. On peut vérifier les performances avec une commande du type: perf stat --event "kvm:*" --all-cpus sleep 10.

 

Cache de pages

Les pages de caches sont toutes gérées par le VMM par défaut. Les processeurs moderne incluent HAP qui, d'une part ne vide plus le TLB, mais gère les pages de cache au niveau des invités, évitant au vmm de gérer les shadow copy coûteuses.

Au niveau de l'OS, les hugepages de 2M, voir 1G sont utiles pour réduire le nombre de pages. Avec des tailles de page de 2Mo, le TLB peut ainsi maintenir l'adressage de 16Go de RAM sur les cpu modernes, ce qui réduit grandement les vm-exist. Couplé avec HAP vu précédemment, les vm-exits sont considérablement réduits.

Sous Linux, il existe 2 gestionnaires de grandes pages, hugetlbpage et transparent_hugepage. Ce dernier est le plus perfomant pour la virtualisation mais n'est pas recommandé pour certaines applications comme les bases de données, on préfèrera dans ce cas utiliser hugetlbpages.

 

CFS

Sous Linux, le scheduler prend en compte 5 modes de gestion des processus:

normal (ou other):  applique les tâches normalement
batch: Ne permet pas à ces tâches d'être préemptés, ce qui résulte d'une meilleur utilisation du cache CPU, mais rend ces tâches moins interactives.
idle: Ces tâches sont lancées quand il n'y à plus de tâche prêtes dans le système. Dans ce système, c'est à l'utilisateur de classer ses tâches en utilisant chrt, parce que le scheduler n'est pas capable de classifier une tâche.
fifo: Temps-réel, les tâches n'ont pas de quanta finis, mais s'exécutent jusqu'à la fin ou jusqu'à ce que le cpu soit relâché.
rr: Temps-réel, le scheduler définis un quanta et planifie les tâches basés sur l'algorithme round-robin.

Il prend également en compte la priorité des tâches. Il utilise des priorités de 0 à 99 pour les tâches temps-réels, et de 100 à 139 pour les autres tâches. Par défaut, une tâche a une priorité de 120, et des outils tels que nice/snice permettent d'ajuter la priorité dans une plage relative de -20 à +19, ce qui permet de gérer la priorité dans la plage 100 à 139.

Sur les serveurs, les paramètres de temps d'exécution des tâche doit être adapté: sched_min_granularity_ns à 10000000 et sched_wakeup_granularity_ns à 15000000 sont un bon point de départ.

 

Entrées/Sorties

La gestion des opérations d'écriture disque est une des données les plus importantes puisque la puissance cpu n'est rien si le système passe son temps à attendre les opérations de lecture/écritures. Je donne ici quelques conseils:

- Toujours utiliser les pilotes virtio, il n'y a aucune raison de s'en passer.
- Assigner un disque physique ou même une partition est toujours plus performant, mais complique la migration.
- Présenter des périphériques block réseaux est toujours préférable à un fichier dans un système de fichier monté localement.
- Un système de fichier journalisé dans un disque virtuel fichier, lui-même sur un système journalisé peut sembler un peu inutile.
- mtime et atime rendent les caches de lecture moins efficaces.
- Le format de disque raw est le plus performant (mais le moins fiable).
- Le cache d'écriture doit être géré par l'os qui dialogue directement avec les disques sachant que writethrough est très bon pour les lectures intensives, et none est meilleur pour les opérations d'écritures.
- Linux AIO et x2APIC améliorent sensiblement les performances
- Le scheduler d'E/S Deadline est le plus performant pour la virtualisation (hôte et invité)
- Désactiver le delay accounting et le random entropy contribution
- Éviter l'overcommit mémoire et cpu.
- Les invités avec 2 vcpu offrent de meilleurs performances d'écriture.
- Comme pour tout serveur, les dirty page sont à adapter pour un usage serveur: ratio à 40% et background_ratio à 15%.
- Supprimer ulatencyd, conçu pour un usage desktop.

 

Présentation des périphériques

La documentation Intel décrit les 5 modes de présentation des périphériques:

- Complète: consiste à émuler de manière entièrement logiciel le matériel.
- Émulation: le VMM présente à la vm un périphérique générique.
- Synthétique: Le VMM expose un périphérique spécifique, et l'invité doit posséder également le pilote dédié.
- Assignement. Le VMM expose un périphérique matériel.
- E/S partagé. Le VMM expose un périphérique matériel partagé.

Le modèle synthétique reste le meilleur choix dans la majorité des cas, mais cela dépend des périphériques et besoins. Par exemple, un lecteur cdrom est souvent de l'émulation complète, de même pour les clavier/souris/carte graphique. La présentation des périphériques physique offre les meilleurs performances, mais complique sérieusement les migrations.

D'une manière générale on évitera au maximum la présentation de périphérique générique, puisque l'on se retrouve avec 2 pilotes l'un sur l'autre. Le mode synthétique utilise par contre un pilote guest dédié, qui n'est finalement qu'une passerelle vers le pilote de l'hôte.

 

Les pilotes virtio

Linux est fournis avec plusieurs pilotes virtio. Ces pilotes sont des périphériques synthétiques haute performance. il existe des pilote virtio PCI, SCSI, balloon, rng, serie, console, réseaux, etc. Inutile de rappeler de les utiliser systèmatiquement.

 

Périphérique balloon

Balloon est un périphérique qui permet à l'hôte de réclamer de la mémoire vive à chaud auprès de l'invité, en clair, de gérer l'allocation dynamique à chaud de la mémoire vive des invités. Il est capable de réclamer de la mémoire inutilisée par un invité pour l'allouer à un autre invité qui en a besoin. Sous Linux, ce périphérique est fournis via un pilote virtio.

 

QXL/Spice

Conçus pour le VDI, QXL est une carte graphique paravirtualisée, et Spice un protocole de connexion à distance qui sépare le trafic en canaux pour un contrôle optimal, et permet de chiffrer le trafic et fournis un mécanisme d'authentification forte. Ce protocole donc bien plus interressant que vnc.

 

Horloges

Il existe plusieurs types d'horloges, et il est possible d'en fournir plusieurs à une machine virtuelle, ce qui est une bonne chose puisque l'invité choisira, en fonction de ce qu'il supporte, le timer qui lui convient le mieux.

RTC ( Real Time Clock) permet de créer des décomptes du temps, avec une précision le l'ordre du milliseconde, ce qui n'est pas suffisamment précis de nos jours.

PIT ( Programmable Interval Timer) est plus précis, mais il est peu utilisé à la faveur des timers présents dans les APIC, plus précis.

HPET ( High Precision Event Timer) est une horloge haute précision présente dans les architectures Intel récentes et tend à remplacer les 2 précédent, mais n'est supporté que les systèmes récents.

TSC ( Time Stamp Counter) est un registre CPU qui compte le nombre de cycle depuis le dernier reset. Il est très simple à utiliser mais ne peut pas fournir un résultat très précis vu que la fréquence d'horloge des CPU moderne est ajustée en permanence.

 

Les threads

Qemu offre la possibilité de créer des iothreads et de les assigner à des opérations d'E/S ou réseaux. Avec les cgroups, on peut aller plus loin, en dédiant des cpu physiques aux opérations d'E/S pour optimiser d'avantage les opérations disques.

Sous QEMU, on les crée un par un avec la commande object:
-object iothread,id=MyIoThread

Sous libvirt c'est plus simple
<iothreads>2</iothreads>

Une fois les threads crées, on peut assigner des opérations d'écritures avec:
iothread=MyIoThread

Sous libvirt, il ne reste plus qu'à mapper le thread à un cpuset et éventuellement de sélectionner le mode de CFS:
<iothreadpin iothread='1' cpuset='7'/>
<iothreadssched iothreads='1' scheduler='rr' priority='1'/>

On peut également faire de même pour le mappage des vcpus:
<vcpupin vcpu="0" cpuset="5"/>
<vcpusched vcpus='5,6' scheduler='batch'/>

 

swap

Quand un OS comme à swapper, les performances s'écroulent. C'est encore plus vrai pour un invité, qui peut monopoliser les accès disques au détriment des autres. Il est donc important de valider que le swap ne soit jamais utilisé. Cependant, il est déconseillé de ne pas avoir de swap, cela évite bien des problèmes. Un bonne pratique consiste à utiliser des disques ou des volumes réseaux dédiés au swap, afin de ne pas interférer avec les disques utilisés par le système et garantir un fonctionnement sans trop de dégradation.

 

Notes

De nombreuses options sont possibles mais non prises en charge actuellement. Par exemple il est techniquement possible d'assigner des threads pour les périphériques réseaux, mais cela n'est pas pris en compte. QEMU et Libvirt étant en constante évolution, les fonctionnalités évoluent rapidement et il est difficile de se tenir à jours.

Aucun commentaire pour cet article

Note: Les commentaires sont temporaiment désactivés, merci de contacter l'auteur par mail