Tom Daluzeau
← Parcours Linux · ressources
Linux · ressources · leçon 3 / 6Ch. 2 · Ressources11 minTerminée

Entrées/sorties, limites et cgroups

Tu sais trouver le disque saturé et le processus qui le sature, choisir le bon outil pour chaque question, lire et régler les limites d'un utilisateur ou d'un processus, et plafonner la mémoire ou le CPU d'un service avec systemd.

Mis à jour le

À recouper avec le cours. Cette leçon a été écrite à partir du plan du chapitre, avant relecture avec les supports. En cas de doute, le cours fait foi.

Pourquoi on voit ça

Tu sais lire le processeur et la mémoire. Il reste deux causes de lenteur ou de panne : le disque qui ne suit pas, et une limite atteinte (trop de fichiers ouverts, trop de processus). Cette leçon ferme le chapitre avec les outils pour les voir, un tableau « quelle question, quel outil », puis la façon moderne de poser des limites : par service, avec systemd et les cgroups.

Les entrées/sorties

Une entrée/sortie (E/S, I/O), c’est une lecture ou une écriture sur un disque. Premier signal : le champ wa de top. S’il est élevé, le processeur attend le disque. Il reste à savoir quel disque et quel processus.

Quel disque : iostat

iostat fait partie du paquet sysstat.

iostat -x 2

-x donne les statistiques détaillées, 2 rafraîchit toutes les 2 secondes. Le premier bloc affiché est une moyenne depuis le démarrage : regarde les suivants. Extrait (la vraie sortie a plus de colonnes) :

Device    r/s     w/s    rkB/s     wkB/s  w_await  %util
sda       1.0    12.0     40.0     310.0     1.10    2.40
sdb       8.0   320.0    130.0   97400.0   185.30   99.70
Colonne Ce qu’elle dit
r/s, w/s lectures et écritures par seconde
rkB/s, wkB/s kilooctets lus et écrits par seconde
r_await, w_await temps d’attente moyen d’une lecture, d’une écriture, en millisecondes
%util part du temps où le disque est occupé

Un %util proche de 100 avec un temps d’attente qui grimpe : le disque est saturé. Ici, c’est sdb.

Quel processus : iotop

iotop -o

iotop est un top trié par E/S. Il se lance en root. -o (only) n’affiche que les processus qui lisent ou écrivent en ce moment.

  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
 2210 be/4 postgres    0.00 B/s   95.10 M/s  0.00 %  87.20 % postgres: checkpointer

Les colonnes DISK READ et DISK WRITE donnent le débit de chaque processus. Le coupable est en haut.

Quelle question, quel outil

Ta question Outil Ce que tu y lis
Qui consomme le CPU ? Le processeur attend-il le disque ? top, htop ligne %Cpu(s), liste des processus
Que se passe-t-il seconde après seconde ? vmstat 1 une ligne par seconde : processus, mémoire, swap, E/S, CPU
Reste-t-il de la mémoire ? free -h colonne available, ligne Swap
Quel disque est saturé ? iostat -x 2 %util, temps d’attente
Quel processus écrit sur le disque ? iotop -o DISK READ, DISK WRITE

htop est un top plus lisible, avec une barre par cœur. Dans vmstat, trois repères suffisent : si et so (ce qui entre et sort du swap : autre chose que 0 en continu, la machine swappe), et wa, le même que dans top.

L'application est lente top : ligne %Cpu(s) us, sy élevés wa élevé tout est calme le processeur le disque la mémoire top, htop quel processus calcule iostat -x 2 quel disque est saturé free -h available, ligne Swap iotop -o quel processus écrit vmstat 1 si, so : swappe-t-il ? « Too many open files » ulimit -n
On part toujours de la ligne CPU de top. En pointillés : l'erreur des journaux qui signale une limite plutôt qu'une ressource.

Les limites système

Le noyau plafonne ce que chaque processus peut consommer, pour qu’un seul programme ne puisse pas épuiser la machine. Deux limites sont à connaître :

Commande Limite
ulimit -n nombre de descripteurs de fichiers ouverts par processus
ulimit -u nombre de processus de l’utilisateur

Un descripteur de fichier est le numéro que le noyau donne à chaque fichier ouvert. Une connexion réseau en consomme un aussi. La valeur habituelle est 1024, vite atteinte par un serveur web ou une base de données. L’erreur est alors toujours la même :

Too many open files

Chaque limite a deux valeurs. La limite soft est celle qui s’applique. La limite hard est le plafond jusqu’où l’utilisateur peut relever sa limite soft. Seul root peut monter la hard.

soft 1024 : celle qui s'applique hard 4096 : le plafond la marge que l'utilisateur peut s'accorder ouverts au-delà : Too many open files ulimit -n 4096 : l'utilisateur relève sa soft seul root
La soft bloque, la hard borne la soft. Un utilisateur se déplace entre les deux, pas au-delà.
ulimit -n          # limite soft actuelle
ulimit -Hn         # limite hard
ulimit -n 4096     # change la limite, pour cette session seulement

Rendre une limite durable : /etc/security/limits.conf

deploy   soft   nofile   8192
deploy   hard   nofile   16384
@devs    hard   nproc    200

Quatre colonnes : qui (un utilisateur, ou un groupe avec @), soft ou hard, quoi (nofile pour les fichiers ouverts, nproc pour les processus), la valeur. Le fichier est lu à l’ouverture de session : il faut se reconnecter. Et il ne concerne pas les services lancés par systemd.

Les ressources d’un processus dans /proc/<PID>/

Tu connais /proc/<PID>/. Trois entrées répondent à « que consomme ce processus, et jusqu’où a-t-il le droit d’aller ? ».

Entrée Contenu
status l’état du processus et sa mémoire : VmRSS (RAM réellement occupée), VmSwap, Threads
limits ses limites, avec les colonnes soft et hard
fd/ un lien par descripteur ouvert
grep "open files" /proc/2210/limits
ls /proc/2210/fd | wc -l
Max open files            1024                 4096                 files
1017

1017 descripteurs ouverts pour une limite soft de 1024 : ce processus est au bord du « Too many open files ».

Les limites posées par systemd

Un service ne passe pas par une session : ses limites s’écrivent dans son unité, section [Service]. Le plus propre est un drop-in, avec systemctl edit api :

[Service]
MemoryMax=500M
CPUQuota=50%
TasksMax=100
LimitNOFILE=65536
Directive Effet
MemoryMax= plafond de mémoire. S’il est dépassé, l’OOM killer tue un processus du service
CPUQuota= part de CPU maximale. 50% = la moitié d’un cœur, 200% = deux cœurs
TasksMax= nombre maximal de processus et de threads du service
LimitNOFILE= l’équivalent de ulimit -n pour le service

Puis systemctl restart api. systemctl status api affiche alors la consommation et ses plafonds (lignes Tasks: et Memory:).

L’idée des cgroups

Un cgroup (control group) est une boîte du noyau dans laquelle on range des processus pour mesurer et limiter ce qu’ils consomment ensemble. systemd crée un cgroup par service : MemoryMax=, CPUQuota= et TasksMax= sont des réglages de cette boîte. Différence avec ulimit : une limite ulimit vaut pour chaque processus, une limite de cgroup vaut pour tout le groupe.

api.service nginx.service backup.service api api worker api worker nginx master nginx worker nginx worker backup.sh tar gzip mémoire du groupe mémoire du groupe CPU du groupe MemoryMax=500M aucune limite CPUQuota=50%
Un enclos par service. La limite porte sur tout l'enclos : si api dépasse 500 Mo à lui tout seul, l'OOM killer frappe dans son enclos, pas chez les voisins.
systemd-cgtop

C’est un top par cgroup : une ligne par service, avec ses tâches, son CPU, sa mémoire et ses E/S.

Contexte, pas à apprendre. Les cgroups sont visibles dans /sys/fs/cgroup/. La limite de mémoire du service api se lit dans /sys/fs/cgroup/system.slice/api.service/memory.max. Les conteneurs Docker reposent sur le même mécanisme.

À retenir

  • wa élevé dans top : le disque. iostat -x dit quel disque (%util proche de 100, temps d’attente élevé), iotop dit quel processus.
  • Une question, un outil : top/htop pour le CPU, vmstat 1 pour suivre dans le temps, free -h pour la mémoire, iostat pour les disques, iotop pour les E/S par processus.
  • ulimit -n : descripteurs de fichiers ouverts. ulimit -u : processus. « Too many open files » = limite -n atteinte.
  • Limites durables d’un utilisateur : /etc/security/limits.conf (soft, hard, nofile, nproc), lu à l’ouverture de session.
  • /proc/<PID>/status (mémoire), /proc/<PID>/limits (limites), /proc/<PID>/fd/ (descripteurs ouverts).
  • Pour un service : MemoryMax=, CPUQuota=, TasksMax=, LimitNOFILE= dans [Service]. Les trois premières règlent le cgroup du service ; systemd-cgtop montre la consommation par cgroup.

Entraînement

12 questions, dont 4 à compléter. Tu réponds, on passe à la suivante. La note arrive à la fin.

Cartes · 8

Réviser les cartes ici

Espace : retourner