Como criar um usuário com uso limitado de RAM?

44

Então, eu tenho 4 GB de RAM + 4 GB de swap. Quero criar um usuário com ram e swap limitados: 3 GB de RAM e 1 GB de swap. Isso é possível? É possível iniciar aplicativos com RAM limitada e trocar disponível para eles sem criar um usuário separado (e não instalar nenhum aplicativo especial - tendo apenas uma configuração padrão do servidor Debian / CentOS e sem usar o sudo)?

Atualizar:

Então eu abri o terminall e digitei o comando ulimit : ulimit -v 1000000que deve ser como 976,6Mblimitação. Em seguida, liguei ulimit -ae vi que a limitação está "ativada". Então iniciei um script bash que compila e inicia meu aplicativo nohup, um longo nohup ./cloud-updater-linux.sh >& /dev/null & ... mas depois de algum tempo, vi:

insira a descrição da imagem aqui

(o que seria aceitável se nenhuma limitação fosse aplicada - ele baixou uma grande lib e começou a compilá-la.)

Mas pensei em aplicar limitações ao shell e a todos os processos iniciados com / a partir dele ulimit -v 1000000? O que eu errei? Como fazer um terminal e todos os subprocessos lançados serem limitados ao uso de memória ram?

myWallJSON
fonte
1
Você não pode colocar restrições de memória em um usuário como um todo, apenas em cada processo. E você não pode distinguir entre RAM e uso de swap. Se você deseja um controle mais preciso, execute os processos do usuário em uma máquina virtual.
Gilles 'SO- stop be evil'
@Gilles certeza que as máquinas virtuais é só usar cgroups e namespaces, ou derivados de
RapidWebs
@RapidWebs não, eles não. Eles apenas simulam a quantidade predefinida de RAM e o sistema operacional convidado decide como alocá-la aos processos.
Ruslan
Contêineres (não máquinas virtuais) usam cgroups para limitar o uso de memória. Limitar a memória virtual não é uma boa ideia; Um processo pode usar muita memória virtual, mas pode usar apenas um pouco de RAM. Por exemplo, meu sistema possui 34359738367 kB de memória virtual alocada, mas muito menos RAM.
Ctrl-alt-delor

Respostas:

64

ulimité feito para isso. Você pode configurar os padrões ulimitpor usuário ou por grupo em

/etc/security/limits.conf

ulimit -v KBYTESdefine o tamanho máximo da memória virtual. Eu não acho que você pode dar uma quantidade máxima de troca. É apenas um limite para a quantidade de memória virtual que o usuário pode usar.

Então você limits.confteria a linha (no máximo 4Gde memória)

luser  hard  as   4000000

UPDATE - CGroups

Os limites impostos por ulimite limits.confsão por processo. Eu definitivamente não estava claro sobre esse ponto.

Se você deseja limitar a quantidade total de memória que um usuário usa (que é o que você pediu). Você quer usar cgroups .

Em /etc/cgconfig.conf:

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

Isso cria um cgroupque possui um limite máximo de memória de 4GiB.

Em /etc/cgrules.conf:

luser   memory   memlimit/

Isso fará com que todos os processos executados lusersejam executados dentro dos memlimitcgroups criados no cgconfig.conf.

sombrio
fonte
tal coisa pode ser resolvida useradd?
myWallJSON
4
@myWallJSON Não diretamente, mas você pode adicioná-lo imediatamente ao limits.conf ou pode configurar um grupo com certos limites no limits.conf e adicionar usuário a esse grupo.
utopiabound
1
Fantástico! Eu não sabia que você poderia fazer isso! Ótima resposta +1
Yanick Girouard
1
@utopiabound: Atualizei meu Q com alguns dados que tentei usar ulimit.
myWallJSON
1
@ f.ardelian Atualize o kernel. Aqui está um artigo sobre como fazer exatamente isso!
Daniel C. Sobral
4

Você não pode limitar o uso da memória no nível do usuário, o ulimit pode fazer isso, exceto por um único processo.

Mesmo com o uso de limites por usuário /etc/security/limits.conf, um usuário pode usar toda a memória executando vários processos.

Se você realmente deseja limitar os recursos, precisa usar uma ferramenta de gerenciamento de recursos, como o rcapd usado por projetos e zonas no Solaris.

Há algo que parece fornecer recursos semelhantes no Linux que você pode investigar: cgroups .

jlliagre
fonte
Bem, suponho que definir um limite para o shell de login do usuário ou algo assim possa ser interpretado como "definir um limite para o usuário", pois todos os processos herdariam desse shell?
quer
1
@ amn Não vai. Um usuário pode simplesmente abrir um novo shell de logon para solucionar esse limite.
Jlliagre 18/04
Certo, isso invalida minha suposição.
quer
3

cgroupssão a maneira correta de fazer isso, como outras respostas apontaram. Infelizmente, não há uma solução perfeita para o problema, como veremos abaixo. Existem várias maneiras diferentes de definir os limites de uso de memória do cgroup. O modo como alguém faz com que a sessão de login de um usuário faça parte automaticamente de um cgroup varia de sistema para sistema. O Red Hat tem algumas ferramentas, e o systemd também .

memory.memsw.limit_in_bytese memory.limit_in_bytesdefinir limites, incluindo e não incluindo swap, respectivamente. A desvantagem memory.limit_in_bytesé que ele conta os arquivos armazenados em cache pelo kernel em nome dos processos no cgroup contra a cota do grupo. Menos cache significa mais acesso ao disco; portanto, você está potencialmente perdendo algum desempenho se o sistema tiver alguma memória disponível.

Por outro lado, memory.soft_limit_in_bytespermite que o cgroup exceda a cota, mas se o killer do OOM do kernel for invocado, os cgroups que estão acima de suas cotas serão mortos primeiro, logicamente. A desvantagem disso, no entanto, é que existem situações em que é necessária alguma memória imediatamente e não há tempo para o OOM killer procurar processos a serem eliminados; nesse caso, algo pode falhar antes que os processos do usuário com excesso de cota sejam morto.

ulimit, no entanto, é absolutamente a ferramenta errada para isso. O ulimit impõe limites ao uso da memória virtual, o que quase certamente não é o que você deseja. Muitos aplicativos do mundo real usam muito mais memória virtual do que memória física. A maioria dos tempos de execução coletados por lixo (Java, Go) funciona dessa maneira para evitar a fragmentação. Um programa trivial "olá mundo" em C, se compilado com desinfetante de endereço, pode usar 20 TB de memória virtual. Alocadores nos quais não dependem sbrk, como jemalloc (que é o alocador padrão para Rust) ou tcmalloc, também terão uso de memória virtual substancialmente superior ao uso físico. Para maior eficiência, muitas ferramentas mapearão arquivos, o que aumenta o uso virtual, mas não necessariamente o uso físico. Todos os meus processos do Chrome estão usando 2 TB de memória virtual cada. Estou em um laptop com 8 GB de memória física. De qualquer maneira que alguém tentasse configurar cotas de memória virtual aqui, ele quebraria o Chrome, forçaria o Chrome a desativar alguns recursos de segurança que dependem da alocação (mas não o uso) de grandes quantidades de memória virtual ou seria completamente ineficaz para impedir que um usuário abuse do sistema .

Adam Azarchs
fonte