web-dev-qa-db-fra.com

Comment utiliser des cgroups pour limiter tous les processus sauf Whitelist à un seul processeur?

Il y a un Guide des cgroups de Red Hat qui est peut-être une sorte de genre de type d'utile (mais ne répond pas à cette question).

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

Tout d'abord, mettre les éléments suivants * en /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;
  }
}

Puis démarrez un processus et attribuez-le spécifiquement à ce cgroup en utilisant:

cgexec -g cpuset:cpu0only myprocessname

Je peux limiter automatiquement toutes les instances d'un nom de processus spécifique par (i pense C'est correct) Mettre ce qui suit dans /etc/cgrules.conf:

# user:process  controller  destination
*:myprocessname cpuset      cpu0only

Ma question est la suivante: comment puis-je faire le inverse?

En d'autres termes, Comment puis-je assigner tous Processus, à l'exception d'un ensemble spécifique de processus blanchisés et leurs enfants cgroup restreint?


Basé sur ce que j'ai étudié, mais je n'ai pas testé, je suis Croyez A partiel Solution serait:

Ajouter un cgroup "sans restriction":

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

Attribuez mon processus explicitement au groupe sans restriction et tout le reste au groupe restreint:

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

Cependant, la mise en garde contre cela semble être (de lire les documents, pas des tests, de sorte que les enfants de sel) que les enfants de myprocessname seront réaffectés à la limite restreinte cpu0only cgroup.

Une approche alternative possible serait de créer un utilisateur pour exécuter myprocessname et avoir tout cet utilisateur traite sans restriction et tout le reste restreint. Cependant, dans mon cas d'utilisation réelle, le processus doit être exécuté par root, et il y a d'autres processus qui doivent également être exécutés par root qui devrait être restreint.

Comment puis-je accomplir cela avec des cgroups?


Si cela n'est pas possible avec des cgroups (ce que je soupçonne maintenant est le cas), sont mes idées de solutions partielles correct et travailleront-ils comme je pense?

* Disclaimer: Ce n'est probablement pas un exemple de code minimal; je ne comprends pas tout Les parties donc je ne sais pas qui ne sont pas nécessaires.

27
Wildcard

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 obsolète.


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 sais maintenant plus que je ne m'attendais jamais à apprendre sur les cgroups, je vais donc répondre à ma propre question ici.

Vous pouvez prendre plusieurs approches. Le contact de notre société chez Red Hat (architecte technique) s'est 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 que cela est possible pour les appels de système de dépendre du code de l'espace utilisateur (tels que les processus LVM), que si restreint pourrait ralentir le système, le contraire de l'effet envisagé. Donc, j'ai fini par restreindre plusieurs processus spécifiquement nommés et laisser tout le reste seul.

De plus, je veux mentionner certains Cgroup Basic Data que j'avais manqué quand j'ai posté ma question.


cgroups do pas dépend de libcgroup étant installé. Toutefois, c'est un ensemble d'outils permettant de manipuler automatiquement la configuration de Cgroup et des missions de processus aux cgroups et peuvent Soyez très utile.

J'ai constaté que les outils LibcGroup peuvent également être trompeurs, car le paquet libcgroup est construit sur son propre Ensemble d'abstractions et d'hypothèses sur votre utilisation de cgroups, qui sont légèrement différentes de la mise en œuvre réelle du niveau du noyau. de cgroups. (Je peux mettre des exemples mais cela prendrait du travail; commenter si vous êtes intéressé.)

Par conséquent, avant d'utiliser des outils libcgroup (tels que /etc/cgconfig.conf, /etc/cgrules.conf, cgexec, cgcreate, cgclassify, etc.) i hautement Recommander très familier avec le /cgroup Système de fichiers virtuels elle-même et création manuelle des cgroups, des hiérarchies de Cgroup (y compris des hiérarchies avec plusieurs sous-systèmes rattachés, ce que LibcGroup résoutit sournoisement et fuite des résumés), réaffectant des processus à différents cgroups en exécutant echo $the_pid > /cgroup/some_cgroup_hierarchy/a_cgroup_within_that_hierarchy/tasks, et d'autres tâches apparemment magiques que libcgroup fonctionne sous la hotte.


Un autre concept de base que j'avais manqué était que si le /cgroup Le systè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é du tout), puis chaque Processus sur votre système complet Is in un cgroup. Il n'y a pas de telles choses telles que "Certains processus sont dans un cgroup et certains ne sont pas".

Il y a ce qu'on appelle le root Cgroup pour une hiérarchie donnée, qui possède tout Les ressources du système pour les sous-systèmes connectés. Par exemple, une hiérarchie Cgroup qui comporte les sous-systèmes CPuset et Blkio attachées, aurait un cgroup racine qui posséderait tous Les CPU sur le système et tous les Blkio sur le système et pourraient partager une partie de Ces ressources avec Enfant Cgroups. Vous ne pouvez pas restreindre le cgroup racine parce qu'il possède tout Les ressources de votre système, alors restreignant cela ne serait même pas logique.


Quelques autres données simples que j'avais manquantes à propos de LibcGroup:

Si tu utilises /etc/cgconfig.conf, vous devez vous assurer que chkconfig --list cgconfig montre que cgconfig est défini pour exécuter au démarrage du système.

Si vous changez /etc/cgconfig.conf, vous devez courir service cgconfig restart Pour charger dans les changements. (Et des problèmes d'arrêt du service ou de la course cgclear sont très courants lorsqu'il trompe des tests. Pour le débogage, je recommande, par exemple, lsof /cgroup/cpuset, si cpuset est le nom de la hiérarchie de Cgroup que vous utilisez.)

Si vous voulez utiliser /etc/cgrules.conf, vous devez vous assurer que le "Démon de moteur Rules Cgroup" (cgrulesengd) est en cours d'exécution: service cgred start et chkconfig cgred on. (Et vous devez être conscient d'une condition de course possible mais improbable 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 tromper manuellement et configurer vos cgroups à 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.conf Fichier Pour refléter votre configuration à l'aide de cgsnapshot avec ses différentes options.


Et enfin, la clé d'informations clés que j'étais manquante 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 cgroup cpu0only restreint.

J'étais correct, 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'attribuer à un cgroup.

cgclassify est la commande d'attribuer un processus déjà en cours d'exécution à un cgroup.

Ces deux empêcheront également cgred (cgrulesengd) de réaffecter le processus spécifié à un cgroupe différent basé sur /etc/cgrules.conf.

les deux cgexec et cgclassify prennent en charge la --sticky drapeau, qui en outre empêche cgred de réaffectation enfant processus basés sur /etc/cgrules.conf.


Donc, La réponse à la question comme je l'ai écrite (Bien que la configuration que j'ai fini par la mise en œuvre, en raison des conseils de notre architecte technique de Red Hat mentionné ci-dessus) est:

Faire le cpu0only et anycpu cgroup comme décrit dans ma question. (Assurez-vous que cgconfig est défini pour exécuter au démarrage.)

Faire le * cpuset cpu0only règle comme décrit dans ma question. (Et assurez-vous cgred est défini pour fonctionner au démarrage.)

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

Ces processus seront sans restriction et tous leurs processus pour enfants seront également sans restriction. Tout le reste sur le système sera limité à la CPU 0 (une fois que vous redémarrez, puisque cgred _ n'applique pas de cgrules à des processus déjà en cours d'exécution, à moins de changer leur UEID). Ce n'est pas complètement conseillé, mais c'était ce que j'ai initialement demandé et cela peut être fait avec des cgroups.

31
Wildcard