6 points par GN⁺ 2025-03-15 | 2 commentaires | Partager sur WhatsApp
  • Sandbox monoprocessus basé sur KVM
    • Permet d’exécuter dans un sandbox des programmes Linux classiques ou des programmes utilisant une API spécifique
  • Fournit des performances natives grâce à la virtualisation matérielle
  • N’utilise qu’une partie de l’API KVM → base de code réduite et efficace

Conception de TinyKVM

  • Prise en charge de l’exécution de programmes Linux ELF statiques
    • La prise en charge des exécutables dynamiques sera ajoutée plus tard
    • Peut aussi être étendu via une API afin de fournir un accès à un serveur HTTP externe ou à un cache
    • Fonctionne actuellement sur AMD64 (x86_64), avec un portage vers AArch64 (ARM 64 bits) prévu
  • Prise en charge des hugepages
    • Il est possible de créer des hugepages pour les pages invitées
    • L’hôte peut aussi utiliser des hugepages → amélioration des performances
    • Exemple : avec des pages de 2 Mo, une hausse de 5 % des performances de compilation LLVM a été constatée
  • Appels de fonction rapides
    • Lors d’un appel de fonction depuis l’invité, le surcoût est de 2 μs
    • Sans timer pendant l’exécution, le surcoût descend à 1,2 μs
  • Prise en charge du débogage à distance
    • Débogage à distance possible avec GDB
    • Reprise normale du programme possible après le débogage
  • Prise en charge du Copy-on-Write
    • Fonction de fork intégrée → permet de réduire au minimum la duplication mémoire
    • Exemple : lors de la duplication d’un modèle de 6 Go, seulement 260 Mo de mémoire sont nécessaires par instance
  • Initialisation rapide de l’état
    • L’état de l’invité peut être réinitialisé rapidement → sécurité renforcée
    • Une réinitialisation à chaque requête réduit le risque d’exposition d’état
  • Base de code simplifiée
    • Environ 42 kLOC de l’API KVM sont utilisés
    • La base de code propre à TinyKVM fait environ 9 kLOC → bien plus petite que les solutions concurrentes
    • Exemple : Wasmtime 350 kLOC, FireCracker 165 kLOC
  • Création statique des tables de pages
    • Impossible de modifier les tables de pages à l’exécution → sécurité renforcée
    • Vérification de l’intégrité des tables de pages effectuée
  • Contexte de processus isolé
    • L’invité KVM utilise un PCID/ASID distinct → plus résistant aux attaques par exécution spéculative comme Spectre
  • Noyau renforcé pour la sécurité
    • SMEP et SMAP activés
    • Gestion possible des exceptions CPU en mode utilisateur

Gestion des appels système

  • Connexion API avec l’hôte
    • Les appels système sont effectués via les instructions SYSCALL/SYSRET ou OUT
    • L’exécution d’un appel système provoque une sortie de VM → environ 1 μs
    • Il est recommandé de limiter les petits appels et de concevoir une API avec de grosses unités d’entrée/sortie

Benchmarks

  • Surcoût des appels VM
    • Mesure de la tail latency lors de la réinitialisation de la VM
    • Le surcoût est faible pour un simple appel sans réinitialisation
  • Performances mémoire
    • Les performances mémoire sont normales
    • Exemple : dans un benchmark HTTP, 1 500 encodages AVIF par seconde sont possibles
  • Performances de conversion JPEG → AVIF
    • Environ 1 582 images peuvent être converties par seconde
    • Une conversion sans perte est possible en utilisant le chemin de conversion YUV

Pourquoi le sandbox est rapide

  • Aucun I/O ni pilote utilisé
    • Pas d’I/O, de pilotes ni de périphériques virtuels → évite les pertes de performances
    • Utilise uniquement les ressources CPU → vitesse proche du natif
  • Optimisation via hugepages
    • L’usage de hugepages réduit les page walks → amélioration des performances
    • Atteint 99,7 % des performances natives sur de grosses charges LLM
  • Appels VM rapides
    • Surcoût minimal lors des appels de fonction depuis l’invité
    • Traitement des données à vitesse CPU native

Limites

  • Impossible de réduire le nombre de vCPU
    • L’API KVM ne permet pas de réduire le nombre de vCPU
    • Le multiprocessus peut être géré en exécutant plusieurs VM en parallèle
  • Baisse de performances lors de la réinitialisation
    • Une baisse de performances peut survenir lors de la réinitialisation de l’état de la VM
    • Mais cela peut être résolu via le partage et la duplication d’état

Travaux à venir

  • Ajout de la prise en charge d’Intel TDX et d’AMD SEV
  • Portage vers AArch64
  • Ajout d’une fonction de verrouillage mémoire (KVM_MEM_READONLY) → sécurité renforcée
  • Amélioration d’une API plus conviviale
  • Ajout de la prise en charge du chargement de liens dynamiques → meilleure intégration avec Varnish

Conclusion

  • TinyKVM est l’une des solutions de sandbox les plus petites et les plus rapides
  • Combine renforcement de la sécurité et optimisation des performances
  • Sa base de code réduite facilite la maintenance
  • Disponible comme bibliothèque open source → si le sujet vous intéresse, vous pouvez consulter le dépôt de code

Dépôt TinyKVM

2 commentaires

 
xcutz 2025-03-16

C'est original.

 
GN⁺ 2025-03-15
Commentaires sur Hacker News
  • J’aime vraiment beaucoup ça. J’espère qu’ils ne s’arrêteront pas et continueront ce qu’ils font actuellement

    • Je savais qu’il était un contributeur majeur d’IncludeOS. C’est le premier projet auquel j’ai pensé en lisant ce billet de blog
    • Je suis obsédé depuis longtemps par la virtualisation des fonctions réseau. C’est la frontière la plus naturelle pour séparer les unités de travail dans les systèmes distribués, et cela offre une abstraction propre ainsi qu’un mécanisme de montée en charge efficace
    • J’utilise Varnish en production avec une très grande satisfaction. Sur certains aspects, je le trouve même plus fiable que nginx. En général, on finit par oublier jusqu’à son existence. Une fois correctement configuré, il n’a jamais été à l’origine d’un bug
  • C’est similaire à Firecracker, mais beaucoup plus rapide

    • Ce que je préfère, c’est la capacité à réinitialiser instantanément l’état de la VM à un état prédéfini. C’est comme redémarrer la VM sans réellement la redémarrer
    • Cela semble être une mesure idéale pour les services réseau continuellement attaqués. Même si une attaque réussit, le résultat est effacé dès la requête suivante
    • Le partage simple de pages COW est aussi très appréciable pour des programmes comme des exécuteurs de modèles ML, qui n’ont pas été écrits en tenant compte de ce point
  • Publication originale : lien

    • On peut trouver beaucoup de publications liées à ce sujet
  • Vraiment intéressant. Les performances de restauration de snapshot en 2.5us sont comparables à Wasmtime, avec le gros avantage de pouvoir exécuter du code natif. En revanche, c’est bien plus lent tout en conservant une interopérabilité à l’échelle de la microseconde

    • Il y a déjà une démo QuickJS dans le dépôt tinykvm_examples, mais ce serait encore plus rapide s’ils pouvaient vérifier s’il est possible d’exécuter un runtime JavaScript avec JIT
    • Dans une expérience de rendu serveur d’une app React, QuickJS natif tournait autour de 12-20ms, tandis que v8 était à 2-4ms après l’échauffement du JIT
    • Je dois encore approfondir le sujet, mais j’aimerais créer un exécutable autonome de type Deno, exécuté dans le sandbox et traitant toutes les requêtes HTTP via Varnish
    • Récupérer une URL JS donnée, puis prendre un snapshot, afin que chaque requête s’exécute dans un snapshot isolé
    • Il faudra sans doute un mécanisme pour réinitialiser la graine aléatoire à chaque requête
  • En gros, ce n’est pas la même chose que libkrun ? lien

  • Ce n’est pas exactement le cas d’usage visé, mais est-ce que quelqu’un a déjà essayé d’exécuter un serveur X (ou Wayland) ?

    • Je développe sur Mac pour un serveur RDP, et j’ai parfois d’autres besoins côté client. Pour le moment, j’utilise une VM UTM (frontend Mac pour QEMU) avec DietPi (une Debian très allégée)
    • Je suis à l’aise avec Docker, mais je connais bien les étapes nécessaires pour faire tourner un serveur graphique. Je me demande s’il existe une méthode plus simple
  • C’est intéressant, mais j’ai du mal à comprendre la vue d’ensemble. Est-ce qu’il s’agit d’exécuter un processus utilisateur dans une VM sans noyau ? Est-ce que tous les appels système provoquent la sortie de la VM pour être proxifiés vers l’hôte ? Ou bien n’y a-t-il tout simplement pas d’appels système ?

  • Si cela correspond à votre cas d’usage, c’est vraiment génial

    • Quelques notes tirées de l’article
    • TinyKVM a été mesuré à 99.7% de la vitesse native
    • Si le programme est statique et n’a pas besoin d’accès fichier ou réseau, il peut simplement être exécuté directement
    • Les invités TinyKVM ont un petit noyau immuable
  • Vraiment cool

    • J’explore les micro-VM pour une PaaS auto-hébergée, et cela semble être une option vraiment intéressante grâce à sa faible surcharge
  • L’article ne dit pas que cela tourne au-dessus de Varnish, et en réalité l’auteur précise que ce n’est pas conçu pour exécuter Varnish