Aller au contenu

Blog ·

VM ou conteneur : que vendre sur Proxmox

Un invité KVM et un conteneur LXC partagent un hyperviseur, un espace de numéros et une grille tarifaire, et presque rien d’autre. Les écarts qui coûtent.

Par Provibr

Proxmox VE fait tourner deux sortes d’invités. Une machine virtuelle KVM démarre son propre noyau derrière un micrologiciel émulé, et un conteneur LXC partage le noyau de l’hôte sur lequel il se trouve. Pour un client qui achète un VPS, les deux sont « un serveur avec un accès root », et c’est bien pourquoi la comparaison se fait d’ordinaire dans un tableau marketing dont les lignes parlent de densité et de surcoût.

Ces lignes sont vraies et ce ne sont pas celles qui vous coûteront quelque chose. Ce qui coûte, c’est l’ensemble des endroits où les deux se ressemblent dans l’API et se comportent différemment en dessous, parce que c’est là qu’un panneau, un système de facturation ou un parcours de commande fait discrètement la mauvaise chose sans que personne ne le remarque pendant un mois.

Nous avons récemment ajouté un second type de calcul à notre propre intégration Proxmox, ce qui a supposé de lire l’API avec une question précise en tête : où ces deux-là divergent-ils. Voici ce qui en est ressorti, dans l’ordre où cela nous a surpris.

Un cluster, un seul espace de numéros

Commencez par l’identifiant, car tout le reste en dépend. Un invité Proxmox est adressé par un numéro, et il est tentant de supposer que les machines virtuelles et les conteneurs disposent chacun de leur propre plage : 100 pourrait être une machine virtuelle et 100 pourrait aussi être un conteneur, distingués par leur type.

Ce n’est pas possible. L’espace de numéros est partagé par l’ensemble du cluster, et trois propriétés de l’API le disent. Le point d’entrée qui distribue l’identifiant libre suivant ne prend aucun paramètre de type, il ne peut donc pas savoir laquelle des deux sortes vous êtes sur le point de créer. La liste des ressources du cluster renvoie machines et conteneurs ensemble sur le même champ numérique. Et la liste des invités du cluster est indexée par ce numéro.

Cela a une conséquence directe pour tout ce qui stocke des invités Proxmox dans sa propre base de données. Mettez la sorte dans votre contrainte d’unicité, de sorte que « machine 5001 » et « conteneur 5001 » soient deux lignes différentes, et vous obtenez un schéma capable de contenir deux enregistrements pour un seul invité et de les laisser se disputer. L’identifiant est unique à lui seul, et la sorte est une observation rangée à côté de lui. Si vous choisissez des plages pour un parc, l’arithmétique de choisir une plage de VMID sur Proxmox ne change pas quand les conteneurs arrivent, et c’est bien là l’intérêt.

Un conteneur se décompresse, il ne se clone pas

La deuxième divergence est le chemin de création, et elle est plus importante qu’il n’y paraît.

Une machine virtuelle est normalement produite en clonant un modèle : vous nommez une source, vous choisissez un clone complet ou lié, et vous obtenez une copie d’une image disque. Un conteneur est produit en décompressant une archive sur un volume neuf. Il n’y a pas d’invité source, il n’y a pas de choix entre complet et lié, et il n’y a pas de lecteur cloud-init, parce qu’il n’y a rien à quoi rattacher un lecteur.

Le corps de la requête n’a donc presque aucun champ en commun avec celui qui crée une machine. Un conteneur veut un ostemplate pointant vers une archive sur un stockage, un indicateur unprivileged, un hostname, un rootfs et une valeur swap. Une machine veut scsi0, scsihw, bios, boot et un ide2 lorsqu’elle démarre depuis une ISO. Réutiliser le vocabulaire de l’un pour l’autre est l’erreur à éviter délibérément : les mots se ressemblent assez pour qu’un champ nommé disk finisse par désigner deux choses différentes dans la même base de code en moins d’un an.

Deux détails de ce corps de requête méritent d’être repris, quelle que soit la technologie sur laquelle vous construisez.

rootfs=<storage>:<size> est une allocation, pas une référence. Cela veut dire « créer un nouveau volume de tant de gigaoctets sur ce stockage ». La forme qui nomme un volume existant lui ressemble presque en tout point et fait quelque chose de catégoriquement différent : elle adopte un volume qui contient peut-être encore les données de quelqu’un d’autre.

Omettre un paramètre est la réponse sûre. L’imbrication, keyctl, FUSE, les montages liés et le passage de périphériques sont tous désactivés tant que vous ne les envoyez pas, et il n’existe aucune valeur « vide » qu’il faudrait penser à écrire. La posture par défaut correcte pour une plateforme d’hébergement est donc une requête courte plutôt qu’une requête longue. Le champ d’architecture raconte la même histoire : Proxmox le déduit de l’archive, et en envoyer un qui la contredit échoue au moment de la décompression.

Trois choses qu’un conteneur ne fera jamais

Certains manques sont des éléments de feuille de route. Trois sont structurels, et confondre les deux catégories dans votre propre produit est la manière dont on finit par promettre une fonction qui ne peut pas exister.

ActionInvité KVMConteneur LXC
Démarrer, arrêter, éteindre, supprimerouioui, même forme, segment de chemin différent
Mettre en pause ou en hibernationouinon : cela relève du moniteur QEMU
Démarrer sur le réseau en PXEouijamais
Installer depuis une ISOouijamais
Choisir un ordre d’amorçage, BIOS ou UEFIouijamais
Consoleframebuffer VNCun terminal, sur un autre protocole
Swapinvisible pour l’hôteun réglage d’hyperviseur avec un nombre

Cinq de ces lignes demandent plus qu’une cellule, en trois groupes.

Le démarrage réseau, l’installation par ISO et le choix du micrologiciel sont impossibles pour une seule raison, et non pour trois : un conteneur n’a pas de micrologiciel. Il n’exécute pas de chargeur d’amorçage, il n’a pas d’ordre d’amorçage, et son démarrage ne fait intervenir rien à quoi l’on pourrait demander d’essayer le réseau en premier. Si vous vendez un produit où « réinstaller depuis notre bibliothèque d’images » est une fonction, notez que le chemin PXE, de la réponse DHCP à l’installation terminée n’a aucun équivalent pour un conteneur. Reconstruire un conteneur est un mécanisme différent avec des garanties différentes, et cela mérite son propre écran plutôt qu’un bouton grisé.

La console est le même genre de différence sous un nom familier. Proxmox vous donnera bien une console pour un conteneur, mais c’est un terminal sur une websocket, pas le framebuffer d’une carte graphique, et un client VNC ne l’affichera pas. Un même onglet de console a désormais deux implémentations derrière lui, et la réponse honnête en attendant est de dire que l’onglet n’est pas encore disponible plutôt que d’ouvrir une visionneuse qui montre un rectangle noir.

La pause et l’hibernation méritent une note, car elles piègent la logique d’application des règles. Si votre plateforme suspend une machine quand un client dépasse une limite, et que « suspendre » veut dire mettre en pause, alors les conteneurs sortent entièrement du champ : la commande est refusée, aucun processus de traitement ne remonte quoi que ce soit, et le client continue de tourner. La frontière appartient au mode, pas à la commande. Arrêter un conteneur est parfaitement possible.

Le swap est une décision produit, pas une valeur par défaut

Voici celle qui finira dans les tickets de support.

Proxmox donne à un nouveau conteneur 512 Mio de swap sauf indication contraire. Héritez de cela sans le dire et un plan vendu comme « 2 Gio de mémoire » livre 2,5 Gio de mémoire utilisable, et l’écart n’apparaît nulle part sous la forme d’un nombre plus grand : il apparaît sous la forme d’un conteneur qui devient lent au lieu de rencontrer une franche condition de mémoire insuffisante, des mois plus tard, sur un hôte qui s’est mis à swapper.

Nous envoyons la valeur explicitement à chaque création, avec zéro comme valeur par défaut. Zéro est un choix, pas une absence. Quel que soit votre choix, faites-le délibérément, inscrivez-le sur le plan, et assurez-vous que le nombre que voit un client est le nombre que reçoit l’hyperviseur.

Mesurer le swap a son propre prix. La liste groupée qui vous donne les compteurs de processeur, de mémoire, de disque et de réseau pour chaque invité d’un cluster ne porte aucun champ de swap, pour aucune des deux sortes. Le seul endroit où Proxmox le rapporte est le point d’entrée d’état par invité, ce qui fait un appel HTTP supplémentaire par conteneur en fonctionnement, pour toujours. Nous le lisons une fois par minute : trois fois par minute triple la charge sur l’hyperviseur de quelqu’un d’autre pour un nombre qui évolue en minutes, et une fois toutes les cinq minutes place exactement un échantillon dans une fenêtre d’agrégation de cinq minutes, ce qui rend la colonne du maximum égale à celle de la moyenne, et donc décorative.

Deux bogues que nous avons livrés en les prenant pour la même chose

Les deux étaient en production depuis des mois avant que nous allions y regarder de plus près.

Le premier : notre écran d’importation listait les conteneurs comme des machines virtuelles. La liste des ressources du cluster avec type=vm n’est pas un filtre QEMU, elle renvoie les deux sortes, et le champ qui indique laquelle n’était tout simplement pas lu. Rien n’a échoué. La liste était fausse.

Le second était plus discret. Chaque conteneur en fonctionnement recevait deux appels d’agent invité par tour de sondage, plus un après chaque commande, contre un chemin qui n’existe que pour QEMU. Chacun était un échec garanti, et rien n’a fait surface, parce qu’un enrichissement facultatif qui échoue est censé être survivable, et il l’était. Cela a été trouvé par un test qui compte quels chemins sont appelés au lieu d’affirmer des résultats, une habitude qui vaut la peine d’être copiée : n’affirmez que sur les résultats et toute une catégorie de travail inutile reste invisible.

Ce que nous écririons avant de vendre l’un ou l’autre

Si vous décidez de ce qu’un produit d’hébergement doit proposer sur Proxmox, quatre questions vous mènent presque au bout.

  1. La sorte est-elle une propriété du plan ou un choix au moment de la commande ? Les deux se défendent. Une valeur par défaut cachée sous le choix, non : un client qui a commandé un conteneur et reçu une machine a obtenu un autre modèle de sécurité, un autre noyau et un autre ensemble de capacités que celui qu’il avait choisi.
  2. Quels refus sont permanents et lesquels sont temporaires ? Dites-le dans l’interface, avec ces mots-là. « Impossible pour un conteneur » et « pas encore construit » sont deux promesses différentes.
  3. D’où vient la protection contre l’usurpation ? Le manque honnête dans notre propre travail : une machine clonée reçoit un filtrage IP à la livraison, un conteneur pas encore. Proxmox a les mêmes points d’entrée de pare-feu pour les deux, c’est donc une étape de construction et non un obstacle, mais un conteneur livré sans cela peut émettre du trafic en prétendant être quelqu’un d’autre.
  4. Que montre la supervision pour un conteneur ? Tout ce qui dérive d’un agent invité, d’un framebuffer ou d’un micrologiciel est vide. Vide, c’est très bien. Vide présenté comme un zéro en bonne santé, non.

Nous avons le champ de plan, le parcours de commande et la requête de création construits et mesurés contre la forme HTTP brute de l’API. Ce que nous n’avons pas fait, c’est créer un conteneur sur l’hyperviseur de production de quelqu’un, si bien que la description honnête de notre prise en charge des conteneurs est « la forme est juste et l’aller-retour n’est pas testé », ce qui est une chose utile à savoir dire à voix haute au sujet de sa propre plateforme.

Ceci est issu de la construction de l’intégration Proxmox pour Provibr, où l’agent tourne à l’intérieur du réseau du client et ne se connecte jamais que vers l’extérieur. L’habitude voisine, ne pas faire confiance à la réponse de succès d’un hyperviseur, est dans pourquoi un 200 de Proxmox n’est pas un résultat.

Commencez avec un hôte et un agent

Créez un compte, installez l’agent avec une seule commande et connectez votre premier hôte Proxmox. La période d’essai dure 14 jours et ne demande aucune coordonnée de paiement.