CPU steal sur VPS : repérer un voisin bruyant
Comprenez le CPU steal d’un VPS, lisez la colonne st de vmstat et distinguez un voisin bruyant d’une surcharge de vos propres processus.
Ce que mesure réellement le temps CPU steal
Le temps CPU steal correspond à la part du temps pendant laquelle votre CPU virtuel était prêt à s’exécuter, sans rien attendre, mais où l’hyperviseur attribuait le cœur physique à une autre machine virtuelle. Le travail était en attente dans la file. Le cœur était utilisé ailleurs. Linux comptabilise ces cycles séparément et les signale sous st. Vous pouvez ainsi distinguer « mon serveur est occupé » de « mon serveur attend son tour ».
C’est précisément la raison d’être de ce compteur. Le temps que vos propres processus passent sur le CPU est comptabilisé sous us (user) ou sy (system). Le temps pendant lequel une tâche reste bloquée sur le stockage est comptabilisé sous wa (I/O wait). Un vCPU (CPU virtuel) prêt à s’exécuter, présent dans la run queue, sans opération d’I/O en attente et qui ne s’exécute toujours pas, est comptabilisé sous st. Rien dans votre serveur ne peut mettre fin à cet état, car la décision d’ordonnancement est prise un niveau en dessous, sur l’hôte.
Cela découle directement de la manière dont un VPS partage une même machine physique entre plusieurs machines virtuelles. La cause habituelle est un voisin : une autre machine virtuelle du même nœud utilise fortement le CPU, et l’hôte répartit les cœurs entre vous. Une seconde cause est souvent oubliée. De nombreux fournisseurs plafonnent un vCPU partagé à une fraction d’un cœur physique. Sur plusieurs hyperviseurs, ce plafond appliqué est comptabilisé comme du steal dans la machine virtuelle. Une valeur st élevée indique donc que le cœur ne vous a pas été attribué. Elle n’indique pas toujours qui l’utilisait.
D’où vient le nombre de steal
Votre noyau ne peut pas mesurer le steal seul, car il n’a pas accès à l’hôte. C’est l’hyperviseur qui le lui indique. Avec KVM, l’hôte écrit un compteur par vCPU dans une page partagée avec le guest, puis le guest l’additionne lorsque le noyau est compilé avec CONFIG_PARAVIRT_TIME_ACCOUNTING, ce qui est le cas de tous les noyaux de distribution. Xen fournit la même information via sa zone runstate. Le total arrive dans l’espace utilisateur à un seul endroit :
head -1 /proc/statCette ligne cpu contient dix compteurs, exprimés en ticks USER_HZ depuis le démarrage, dans cet ordre : user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice. Le steal correspond à la huitième valeur après le libellé. Tous les outils ci-dessous, vmstat, top, mpstat et les exporters Prometheus, lisent ce même champ et convertissent deux échantillons en pourcentage.
Une conséquence est plus importante que les autres. Si l’hyperviseur n’exporte jamais le compteur, le champ reste toujours à zéro, et tous les outils qui l’utilisent indiquent un 0.0 normal alors que l’hôte est en surcharge. KVM et Xen l’exportent. Sur les autres plateformes, notamment VMware et Hyper-V, l’affichage du steal dépend de ce que l’hôte expose et de ce que le noyau du guest prend en charge. Une valeur nulle constante ne prouve donc rien à elle seule. Vérifiez la plateforme avant de faire confiance à une valeur nulle :
systemd-detect-virtLa commande affiche le nom de la plateforme, par exemple kvm, xen, vmware ou microsoft, et none sur un serveur bare metal. Dans un conteneur, elle indique à la place le runtime, par exemple lxc, docker ou podman. Elle renseigne alors sur le conteneur, pas sur la machine sous-jacente. Avec kvm, une valeur nulle indique réellement que l’hôte vous accorde suffisamment de temps CPU. Sur une plateforme qui ne renseigne jamais ce champ, une valeur nulle n’apporte aucune preuve. Il faut alors évaluer la contention en mesurant le temps nécessaire à l’exécution d’un travail réel.
Comment vérifier le temps de vol CPU sur un VPS ?
vmstat provient du paquet procps. Il est présent dans presque toutes les images VPS Ubuntu et Debian, mais peut manquer dans certaines images de conteneur minimales. Installez-le avant d’en dépendre.
sudo apt-get update
sudo apt-get install -y procps
vmstat --version
vmstat 1 5vmstat --version affiche une ligne telle que vmstat from procps-ng 4.0.4. Si cette ligne s’affiche, l’outil est installé et vous lisez de vrais compteurs du noyau. vmstat 1 5 affiche ensuite cinq rapports : le premier correspond à la moyenne depuis le démarrage, et les quatre suivants sont des échantillons espacés d’une seconde.
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
r b swpd free buff cache si so bi bo in cs us sy id wa st gu
1 0 0 3216484 98304 1284360 0 0 4 18 62 110 3 1 96 0 0 0
2 0 0 3216232 98304 1284360 0 0 0 0 248 431 6 2 84 0 8 0Recherchez la colonne st dans le bloc cpu à droite. Les versions actuelles de procps-ng affichent ensuite une colonne gu pour le temps du guest KVM. st est donc l’avant-dernière colonne, et non la dernière. Lisez la colonne à partir de son nom d’en-tête, car cette position a changé selon les versions.
Deux habitudes permettent d’obtenir une mesure fiable. La première ligne de données correspond à la moyenne depuis le démarrage : ignorez-la et lisez les lignes suivantes. Un seul échantillon ne constitue pas une mesure, car le temps de vol survient par rafales. Exécutez vmstat 1 61, qui fournit soixante échantillons d’une seconde après la ligne correspondant au démarrage, puis observez une minute complète avant de tirer une conclusion.
top indique le même nombre sur sa ligne récapitulative %Cpu(s), dans le champ marqué st :
%Cpu(s): 6.2 us, 2.1 sy, 0.0 ni, 83.9 id, 0.0 wa, 0.0 hi, 0.3 si, 7.5 stPour obtenir le détail par cœur, ajoutez sysstat :
sudo apt-get install -y sysstat
mpstat -P ALL 1 5mpstat affiche une ligne par CPU avec une colonne %steal. Elle indique si tous les vCPU sont concernés ou si un seul l’est. Pour conserver l’historique nécessaire à un ticket de support, enregistrez les échantillons au lieu de les lire à l’écran :
date -u | tee -a ~/steal.log
mpstat -P ALL 1 5 | tee -a ~/steal.logExécutez cette commande depuis cron pendant les heures où vous soupçonnez le problème. Le fichier vous permettra de remplacer « le serveur semblait lent hier soir » par les dix minutes exactes.
Que signifient les valeurs de steal ?
- Un
0.0stable. C’est normal, ou la plateforme ne signale pas du tout le steal. Vérifiez avecsystemd-detect-virtavant de conclure. - Des pointes de quelques pourcents pendant quelques secondes. C’est normal sur tout nœud partagé. Une compilation démarre chez un voisin ou l’hôte exécute ses sauvegardes.
- De 1 à 5 pourcents de manière durable sur une offre partagée. C’est attendu. Le prix reflète le partage du CPU.
- De 5 à 10 pourcents de manière durable. Le ralentissement est mesurable. Commencez à recueillir des éléments et comparez les mêmes heures sur plusieurs jours.
- Plus de 10 pourcents pendant plusieurs heures. Le nœud est peut-être surchargé pour votre charge de travail, ou la limite de CPU de votre offre est appliquée. Certains fournisseurs signalent cette limite comme du steal. C’est le niveau qui justifie l’ouverture d’un ticket auprès du support ou un changement d’offre.
Considérez ces fourchettes comme un guide d’interprétation plutôt que comme une spécification, car aucun fournisseur ne garantit un niveau de steal sur une offre partagée. Mettez-les en regard de votre charge de travail. Un traitement batch nocturne peut supporter 15 pourcents de steal sans que personne ne le remarque. Un service sensible à la latence le montre dans le p99 bien avant que la moyenne ne devienne alarmante. C’est pourquoi les charges de travail sensibles à la latence, comme les bots de trading doivent utiliser des cœurs dédiés.
Quel est le coût du steal time pour vous ?
Le calcul est simple. Si une fraction s de votre temps CPU est accaparée, une tâche qui nécessite une quantité fixe de CPU prend 1 / (1 - s) fois plus longtemps en temps réel. Pour une tâche nécessitant 60 secondes de CPU :
Les données de ce graphique
[
{
"steal_percent": 0,
"wall_clock_seconds": "60.0"
},
{
"steal_percent": 3,
"wall_clock_seconds": "61.9"
},
{
"steal_percent": 8,
"wall_clock_seconds": "65.2"
},
{
"steal_percent": 15,
"wall_clock_seconds": "70.6"
},
{
"steal_percent": 25,
"wall_clock_seconds": "80.0"
},
{
"steal_percent": 40,
"wall_clock_seconds": "100.0"
}
]À 3 %, selon une valeur courante sur une offre mutualisée, cette tâche prend 61.9 secondes au lieu de 60.0. Personne n’ouvre un ticket pour cela. À 8 %, elle prend 65.2 secondes. À 40 %, la même tâche nécessite 100.0 secondes, et une file qui se vidait commence alors à s’allonger.
Il s’agit de valeurs calculées, et non de mesures. Le modèle suppose un thread exécutable unique et un steal réparti uniformément sur l’intervalle. Les services réels semblent souvent plus lents que ne le suggère la courbe, car une tranche de temps accaparée peut interrompre une requête et le délai est alors subi à nouveau par tous les traitements qui attendent cette requête. Pour obtenir votre propre valeur plutôt qu’une formule, évaluez les performances du VPS pendant une période creuse, puis de nouveau pendant une période chargée, en enregistrant st pour les deux périodes.
Est-ce du steal, ou autre chose ?
Le steal est facile à confondre avec d’autres symptômes. Lisez les compteurs ensemble, sur la même ligne vmstat.
stélevé, tandis queretusrestent faibles : l’hôte ne vous attribue pas le vCPU. C’est du steal.rnettement supérieur au nombre de vCPU, avecusélevé etstproche de zéro : vous exécutez plus de tâches que vos propres processeurs ne peuvent en traiter. Comparezravec la sortie denproc. Il s’agit de votre propre oversubscription, pas de celle d’un voisin.waélevé avecstproche de zéro : les tâches sont bloquées sur le stockage. Il s’agit d’un autre problème, qui nécessite une autre correction.- Load average élevé alors que
stetussont tous les deux faibles : la charge inclut également les tâches non interruptibles. Cela indique généralement un périphérique bloqué ou un montage réseau qui ne répond plus, plutôt qu’un problème de CPU.
Les offres burstable méritent une remarque spécifique. Elles vous accordent un solde de crédits qui augmente lorsque la charge est faible et diminue lorsque vous êtes actif. Lorsqu’il est épuisé, le fournisseur vous limite à un débit de base. Sur certaines plateformes, cette limitation est indiquée comme du steal. Sur d’autres, elle est invisible depuis la machine, qui reçoit simplement moins de cycles par seconde. Lisez la description de l’offre avant d’accuser un voisin.
Pourquoi un conteneur n’indique aucun temps volé
Le temps volé est une propriété de la machine virtuelle, pas d’un conteneur qui s’exécute à l’intérieur. Un conteneur Docker sur votre propre VPS partage le /proc de l’hôte. La valeur st lue à l’intérieur correspond donc au temps volé du VPS, ce qui est le résultat recherché. La virtualisation basée sur des conteneurs et vendue comme un VPS fonctionne différemment. Avec lxcfs en place, /proc/stat à l’intérieur du conteneur est calculé à partir des statistiques des cgroups, et le temps volé vaut zéro par construction. Une stack de monitoring qui collecte les métriques uniquement depuis l’intérieur peut afficher un zéro parfaitement stable alors que la machine physique sous-jacente manque de ressources.
Dans un conteneur, le compteur qui a la même signification est la limitation du CPU par quota. Avec cgroup v2 :
cat /sys/fs/cgroup/cpu.statnr_throttled compte les périodes d’application pendant lesquelles le groupe a atteint son quota CPU, et throttled_usec totalise le temps pendant lequel il a été suspendu. Une valeur nr_throttled en hausse signifie que votre processus était exécutable mais ne s’exécutait pas. L’expérience est la même qu’avec du temps volé, mais la cause est une limite que vous avez définie vous-même. Vérifiez vos propres limites avant d’accuser l’hôte, en particulier si vous exécutez vos services dans Docker sur un VPS avec des limites CPU dans le fichier compose. La virtualisation imbriquée ajoute un autre endroit où du temps peut disparaître, car une VM exécutée dans votre VPS subit le temps volé du VPS ainsi que son propre délai d’ordonnancement. Gardez ce point à l’esprit si vous utilisez la virtualisation imbriquée sur un VPS.
Que faire en cas de steal prolongé
Aucun réglage dans le guest ne corrige le steal, car le scheduler qui prend cette décision s’exécute en dehors du guest. Mettre à niveau le kernel ne change rien non plus : le scheduling tenant compte du cache ajouté dans Linux kernel 7.2 réorganise vos tâches entre les cœurs qui vous ont réellement été attribués, mais ne peut pas récupérer les cycles déjà pris par un voisin. Quatre actions sont réellement possibles.
Commencez par collecter des éléments probants. Notez les horodatages en UTC, la durée de chaque épisode, sa fréquence et si mpstat indique qu’un seul vCPU est affecté ou qu’ils le sont tous. Une semaine d’échantillons journalisés vaut mieux qu’une capture d’écran.
Ouvrez un ticket avec ces données. Posez deux questions directes : ce nœud est-il surchargé pendant ces plages horaires et mon instance peut-elle être déplacée ? Joignez la sortie de vmstat et les heures exactes. Les fournisseurs interviennent lorsqu’une plage horaire est reproductible. Un ticket indiquant seulement que le serveur est lent reçoit une réponse demandant ces informations. La quantité de travail que vous pouvez déléguer est l’une des différences pratiques entre un VPS managé et un VPS non managé.
Demandez une migration. Déplacer un guest vers un nœud moins chargé est une opération courante pour un fournisseur et nécessite généralement un court redémarrage. Cette solution ne coûte rien. Elle résout le cas fréquent où un nœud héberge simultanément plusieurs voisins très sollicités.
Éliminez la contention en changeant d’offre. Une offre avec vCPU dédié réserve une capacité CPU à votre instance : un cœur complet ou un thread matériel complet selon le fournisseur. Les voisins ne prennent alors plus vos cycles et le compteur reste à zéro ou presque. Les tâches internes de l’hyperviseur peuvent néanmoins laisser une faible valeur résiduelle. Cette solution coûte plus cher chaque mois. C’est la réponse adaptée à une charge de travail qui ne peut pas absorber cette variabilité. Si cela ne suffit toujours pas, ou si vous voulez également disposer de toute la bande passante mémoire, l’étape suivante est un serveur dédié plutôt qu’un VPS.
En attendant, réduisez l’impact du steal. Exécutez moins de threads de travail que vous n’avez de vCPU, car les threads qui ne peuvent pas obtenir de cœur ne font qu’ajouter des changements de contexte. Déplacez les traitements batch vers les heures où le nœud est peu chargé, comme votre journal vous l’indique désormais. Mesurez ensuite à nouveau avec la même commande pendant les mêmes heures. Vous pourrez ainsi vérifier si la modification a fonctionné au lieu de vous baser sur des suppositions.
FAQ
Quelle est la valeur normale du temps de vol CPU sur un VPS ?
Sur une offre mutualisée, de brèves pointes et une valeur durable inférieure à environ 5 % sont normales, car le CPU partagé signifie que l’hôte répartit les cœurs physiques entre les machines invitées. Une valeur à deux chiffres maintenue pendant plusieurs heures n’est pas normale et justifie l’ouverture d’un ticket. Sur une offre avec vCPU dédié, la valeur attendue est égale ou très proche de 0.0, car les tâches de maintenance de l’hyperviseur peuvent tout de même utiliser une petite partie du CPU. Une valeur de vol durablement supérieure à ce seuil doit être signalée. Évaluez cette valeur en fonction de votre propre charge : un traitement par lots exécuté pendant la nuit supporte un temps de vol qu’une API sensible à la latence ne peut pas tolérer.
Une offre plus grande corrigera-t-elle un temps de vol élevé ?
Pas à elle seule. Ajouter des vCPU sur le même nœud partagé signifie que davantage de CPU virtuels se disputent les mêmes cœurs physiques saturés, et le pourcentage peut rester exactement identique. Pour supprimer presque tout le temps de vol, il faut une allocation de CPU dédié ou migrer vers un nœud moins chargé. Une part plus importante d’une machine très sollicitée reste une part d’une machine très sollicitée.
Pourquoi mon VPS affiche-t-il 0 en temps de vol alors qu’il est manifestement lent ?
Deux raisons sont fréquentes. L’hyperviseur peut ne pas exporter ce compteur du tout. Cela se produit sur certaines plateformes, selon l’hôte et le kernel invité. Le champ reste alors à zéro, quelle que soit la charge de l’hôte. Exécutez systemd-detect-virt pour identifier la plateforme utilisée. Sinon, le goulet d’étranglement se trouve ailleurs : vérifiez wa pour les attentes liées au stockage, comparez r et nproc pour détecter une surcharge de votre côté, puis consultez /sys/fs/cgroup/cpu.stat dans les conteneurs pour repérer une limitation de quota.
Puis-je réduire le temps de vol depuis mon serveur ?
Vous ne pouvez pas modifier la planification de l’hôte depuis la machine invitée. Vous pouvez seulement réduire ses effets. Exécutez moins de threads worker que votre nombre de vCPU, afin de limiter le travail en attente dans la run queue d’un cœur qui ne se libère pas. Déplacez les traitements par lots aux heures où le nœud est moins chargé. Mettez les résultats en cache pour réduire le nombre de requêtes nécessitant du CPU. Les changements qui suppriment réellement le temps de vol, comme une migration vers un autre nœud ou vers des cœurs dédiés, relèvent du fournisseur.