Journal Les cgroups, un outil trop méconnu

Posté par (page perso) . Licence CC by-sa
76
27
sept.
2015

Dans les temps anciens, où Linux était facile, on apprenait à gérer la priorité des processus avec la commande "nice". C'était facile, simple, mais limité : même avec "nice -19 stress -c 1", les autres programmes n'obtenaient pas plus de 90% du temps processeur.

Depuis quelques années, nice ne répond plus. Si si, essayez dans votre distribution favorite : lancez la commande ci-dessus, puis simultanément la même sans nice : "stress -c 1". Vous verrez avec "top" qu'elles ont chacune 50% de processeur sur une machine mono-cœur. Bizarre, on m'a répondu que les cgroups sont l'avenir, yapuka.

Sur le moment, on n'a jamais le temps, on repousse, mais là j'ai craqué : mon film en 720p saccade par moments, il demande parfois 80% du temps processeur, et ktorrent en prend jusqu'à 30%.

## créer un groupe nommé plustard pour l'utilisateur live
sudo cgcreate -a live:live -t live:live -g cpu:/plustard

# Lui affecter la priorité processeur la plus basse (c'est 1024 par défaut)
cgset -r cpu.shares=2 plustard

# Affecter ktorrent à ce groupe
cgclassify -g cpu:plustard $(pgrep ktorrent)

Voilà, après une heure de recherches c'est aussi simple que de mettre ça en démarrage automatique de KDE. Remplacez live par votre utilisateur et groupe. C'est beaucoup plus puissant puisque j'obtiens 99,4% de temps processeur dans le même test qu'au début. Il faut remplacer nice par "cgexec -g cpu:plustard stress -c 1"

  • # cpuset

    Posté par . Évalué à 9.

    Pour ceux qui rencontreraient un problème "subsystems not mounted" avec la ligne de commande cgcreate, il faut remplacer cpu par cpuset.

    The capacity of the human mind for swallowing nonsense and spewing it forth in violent and repressive action has never yet been plumbed. -- Robert A. Heinlein

  • # niceness

    Posté par . Évalué à 5.

    même avec "nice -19 stress -c 1", les autres programmes n'obtenaient pas plus de 90% du temps processeur.

    Pour info, le niceness, plus c'est bas plus ça favorise le processus, donc ça me parait normal.

    • [^] # Re: niceness

      Posté par . Évalué à 10.

      Dans « nice -19 », le - est juste le tiret de l’option, ça équivaut à « nice -n 19 », la priorité la plus basse. Pour la priorité la plus haute, c’est « nice --20 ».

      Théorie du pot-au-feu : « Tout milieu où existe une notion de hauteur (notamment les milieux économique, politique, professionnels) se comporte comme un pot-au-feu : les mauvaises graisses remontent. »

      • [^] # Re: niceness

        Posté par . Évalué à 3.

        Euh..; C'est une gnuserie alors.

        D'après le man :

        COMPATIBILITY
        The traditional -increment option has been deprecated but is still sup‐
        ported.

        • [^] # Re: niceness

          Posté par . Évalué à 4.

          C'est nice qui est déprécié :)

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

          • [^] # Re: niceness

            Posté par . Évalué à 3.

            It's nice to be important, but it's more important do be nice.

      • [^] # Re: niceness

        Posté par . Évalué à 3.

        En effet, j'avais pas vu l'absence du -n.
        C'est bien piégeux en tout cas comme comportement !

        • [^] # Pièges du shell

          Posté par . Évalué à 5.

          S’il n’y avait que ça qui soit piégeux en shell…

          Par exemple, tu peux utiliser cut pour récupérer un champ ; tu peux aussi utiliser sort pour trier selon un champ.
          Avec cut, -f indique le champ (« field » en anglais), -d le délimiteur.
          Tu te dirais qu’avec sort, ce serait pareil.
          Eh bien non ! Avec sort, -k indique le champ selon lequel on trie — la clé (« key ») de tri, c’est incohérent, mais ça a un sens — et -t indique le délimiteur — et là, le sens, on le cherche…

          Et il y a d’autres sources d’« amusement » :

          $ [ -z $bidon ] && echo oui
          oui
          $ [ $bidon = "" ] && echo oui
          bash: [: = : opérateur unaire attendu

          Il fallait écrire [ "$bidon" = "" ], parce que le shell commence par faire une expansion de variables et ensuite analyse la chaîne de caractères résultante, et à ce stade, ce qu’il voit, c’est [ = "" ] ; curieusement, -z est robuste à ce problème.

          Théorie du pot-au-feu : « Tout milieu où existe une notion de hauteur (notamment les milieux économique, politique, professionnels) se comporte comme un pot-au-feu : les mauvaises graisses remontent. »

          • [^] # Re: Pièges du shell

            Posté par . Évalué à 3. Dernière modification le 04/10/15 à 13:45.

            Tu te dirais qu’avec sort, ce serait pareil. Eh bien non !

            cut et sort c’est pas le shell. C’est des programmes indépendants utilisables depuis le shell.

            Ta critique c’est comme si tu disais que les interfaces graphiques (Xorg/Wayland/les équivalents proprios) c'est nul parce que dans certains programmes le réglage des options se fait dans le menu « Outils » tandis que dans d’autres il se fait dans « Fichier ». Ou que Python c’est nul parce que dans la lib A on appelle les fonctions comme_ca tandis que dans la lib B on appelle les fonctions commeCa.

            • [^] # Re: Pièges du shell

              Posté par . Évalué à 4. Dernière modification le 05/10/15 à 14:12.

              cut et sort c’est pas le shell. C’est des programmes indépendants utilisables depuis le shell.

              Je sais, mais ce sont des commandes qui ont été développées à la même époque, probablement par des personnes qui se connaissaient (il n’y avait pas tant de monde que ça, à l’époque héroïque des débuts d’Unix) pour faire partie de l’environnement de base de la ligne de commande. Et si tu enlèves toutes les commandes classiques qui sont des « programmes indépendants » (ça veut dire aussi cp, rm…), le shell tout nu ne sert plus à rien.

              Toi, je ne sais pas, mais mois, si on me demande de faire un truc en shell et qu’on vient me dire, « non, tu as utilisé sort, c’est pas du shell », ça va mal se passer…

              Théorie du pot-au-feu : « Tout milieu où existe une notion de hauteur (notamment les milieux économique, politique, professionnels) se comporte comme un pot-au-feu : les mauvaises graisses remontent. »

  • # Et pour éviter de swapper

    Posté par (page perso) . Évalué à 10.

    Effectivement c'est un outil méconnu et qui fonctionne aussi pour autre choses que le CPU. Par exemple j'ai chez moi un cgroup 'limited' qui me permet de lancer un processus dans un environnement réellement limité (ne me parlez plus de ulimit !).

    dans '/etc/cgconfig.conf' ajoutez simplement :

    group limited {
      perm {
        admin {
          uid = votre_nom_utilisateur;
        }
        task {
          uid = votre_nom_utilisateur;
        }
      }
      cpu {
        cpu.shares = 50;
      }
      memory {
    # 2GiB limit
        memory.limit_in_bytes = 2147483648;
      }
    }
    

    Puis pour lancer un processus dans cet environnement, utilisez simplement : cgexec -g 'cpu,memory:limited' ls

    • [^] # Re: Et pour éviter de swapper

      Posté par . Évalué à 7.

      On trouve la liste des autres « axes de contraintes » par la commande cat /proc/self/cgroup.

      À noter que systemd fournit des utilitaires pour les cgroups : systemd-cgls et systemd-gctop.

      The capacity of the human mind for swallowing nonsense and spewing it forth in violent and repressive action has never yet been plumbed. -- Robert A. Heinlein

  • # et systemd ?

    Posté par . Évalué à 4.

    C'est pas pour troller, mais j'avais entendu dire que, dorénavant, c'est systemd qui allait gérer l'ensemble des cgroups. Donc est-ce que ces manipulations ne risque pas de perturber notre PID 1 préféré ?

    • [^] # Re: et systemd ?

      Posté par (page perso) . Évalué à 8.

      dorénavant, c'est systemd qui allait gérer l'ensemble des cgroups.

      Plus précisément, le gros changement à venir dans l’interface des cgroups est qu’un seul processus sera autorisé à manipuler directement les cgroups. Sur les systèmes où systemd est disponible, c’est lui qui s’en chargera.

      Donc est-ce que ces manipulations ne risque pas de perturber notre PID 1 préféré ?

      Pour l’instant, non. Et le jour où systemd prendra le contrôle de la hiérarchie des cgroups, les manipulations du genre de celles décrites ici seront toujours possible, seulement de manière différente : on ne manipulera plus des cgroups avec des commandes cg*, mais des slices avec une API propre à systemd.

    • [^] # Re: et systemd ?

      Posté par . Évalué à 1. Dernière modification le 28/09/15 à 15:27.

      Question pertinente, systemd offre-t-il tous les contrôles possibles sur les cgroups ?
      Thétis donne une indication dans son commentaire, ou bien l'usage que systemd en fait n'est pas complet ?

      De ce que j'avais lu à l'époque (et compris), systemd avait recours aux cgroups pour sa gestion des processus (d'où l'impossibilité de port sur FreeBSD qui n'a pas cette notion).

      P.S: tout comme pour rewind, nulle volonté trollesque dans ce message.

      Edit : réponse juste au-dessus, merci gouttegd.

      Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

    • [^] # Re: et systemd ?

      Posté par . Évalué à 7.

      Pour compléter le message de gouttegd,

      Globalement le contrôle des cgroups se fait via des pseudo-systèmes de fichiers dans /sys. Voilà ce que monte systemd dans ma machine :

      tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
      cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
      cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
      cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
      cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
      cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
      cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)
      cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
      cgroup on /sys/fs/cgroup/bfqio type cgroup (rw,nosuid,nodev,noexec,relatime,bfqio)

      Pour créer les groupes et poser une limite, on va piocher dans la doc de blkio :

      • Create two cgroups
        mkdir -p /sys/fs/cgroup/blkio/test1/ /sys/fs/cgroup/blkio/test2

      • Set weights of group test1 and test2
        echo 1000 > /sys/fs/cgroup/blkio/test1/blkio.weight
        echo 500 > /sys/fs/cgroup/blkio/test2/blkio.weight

      Ce qui est plutôt barbant si on planifie de créer une arborescence complète, d'où la nécessité d'avoir des outils permettant de faciliter la création des groupes. Que ce soit par des commandes cg* ou des commandes systemd-cg*, cela ne devrait pas changer grand chose.

      The capacity of the human mind for swallowing nonsense and spewing it forth in violent and repressive action has never yet been plumbed. -- Robert A. Heinlein

    • [^] # Re: et systemd ?

      Posté par . Évalué à 10.

      C'est pas pour troller, mais j'avais entendu dire que, dorénavant, c'est systemd qui allait gérer l'ensemble des cgroups. Donc est-ce que ces manipulations ne risque pas de perturber notre PID 1 préféré ?

      Oui et non.
      Si il s'agit d'un processus lancé depuis un terminal ou un pseudo terminal, ça ne change pas grand chose. Il y a des projets de nouvelle interface pour les cgroups qui forcera une interface centralisée. Dans les systèmes utilisant le framework systemd c'est celui-ci qui s'occupera de gérer les cgroups.L'api et les commandes seront différentes, mais dans l'ensemble les fonctionnalités devrait être sensiblement les mêmes.

      Par contre si il s'agit d'un processus détaché (daemon ou autre) géré par l'init, ça devient plus compliqué. Et c'est déjà le cas aujourd'hui, même sans la nouvelle interface.

      Si le processus a été lancé par systemd il a nécessairement été placé dans une slice, c'est à dire une tranche de ressources configurée dans systemd. Par défaut il y a trois grande catégories de slice présente dans systemd
      - la slice system, qui lance tous les services "classiques".
      - la slice user, qui lance tous les services "utilisateurs" - c'est à dire ayant besoin d'avoir accès à logind)
      - la slice machine qui gère les machines virtuelles et les containers (dans une certaine mesure, tout n'est pas supporté et tout ce qui est supporté n'est pas recommandé)

      Il faut bien comprendre trois choses :
      - Un processus ne peut appartenir qu'à un cgroup et un seul
      - Quand un processus change de hiérarchie il devient littéralement invisible aux yeux des processus qui ne sont pas dans une hiérarchie ancêtre.
      - Certains processus (par exemple logind) et certains devices (les cartes réseaux notamment) ne peuvent pas être déplacés, ré-alloués ou même relancés dans un autre cgroup sans heurts. (Et par heurts je veux dire passage de systemd en mode panique totale, avec tentative de relance en boucle de certains services)

      A noter que le troisième point n'est en aucun cas une faute de systemd, simplement le résultat d'un choix qui a été fait dans un soucis de simplification. La nouvelle interface résoudra ce problème via la centralisation des appels.

      De fait certaines opérations sur les cgroups qui sont possibles sans systemd deviennent très complexe avec systemd.

      Par exemple supposons que je veuille mettre à disposition d'un client une machine virtuelle avec une carte réseau dédiée, et en plus une interface web de monitoring sur laquelle il peut se loguer en utilisant ses identifiants utilisateurs local (ou domaine).
      Maintenant supposons que je veuille mettre des restrictions à tout ça en utilisant les cgroups. La transversalité du bignou va m'obliger à créer plusieurs tranches avec systemd et à composer avec les différents éléments.
      Sans systemd je peux parfaitement créer une hiérarchie globale pour le client et mettre les restrictions dessus.
      En plus certaines opérations, comme allouer un coeur CPU ou une carte réseau à un cgroup défini, geler un processus ou encore taguer les paquets en fonction de leur cgroup ne sont pas encore supportées par systemd.

      Pour faire court :
      - Pour l'instant sur tous les processus lancés depuis un tty, ça marche et ça devrait continuer de marcher - mais peut-être avec une API différente, et peut-être avec certains manques sous le framework systemd si les fonctionnalités manquantes aux slides en sont pas implémentées.
      - En ce qui concerne les processus rattachés au PID 1,à aujourd'hui il y a des limitations - elles n'impactent probablement pas grand monde (mais j'en suis et ca me casse les pieds gravement)
      Pour le futur ca dépendra du controlleur de cgroups au final, sous le framework systemd il y aura très probablement des manques dus aux choix architecturaux. Mais on ne sait jamais, il faut attendre les nouvelles interface et leur intégration pour être sur.

  • # Genial

    Posté par . Évalué à 10.

    Si je comprend bien si tu n'es plus admin et si ton admin n'a pas prévu le group tu ne plus décider de l'utilisation des ressources de façon simple.

    Un gros progrès clairement…

    • [^] # Re: Genial

      Posté par . Évalué à 9.

      Et vu la complication de mise en oeuvre il ne faut pas s'étonner que les cgroups soient un "outil méconnu". Bref…

    • [^] # Re: Genial

      Posté par . Évalué à 10.

      Pour ceux qui "moinsse" ce message pouvez vous m'expliquer comment faire si "nice" ne fonctionne pas, que je ne veux pas emmerder les autres utilisateurs car je suis un gentil et si je ne suis pas root pour creer le cgroup?

      Parceque c'est bien gentil de dire que c'est non pertinnent mais j'aimerai bien un vrai solution.

      • [^] # Re: Genial

        Posté par . Évalué à -3.

        T'emmerdes l'admin en lui demandant de créer le cg, ou de te filer les droits sudo pour le faire !

    • [^] # Re: Genial

      Posté par (page perso) . Évalué à 9.

      tu ne plus décider de l'utilisation des ressources de façon simple.

      Voilà.

      J'ai bien remarqué ça sur mon serveur de calcul. J'ai des gros batches qui tournent plusieurs dizaines d'heures, et parfois, j'ai un truc plus urgent à lancer et dont j'attend avec impatience le résultat.

      Avant l'arrivée de l'œuvre du démon, c'était simple : un petit coup de renice pour calmer les trucs moins urgent, et hop…

      Maintenant, bof ;(

      Comment retrouver simplement l'ancien comportement ?

      * Ils vendront Usenet^W les boites noires quand on aura fini de les remplir.

  • # Heu ... nice ça marche encore très bien

    Posté par (page perso) . Évalué à 3.

    Testé chez moi, "nice -19 stress-ng -c 4" et "stress-ng -c 4" => deux groupes de 4 processus distincts dans htop avec 95% de cpu pour celui en nice à 0 (défault) et 2/3% pour les autres

  • # Et pour le HDD ?

    Posté par . Évalué à 2.

    Pour ce qui est des opérations I/O, c'est-à-dire les cp/mv/etc., que ce soit en console ou via XFCE4/Thunar) :

    Plutôt que de lancer la copie puis limiter ensuite via une commande, est-il possible de créer une règle qui fait ça automatiquement, sans avoir à manipuler, selon les cas suivants :

    • entre disques internes à la tour, ne pas intervenir,
    • mais dès qu'il y a un disque USB externe (source ou destination), limiter la bande-passante à disons 25MB/s.

    C'est possible ?

    • [^] # Re: Et pour le HDD ?

      Posté par . Évalué à 1.

      Je pense à une règle udev (qui fait maintenant partie de systemd il me semble).
      J'y regarde right now. Si je trouve, j'vous dis quoi.

    • [^] # Re: Et pour le HDD ?

      Posté par . Évalué à 1.

      dès qu'il y a un disque USB externe (source ou destination), limiter la bande-passante à disons 25MB/s.

      Pourquoi vouloir limiter cette bande passante ?
      Note que sur un disque externe en USB 2, c'est de fait limité dans les 30-35 MB/s.
      Si ton "IO scheduler" est CFQ (Completely Fair Queuing), tu as la commande "ionice" qui permet d'affecter la priorité de transfert, et même de mettre un processus dans la classe "idle" (fais un "man" tu verras).

      • [^] # Re: Et pour le HDD ?

        Posté par . Évalué à 2.

        En fait quand je fais un rsync ou une copie sur un HDD externe (port USB3 et disque USB3), et bien toutes les…. 10s (environ), il y a une purge du buffer et le PC est à genoux (core i7 avec 8 Go de DDR3).
        Merci, je vais vérifier mon IO scheduler et utiliser ionice.

  • # IO

    Posté par . Évalué à 3. Dernière modification le 21/10/15 à 10:09.

    Je commence à m'en servir (enfin !) et j'en suis plutôt content :)

    Par contre je cherche aussi à mettre des contraintes sur les I/O. J'aimerais un io.shares comme le cpu.shares.

    Je ne trouve que des exemples avec blkio qui limitent le débit, il n'y a vraiment pas d'autre solution ?

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.