Comment créer un utilisateur avec une utilisation limitée de la RAM?

45

J'ai donc 4 Go de RAM + 4 Go swap. Je souhaite créer un utilisateur avec une mémoire RAM et un échange limités: 3 Go de RAM et 1 Go d’échange. Une telle chose est-elle possible? Est-il possible de démarrer des applications avec une mémoire RAM et un échange limités qui leur sont disponibles sans créer un utilisateur distinct (et sans installer d'applications spéciales - n'ayant qu'une configuration de serveur Debian / CentOS par défaut et n'utilisant pas sudo)?

Mise à jour:

J'ai donc ouvert terminall et tapé dedans la commande ulimit : ulimit -v 1000000ce sera comme 976,6Mblimitation. Ensuite, j'ai appelé ulimit -aet vu que la limitation est "activée". Ensuite, j'ai commencé un script bash qui compile et démarre mon application nohup, un long nohup ./cloud-updater-linux.sh >& /dev/null & ... mais après un certain temps, j'ai vu:

entrez la description de l'image ici

(Ce qui serait bien si aucune limitation n'était appliquée - il a téléchargé une bibliothèque volumineuse et a commencé à la compiler.)

Mais je pensais avoir appliqué des limitations au shell et à tous les processus lancés avec / depuis celui-ci ulimit -v 1000000? Qu'est-ce que je me suis trompé? Comment faire en sorte qu'un terminal et tous les sous-processus qu'il lance soient limités à l'utilisation de RAM?

myWallJSON
la source
1
Vous ne pouvez pas imposer de restrictions de mémoire à un utilisateur dans son ensemble, mais uniquement à chaque processus. Et vous ne pouvez pas distinguer l'utilisation de la RAM et de l'échange. Si vous souhaitez un contrôle plus précis, exécutez les processus de l'utilisateur sur une machine virtuelle.
Gilles, arrête de faire le mal
@Gilles à peu près sûr que les machines virtuelles utilisent simplement des
groupes de contrôle
@ RapidWebs non, ils ne le font pas. Ils émulent simplement la quantité de RAM prédéfinie et le système d'exploitation invité décide ensuite de la façon dont elle est allouée aux processus.
Ruslan
Les conteneurs (et non les machines virtuelles) utilisent des groupes de contrôle pour limiter l'utilisation de la mémoire. Limiter la mémoire virtuelle n'est pas une bonne idée. Un processus peut utiliser beaucoup de mémoire virtuelle, mais n'utiliser qu'un peu de RAM. Par exemple, mon système a 34359738367 Ko de mémoire virtuelle allouée, mais beaucoup moins de RAM.
ctrl-alt-delor

Réponses:

65

ulimitest fait pour cela. Vous pouvez configurer les valeurs par défaut pour ulimitchaque utilisateur ou groupe de personnes dans

/etc/security/limits.conf

ulimit -v KBYTESdéfinit la taille maximale de la mémoire virtuelle. Je ne pense pas que vous puissiez donner un maximum d’échange. C'est juste une limite sur la quantité de mémoire virtuelle que l'utilisateur peut utiliser.

Donc, vous limits.confauriez la ligne (avec un maximum 4Gde mémoire)

luser  hard  as   4000000

MISE À JOUR - CGroupes

Les limites imposées par ulimitet limits.confsont par processus. Je n'étais certainement pas clair sur ce point.

Si vous souhaitez limiter la quantité totale de mémoire utilisée par un utilisateur (ce que vous avez demandé). Vous voulez utiliser les cgroups .

Dans /etc/cgconfig.conf:

group memlimit {
    memory {
        memory.limit_in_bytes = 4294967296;
    }
}

Cela crée une cgrouplimite de mémoire maximale de 4 Go.

Dans /etc/cgrules.conf:

luser   memory   memlimit/

Ainsi, tous les processus exécutés par lusers'exécuteront dans les memlimitgroupes de contrôle créés dans cgconfig.conf.

utopique
la source
est-ce qu'une telle chose peut être réglée useradd?
myWallJSON
4
@myWallJSON Pas directement, mais vous pouvez l'ajouter immédiatement à limits.conf, ou vous pouvez configurer un groupe avec certaines limites dans limits.conf et ajouter un utilisateur à ce groupe.
Utopiabound
1
C'est génial! Je ne savais pas que tu pouvais faire ça! Excellente réponse +1
Yanick Girouard
1
@utopiabound: J'ai mis à jour mon Q avec certaines données que je tentais d'utiliser ulimit.
myWallJSON
1
@ f.ardelian Mettez à niveau le noyau. Voici un article sur comment faire exactement cela!
Daniel C. Sobral
4

Vous ne pouvez pas limiter l'utilisation de la mémoire au niveau utilisateur; ulimit peut le faire, mais pour un processus unique.

Même en utilisant des limites par utilisateur /etc/security/limits.conf, un utilisateur peut utiliser toute la mémoire en exécutant plusieurs processus.

Si vous souhaitez vraiment limiter les ressources, vous devez utiliser un outil de gestion des ressources, tel que rcapd utilisé par les projets et les zones sous Solaris.

Il y a quelque chose qui semble fournir des fonctionnalités similaires sur Linux que vous pourriez explorer: les groupes de contrôle .

jlliagre
la source
Eh bien, je suppose que fixer une limite au shell de connexion des utilisateurs ou quelque chose du genre pourrait être interprété comme "une limite pour l'utilisateur", puisque tous les processus hériteraient de ce shell?
amn
1
@ amn ça ne va pas. Un utilisateur peut simplement ouvrir un nouveau shell de connexion pour contourner une telle limite.
Juin
Oui, cela invalide mon hypothèse.
amn
4

cgroupssont la bonne façon de le faire, comme d'autres réponses l'ont souligné. Malheureusement, il n’ya pas de solution parfaite au problème, comme nous le verrons plus loin. Il existe différentes manières de définir les limites d'utilisation de la mémoire du groupe de contrôle. Comment faire pour que la session de connexion d'un utilisateur fasse automatiquement partie d'un groupe de contrôle varie d'un système à l'autre. Red Hat a quelques outils, tout comme systemd .

memory.memsw.limit_in_byteset memory.limit_in_bytesfixer des limites incluant et non compris l'échange, respectivement. L'inconvénient memory.limit_in_bytesest qu'il compte les fichiers mis en cache par le noyau pour le compte des processus du groupe de contrôle par rapport au quota du groupe. Moins de cache signifie plus d’accès au disque. Vous risquez donc de perdre des performances si le système disposait d’une mémoire suffisante.

D'autre part, memory.soft_limit_in_bytespermet au groupe de contrôle de dépasser le quota, mais si le tueur de MOO du noyau est invoqué, les groupes de contrôle dépassant leurs quotas sont tués en premier, logiquement. L’inconvénient, c’est qu’il existe parfois des situations dans lesquelles de la mémoire est nécessaire immédiatement et que le tueur OOM n'a pas le temps de rechercher les processus à tuer, auquel cas quelque chose peut échouer avant les processus de l’utilisateur hors quota. tué.

ulimit, cependant, est absolument le mauvais outil pour cela. ulimit impose des limites à l'utilisation de la mémoire virtuelle, ce qui n'est certainement pas ce que vous voulez. De nombreuses applications réelles utilisent beaucoup plus de mémoire virtuelle que de mémoire physique. La plupart des runtime collectés (Java, Go) fonctionnent de cette manière pour éviter la fragmentation. Un programme trivial "hello world" en C, s'il est compilé avec un assainisseur d'adresses, peut utiliser 20 To de mémoire virtuelle. Allocateurs qui ne s'appuient pas sur sbrk, comme jemalloc (qui est l'allocateur par défaut pour Rust) ou tcmalloc, aura également une utilisation de la mémoire virtuelle largement supérieure à leur utilisation physique. Pour plus d'efficacité, de nombreux outils utilisent des fichiers mmap, ce qui augmente l'utilisation virtuelle mais pas nécessairement physique. Tous mes processus Chrome utilisent 2 To de mémoire virtuelle chacun. Je suis sur un ordinateur portable avec 8 Go de mémoire physique. Quiconque tenterait de définir des quotas de mémoire virtuelle risquait de casser Chrome, de le forcer à désactiver certaines fonctionnalités de sécurité reposant sur l'allocation (mais de ne pas utiliser) de grandes quantités de mémoire virtuelle, ou d'empêcher complètement un utilisateur d'abuser du système. .

Adam Azarchs
la source