SSD Nodes Learn 🎉 VPS dès $4.99/mois
Guides Matt ConnorPar Matt Connor

CPU steal time : repérer un voisin bruyant sur un VPS

Le temps CPU steal révèle un vCPU prêt mais privé de CPU physique. Apprenez à lire la colonne st de vmstat et à distinguer voisin bruyant et surcharge locale.

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 à un autre guest. Le travail était en attente dans la file. Le cœur exécutait une autre charge. Linux compte ces cycles séparément et les indique comme st. Vous pouvez ainsi distinguer « mon serveur est très sollicité » de « mon serveur attend son tour ».

C’est la raison d’être de ce compteur. Le temps que vos propres processus passent sur le CPU est indiqué comme us (user) ou sy (system). Le temps pendant lequel une tâche reste bloquée sur le stockage est indiqué comme wa (I/O wait). Un vCPU (CPU virtuel) prêt à s’exécuter, présent dans la run queue, sans opération d’E/S en attente et qui ne s’exécute toujours pas, est indiqué comme st. Rien dans votre serveur ne peut mettre fin à cet état, car la décision d’ordonnancement est prise à un niveau inférieur, sur l’hôte.

Cela découle directement de la manière dont un VPS partage une même machine physique entre plusieurs guests. La cause habituelle est un voisin : un autre guest sur le même nœud utilise fortement les ressources, et l’hôte répartit les cœurs entre les différents guests. Une autre cause est souvent ignorée. De nombreux fournisseurs limitent un vCPU partagé à une fraction d’un cœur physique. Sur plusieurs hyperviseurs, cette limite appliquée est comptabilisée comme du steal dans le guest. Ainsi, une valeur st élevée indique que le cœur ne vous a pas été attribué. Elle n’indique pas toujours qui l’utilisait.

D’où vient la valeur de steal

Votre kernel ne peut pas mesurer le steal seul, car il ne voit pas l’hôte. C’est l’hyperviseur qui la lui transmet. Avec KVM, l’hôte écrit un compteur par vCPU dans une page partagée avec le guest, puis le guest additionne ses valeurs lorsque le kernel est compilé avec CONFIG_PARAVIRT_TIME_ACCOUNTING, ce qui est le cas de tous les kernels des distributions. Xen fournit la même information via sa zone runstate. Le total atteint l’espace utilisateur à un seul endroit :

head -1 /proc/stat

La 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. Steal est 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 calculent un pourcentage à partir de deux échantillons.

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 signalent un 0.0 normal alors que l’hôte est saturé. KVM et Xen exportent ce compteur. Les guests sur VMware et Hyper-V signalent généralement une valeur toujours égale à zéro. Vérifiez la plateforme avant de faire confiance à une valeur nulle :

systemd-detect-virt

Cette commande affiche le nom de la plateforme, par exemple kvm, xen, vmware ou microsoft, et none sur une machine bare metal. Dans un conteneur, elle indique plutôt le runtime, par exemple lxc, docker ou podman, ce qui renseigne sur le conteneur et non sur la machine sous-jacente. Sur kvm, une valeur nulle prouve réellement que l’hôte vous fournit suffisamment de ressources. Sur une plateforme qui ne renseigne jamais ce champ, une valeur nulle ne prouve rien, et il faut évaluer la contention en mesurant la durée d’exécution d’un travail réel.

Comment vérifier le steal time du 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 5

vmstat --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 les vrais compteurs du kernel. vmstat 1 5 prélève ensuite un échantillon par seconde, cinq fois.

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  0

Repérez la colonne st dans le bloc cpu situé à droite. Les versions actuelles de procps-ng affichent une colonne gu après celle-ci pour le temps passé dans un invité KVM. st est donc l’avant-dernière colonne et non la dernière. Lisez la colonne à partir de son en-tête, car cette position a changé entre les versions.

Deux habitudes permettent de conserver 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 steal time survient par rafales. Exécutez vmstat 1 60 et surveillez une minute complète avant de tirer une conclusion.

top affiche 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 st

Pour obtenir le détail par cœur, ajoutez sysstat :

sudo apt-get install -y sysstat
mpstat -P ALL 1 5

mpstat 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.log

Exécutez cette commande depuis cron pendant les heures où vous suspectez le problème. Le fichier permettra de remplacer « c’était lent hier soir » par les dix minutes exactes concernées.

Que signifient les valeurs de steal ?

  • Un 0.0 stable. L’état est normal, ou la plateforme ne signale pas du tout de steal. Vérifiez avec systemd-detect-virt avant de conclure.
  • Des pointes de quelques pour cent pendant quelques secondes. C’est normal sur tout nœud partagé. Le build d’un voisin démarre ou l’hôte exécute ses sauvegardes.
  • De 1 à 5 pour cent de façon continue sur une offre partagée. C’est attendu. Le prix reflète l’utilisation d’un CPU partagé.
  • De 5 à 10 pour cent de façon continue. Le ralentissement est mesurable. Commencez à recueillir des éléments et comparez les mêmes horaires sur plusieurs jours.
  • Plus de 10 pour cent pendant plusieurs heures. Le nœud est surabonné pour votre charge de travail. C’est le niveau qui justifie l’ouverture d’un ticket auprès du support ou une migration.

Considérez ces fourchettes comme un guide de lecture, et non comme une spécification, car aucun fournisseur ne garantit un niveau de steal sur une offre partagée. Mettez-les en perspective avec vos charges de travail. Un traitement batch nocturne peut absorber 15 pour cent 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 inquiétante. C’est pourquoi les charges sensibles à la latence, comme les bots de trading doivent utiliser des cœurs dédiés.

Quel coût le steal time représente-t-il pour vous ?

Le calcul est simple. Si une fraction s de votre temps CPU est prise par le steal, une tâche qui nécessite une quantité fixe de CPU prend 1 / (1 - s) fois plus de temps réel. Pour une tâche nécessitant 60 secondes de CPU :

ChartWall clock time for a job needing 60 seconds of CPU
The data behind this chart
[
  {
    "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 situation ordinaire 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 jusque-là commence à s’allonger.

Ces valeurs sont calculées, pas mesurées. Le modèle suppose un seul thread exécutable 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 volée peut interrompre une requête et le délai est alors subi à nouveau par tout ce qui attend cette requête. Pour obtenir votre propre valeur plutôt qu’une formule, mesurez les performances de votre VPS pendant une période calme, puis de nouveau pendant une période chargée, en enregistrant st pour les deux périodes.

Vient-il d’un voisin, ou d’autre chose ?

Le steal se confond facilement avec d’autres symptômes. Lisez les compteurs ensemble, sur la même ligne vmstat.

  • st élevé, tandis que r et us restent faibles : l’hôte ne vous attribue pas le core. C’est du steal.
  • r nettement supérieur à votre nombre de vCPU, avec us élevé et st proche de zéro : vous exécutez plus de tâches que vos propres CPU ne peuvent en traiter. Comparez r avec la sortie de nproc. Il s’agit de votre propre oversubscription, pas de celle d’un voisin.
  • wa élevé, avec st proche de zéro : les tâches sont bloquées sur le stockage. C’est un autre problème, qui nécessite une autre correction.
  • Load average élevé, tandis que st et us sont tous deux faibles : la charge compte également les tâches uninterruptible. Cela indique généralement un périphérique bloqué ou un montage réseau suspendu, plutôt qu’un problème de CPU.

Les offres burstable nécessitent une précision particulière. Elles vous attribuent un solde de crédits qui augmente lorsque la machine est inactive et diminue lorsqu’elle est sollicitée. Lorsque ce solde est épuisé, le provider vous limite à un débit de base. Sur certaines plateformes, cette limitation apparaît comme du steal. Sur d’autres, elle est invisible depuis l’intérieur de la machine, qui reçoit simplement moins de cycles par seconde. Consultez la description de l’offre avant d’accuser un voisin.

Pourquoi un conteneur n’indique aucun temps de vol

Le temps de 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 de vol du VPS, ce qui est le résultat attendu. La virtualisation par conteneurs vendue comme un VPS se comporte autrement. Avec lxcfs en place, /proc/stat dans le conteneur est calculé à partir des statistiques cgroup, et le temps de vol est nul par construction. Une stack de supervision qui collecte uniquement les données depuis l’intérieur peut afficher une valeur nulle, stable et rassurante, alors que la machine physique sous-jacente manque de ressources.

Dans un conteneur, le compteur qui a la même signification est la limitation CPU par quota. Avec cgroup v2 :

cat /sys/fs/cgroup/cpu.stat

nr_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 le temps de 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 : une VM à l’intérieur de votre VPS subit le temps de vol du VPS, en plus de son propre délai d’ordonnancement. Tenez-en compte si vous utilisez la virtualisation imbriquée sur un VPS.

Que faire en cas de steal persistant

Aucun réglage dans le guest ne corrige le steal, car le scheduler qui prend la décision s’exécute en dehors du guest. Quatre actions sont réellement possibles.

Commencez par recueillir des éléments. Notez les horodatages en UTC, la durée de chaque épisode, sa fréquence et indiquez si mpstat montre qu’un seul vCPU est affecté ou s’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 node est-il en surallocation pendant ces créneaux, et mon instance peut-elle être déplacée ? Collez la sortie de vmstat et les horaires exacts. Les fournisseurs interviennent sur la base d’un créneau reproductible. Un ticket indiquant seulement que le serveur est lent reçoit généralement une réponse demandant ces informations. La quantité de travail que vous pouvez leur confier 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 node moins chargé est une opération courante pour un fournisseur. Il s’agit généralement d’un bref redémarrage. Cette correction ne coûte rien. Elle résout le cas le plus fréquent : un node héberge temporairement plusieurs voisins fortement consommateurs de ressources.

Éliminez la contention en changeant d’offre. Une offre avec vCPU dédié réserve des cœurs physiques pour votre instance. Le compteur reste alors à zéro. Cette solution coûte plus cher chaque mois. C’est le choix approprié pour une charge 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 worker 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 aux heures où le node est peu chargé, comme vos propres journaux vous l’indiquent maintenant. Mesurez ensuite avec la même commande pendant les mêmes heures. Vous pourrez ainsi déterminer si la modification a fonctionné au lieu de supposer que c’est le cas.

FAQ

Quel est le niveau normal de steal time sur un VPS ?

Sur une offre mutualisée, de brèves pointes et une valeur durablement inférieure à environ 5 pour cent sont normales, car le CPU partagé signifie que l’hôte répartit les cœurs physiques entre les guests. 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 0.0. Toute autre valeur doit donc être signalée. Évaluez cette valeur en fonction de votre propre charge : un traitement batch nocturne peut absorber du steal time, contrairement à une API sensible à la latence.

Une offre plus grande corrigera-t-elle un steal time élevé ?

Pas à elle seule. Ajouter des vCPU sur le même nœud partagé signifie ajouter des CPU virtuels qui se disputent les mêmes cœurs physiques très sollicités, et le pourcentage peut rester exactement identique. Pour supprimer le steal time, il faut une allocation de CPU dédiée ou migrer vers un nœud moins chargé. Une part plus importante d’une machine très sollicitée reste une part de cette machine très sollicitée.

Pourquoi mon VPS affiche-t-il 0 en steal time alors qu’il est manifestement lent ?

Deux raisons sont fréquentes. L’hyperviseur peut ne pas exporter ce compteur, ce qui est habituel sur les plateformes VMware et Hyper-V. Le champ reste alors à zéro, quelle que soit l’activité de l’hôte. Exécutez systemd-detect-virt pour identifier la plateforme utilisée. Sinon, le goulot d’étranglement se trouve ailleurs : vérifiez wa pour les attentes liées au stockage, comparez r à nproc pour détecter une surcharge de votre côté, et consultez /sys/fs/cgroup/cpu.stat dans les conteneurs pour repérer une limitation due aux quotas.

Puis-je réduire le steal time depuis mon serveur ?

Vous ne pouvez pas modifier la planification de l’hôte depuis le guest. Vous pouvez seulement limiter son impact. Exécutez moins de threads worker que vous n’avez de vCPU, afin que moins de tâches restent dans la run queue en attendant un cœur qui ne se libère pas. Déplacez les traitements batch vers les 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 steal time, comme une migration vers un autre nœud ou vers des cœurs dédiés, relèvent du fournisseur.