Comment utiliser les groupes de contrôle pour limiter tous les processus sauf la liste blanche à un seul processeur?

26

Il existe un guide des cgroups de Red Hat qui est peut-être un peu utile (mais ne répond pas à cette question).

Je sais comment limiter un processus spécifique à un CPU spécifique, lors de la commande pour démarrer ce processus, en:

Tout d'abord, insérez les éléments suivants * /etc/cgconfig.conf:

mount {
  cpuset =  /cgroup/cpuset;
  cpu =     /cgroup/cpu;
  cpuacct = /cgroup/cpuacct;
  memory =  /cgroup/memory;
  devices = /cgroup/devices;
  freezer = /cgroup/freezer;
  net_cls = /cgroup/net_cls;
  blkio =   /cgroup/blkio;
}

group cpu0only {
  cpuset {
    cpuset.cpus = 0;
    cpuset.mems = 0;
  }
}

Et puis démarrez un processus et affectez-le spécifiquement à ce groupe de contrôle en utilisant:

cgexec -g cpuset:cpu0only myprocessname

Je peux limiter automatiquement toutes les instances d'un nom de processus spécifique en (je pense que c'est correct) en mettant ce qui suit dans /etc/cgrules.conf:

# user:process  controller  destination
*:myprocessname cpuset      cpu0only

Ma question est: comment faire l' inverse ?

En d'autres termes, comment puis-je affecter tous les processus à l'exception d'un ensemble spécifique de processus en liste blanche et de leurs enfants à un groupe de contrôle restreint?


Sur la base de ce que j'ai étudié, mais que je n'ai pas testé, je pense qu'une solution partielle serait:

Ajoutez un groupe de contrôle "sans restriction":

group anycpu {
  cpuset {
    cpuset.cpus = 0-31;
    cpuset.mems = 0;  # Not sure about this param but it seems to be required
  }
}

Assignez mon processus explicitement au groupe non restreint et tout le reste au groupe restreint:

# user:process  controller  destination
*:myprocessname cpuset      anycpu
*               cpuset      cpu0only

Cependant, la mise en garde à ce sujet semble être (de la lecture des documents, pas des tests, donc du grain de sel) que les enfants de myprocessnameseront réaffectés au groupe restreint cpu0only.

Une autre approche possible serait de créer un utilisateur à exécuter myprocessnameet d'avoir tous les processus de cet utilisateur sans restriction, et tout le reste restreint. Cependant, dans mon cas d'utilisation réel, le processus doit être exécuté par root, et il existe d'autres processus qui doivent également être exécutés par root qui doivent être limités.

Comment puis-je accomplir cela avec des groupes de contrôle?


Si ce n'est pas possible avec les cgroups (ce que je soupçonne maintenant d'être le cas), mes idées de solutions partielles sont-elles correctes et fonctionneront-elles comme je le pense?

* Avertissement: Ce n'est probablement pas un exemple de code minimal; je ne comprends pas toutes les parties, donc je ne sais pas lesquelles ne sont pas nécessaires.

Caractère générique
la source

Réponses:

30

MISE À JOUR: Notez que la réponse ci-dessous s'applique à RHEL 6. Dans RHEL 7, la plupart des cgroups sont gérés par systemd et libcgroup est déconseillé.


Depuis la publication de cette question, j'ai étudié l'intégralité du guide que j'ai lié à ci-dessus, ainsi que la majorité de la documentation cgroups.txt et cpusets.txt . Je connais maintenant plus que je ne m'attendais à en savoir plus sur les groupes de contrôle, je vais donc répondre à ma propre question ici.

Il existe plusieurs approches que vous pouvez adopter. Le contact de notre entreprise chez Red Hat (un architecte technique) a recommandé contre une restriction générale de tous les processus, de préférence à une approche plus déclarative - restreignant uniquement les processus que nous voulions spécifiquement restreints. La raison de cela, selon ses déclarations sur le sujet, est qu'il est possible que les appels système dépendent du code de l'espace utilisateur (tel que les processus LVM) qui, s'il était restreint, pourrait ralentir le système - l'opposé de l'effet recherché. J'ai donc fini par restreindre plusieurs processus spécifiquement nommés et laisser tout le reste tranquille.

De plus, je veux mentionner certaines données de base de cgroup qui me manquaient lorsque j'ai posté ma question.


Les groupes de contrôle ne dépendent pas de libcgroupleur installation. Cependant, il s'agit d'un ensemble d'outils pour gérer automatiquement la configuration de cgroup et les affectations de processus aux cgroups et peut être très utile.

J'ai trouvé que les outils libcgroup peuvent également être trompeurs, car le package libcgroup est construit sur son propre ensemble d'abstractions et d'hypothèses sur votre utilisation des cgroups, qui sont légèrement différentes de l'implémentation réelle au niveau du noyau des cgroups. (Je peux mettre des exemples mais cela demanderait du travail; commentez si vous êtes intéressé.)

Par conséquent, avant d' utiliser des outils de libcgroup (tels que /etc/cgconfig.conf, /etc/cgrules.conf, cgexec, cgcreate, cgclassify, etc.) Je fortement recommande d' obtenir très familier avec le /cgroupsystème de fichiers virtuel lui - même, et créer manuellement des groupes de contrôle, des hiérarchies de groupes de contrôle (y compris les hiérarchies avec de multiples sous - systèmes connectés, qui libcgroup sneakily et résumés leakily ), réaffecter des processus à différents groupes de contrôle en exécutant echo $the_pid > /cgroup/some_cgroup_hierarchy/a_cgroup_within_that_hierarchy/tasks, et d'autres tâches apparemment magiques qui libcgroups'exécutent sous le capot.


Un autre concept de base qui me manquait était que si le /cgroupsystème de fichiers virtuel est monté sur votre système (ou plus précisément, si l'un des sous-systèmes cgroup aka "contrôleurs" est monté), alors chaque processus sur votre système entier est dans un cgroup. Il n'y a rien de tel que «certains processus sont dans un groupe de contrôle et certains ne le sont pas».

Il existe ce qu'on appelle le groupe racine pour une hiérarchie donnée, qui possède toutes les ressources du système pour les sous-systèmes attachés. Par exemple, une hiérarchie de groupes de contrôle auxquels sont attachés les sous-systèmes cpuset et blkio aurait un groupe de contrôle racine qui détiendrait tous les processeurs du système et tous les blkio du système et pourrait partager certaines de ces ressources avec des groupes de contrôle enfants . Vous ne pouvez pas restreindre le groupe de contrôle racine car il possède toutes les ressources de votre système, donc le restreindre n'aurait même aucun sens.


Quelques autres données simples qui me manquaient sur libcgroup:

Si vous utilisez /etc/cgconfig.conf, vous devez vous assurer que les chkconfig --list cgconfigémissions cgconfigsont définies pour s'exécuter au démarrage du système.

Si vous changez /etc/cgconfig.conf, vous devez exécuter service cgconfig restartpour charger les modifications. (Et les problèmes liés à l'arrêt du service ou à l'exécution cgclearsont très fréquents lors des tests. Pour le débogage, je recommande, par exemple lsof /cgroup/cpuset, si cpusetest le nom de la hiérarchie de groupe de contrôle que vous utilisez.)

Si vous voulez l'utiliser /etc/cgrules.conf, vous devez vous assurer que le "démon du moteur de règles de groupe" ( cgrulesengd) est en cours d'exécution: service cgred startet chkconfig cgred on. (Et vous devez être conscient d'une condition de concurrence possible mais peu probable concernant ce service, comme décrit dans le Guide de gestion des ressources Red Hat à la section 2.8.1 au bas de la page.)

Si vous voulez vous amuser manuellement et configurer vos groupes de contrôle à l'aide du système de fichiers virtuel (que je recommande pour la première utilisation), vous pouvez le faire, puis créer un cgconfig.conffichier pour refléter votre configuration à l'aide cgsnapshotde ses différentes options.


Et enfin, l'élément clé des informations qui me manquait lorsque j'ai écrit ce qui suit:

Cependant, la mise en garde à ce sujet semble être ... que les enfants de myprocessname seront réaffectés au groupe restreint cpu0only.

J'avais raison, mais il y a une option que je n'étais pas au courant.

cgexec est la commande pour démarrer un processus / exécuter une commande et l'affecter à un groupe de contrôle.

cgclassify est la commande pour affecter un processus déjà en cours d'exécution à un groupe de contrôle.

Les deux empêcheront également cgred( cgrulesengd) de réaffecter le processus spécifié à un autre groupe de contrôle basé sur /etc/cgrules.conf.

Les deux cgexecet cgclassifysoutenir le --stickydrapeau, qui en outre empêche cgredde réattribution enfant processus basés sur /etc/cgrules.conf.


Ainsi, la réponse à la question telle que je l'ai écrite (mais pas la configuration que j'ai finalement implémentée, en raison des conseils de notre architecte technique Red Hat mentionnés ci-dessus) est:

Faites le cpu0onlyet anycpucgroup comme décrit dans ma question. (Assurez cgconfig- vous qu'il est configuré pour s'exécuter au démarrage.)

Faites la * cpuset cpu0onlyrègle comme décrit dans ma question. (Et assurez cgred- vous qu'il est configuré pour s'exécuter au démarrage.)

Démarrez les processus que je veux sans restriction avec: cgexec -g cpuset:anycpu --sticky myprocessname.

Ces processus seront illimités, et tous leurs processus enfants seront également illimités. Tout le reste du système sera limité au CPU 0 (une fois que vous redémarrez, car il cgredn'applique pas les cgrules aux processus déjà en cours d'exécution à moins qu'ils ne modifient leur EUID). Ce n'est pas tout à fait conseillé, mais c'est ce que j'ai initialement demandé et cela peut être fait avec des groupes de contrôle.

Caractère générique
la source
sensationnel. cool. comment cela at-il eu 0 votes?
mikeserv
@mikeserv, merci. :) Réponse à votre question: vérifiez les dates; Je viens d'écrire cette réponse hier.
Wildcard
1
j'ai vu ça. mais c'était il y a 24 heures. probablement sa cause sa longue. les bonnes choses peuvent parfois être négligées comme ça. et de toute façon, les réponses avec beaucoup de votes très bientôt sont très rarement les bonnes - les informations ne peuvent pas être si utiles si tant de gens le savent déjà. c'est l'un des bons, cependant. cgroups sont friggin mystérieux.
mikeserv