Limitar o uso total de memória para várias instâncias do serviço systemd

1

Estou executando alguns processos do .NET Core como serviços systemd no Ubuntu 16.04 (logo a ser 18.04). Eu tenho um arquivo de configuração systemd ( /lib/systemd/system/[email protected] ) que se parece com isto:

[Unit]
Description=My Service %i

[Service]
Type=simple
User=myservice
EnvironmentFile=/etc/environment
WorkingDirectory=/home/myservice/instances/%i
ExecStart=/opt/dotnet/dotnet My.Service.dll

[Install]
WantedBy=multi-user.target

Eu quero limitar a quantidade total de RAM que todas instâncias deste serviço podem usar. Não quero limitar a RAM de nenhuma instância individual a menos do que isso, portanto, configurações como MemoryHigh e MemoryMax não são úteis.

Eu sei que systemd cria um cgroup para o template de serviço, então eu quero mudar o limite de memória para esse cgroup de alguma forma.

No Ubuntu 18.04 eu posso editar manualmente /sys/fs/cgroup/memory/system.slice/system-myservice.slice/memory.limit_in_bytes e isso basicamente faz o que eu quero (processos são mortos quando o uso total de memória excede o limite), mas existem alguns problemas com essa abordagem:

  • Este arquivo nem sempre existe na inicialização até que o serviço seja iniciado.
  • No Ubuntu 18.04, esse arquivo é sobrescrito sempre que systemctl daemon-reload é chamado.
  • Tentar gravar no arquivo às vezes retorna write error: Device or resource busy

(No Ubuntu 16.04, o limite parece ser redefinido sempre que meu serviço é iniciado, por isso não tem efeito.)

Existe alguma maneira de obter o próprio systemd para definir esse valor, então eu não tenho que lutar contra isso? Ou alguma outra maneira de limitar o uso total de memória para um grupo de processos? Todos eles são executados como o mesmo usuário, por isso, seria OK limitar a RAM usada por esse usuário, por exemplo.

Eu até tentei criar manualmente um cgroup ( cgcreate -t myservice:myservice -g memory:mycgroup ) e depois alterar ExecStart na configuração do serviço para /usr/bin/cgexec -g memory:mycgroup /opt/dotnet/dotnet My.Service.dll e isso novamente funciona, mas não de forma confiável: o limite de memória que escrevi para memory.limit_in_bytes tem redefinir em algum momento e eu não sei quando ou por quê.

    
por EM0 10.04.2018 / 16:36

1 resposta

0

Talvez seja necessário usar "hierarquia de cgroup unificada", conforme explicado em Hierarquias do grupo de controle unificado e legado .

Para ativar esse recurso, adicione     systemd.unified_cgroup_hierarchy = 1 para GRUB_CMDLINE_LINUX_DEFAULT em /etc/default/grub , execute update-grub e reinicie o Linux.

systemd.unified_cgroup_hierarchy é explicado aqui .

Em seguida, adicionamos as seguintes linhas na seção [Service] do arquivo de unidade do systemd, e execute systemctl daemon-reload :

Delegate=memory
MemoryHigh=8G (if you choose 8 gigabytes as the limit)

Explicação de "MemoryHigh" é dada em aqui .

    
por 30.06.2018 / 00:52