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ê.