Limiting snap's memory usage

We need to find out a way to limit the memory usage of the snap in our Ubuntu Core running devices.

It would be nice to apply the limits to systemd services, but limiting the memory usage of entire snap would be fine either.

I saw a couple of posts in the forum requesting this functionaly. For us it’s not critical to set-up the limits dynamically, we can specify it as snapcraft service values, for example as Systemd’s MemoryLimit setting.

Did anybody solve a similar problem? Any help is appreciated.

3 Likes

Ping @ondra / @mvo - any chance you could chime in here? Thanks.

I’m not sure if it is the best solution, but something that will probably work right now would be to use systemd “drop-in” configuration files.

For example, if your snap provides a systemd service called snap.foo.bar.service, you could create a file /etc/systemd/system/snap.foo.bar.service.d/memory.conf:

[Service]
MemoryMax=nnnn

This should survive upgrades of the snap, and combined with any settings in the main service configuration file.

As far as getting the configuration file onto the device, presumably you can do this with a gadget snap (which is probably where it belongs for device specific settings like memory limits).

1 Like

Thanks @jamesh

I made the change on the existing device and it worked with a small change - I had to replace MemoryMax with MemoryLimit.

Now I’m trying to deliver this update or our existing devices and I can’t find any snap interface that allows writing to the systemd’s directory.

Not sure that gadget snap is capable of modifying systemd’s files.

It looks like MemoryMax didn’t exist when Xenial was released. So yes, MemoryLimit would be what you want for an Ubuntu Core 16 device.

My thought was that you could use the gadget snap’s prepare-device hook to place the config file fragments. That only really helps for new devices though: I don’t have a good idea of how to handle existing devices. Hopefully someone else has some ideas?

@mvo and I discussed this in the past and there was consensus that snapd would unconditionally add every snap to a cpu and memory cgroup, but not actually set any limits which would at least let an admin apply limits. After this, a mechanism would be devised to allow a snap to modify these cgroups (snapctl, gadget, interface, etc). IIRC, @mvo did a proof-of-concept, but I’m not sure of the status of this work or if it is roadmapped. Perhaps @mvo or @pedronis can comment.

This does not currently exist. It is interesting to think about the gadget having access to /etc/systemd/system/snap.*/*.conf files, or this potentially added as an interface (or possibly snapd-control). This would need a bit of design (cc @mvo and @pedronis).

@jdstrand, did you consider setting something like setting the limits from the snapcraft files instad, like a restart delay[1] that we successfully use already.

  1. https://github.com/snapcore/snapd/blob/master/wrappers/services.go#L426

yes, we did consider it, the problem with that, is that for any snap that is not single purpose, known to run exactly on one device/device class, it’s very hard to set good values there or for us to come up with ranges of what would be reasonable demands from the snap on the system (they would be system dependent). The values will depend on usage. In the end the user or the gadget would have to override them, in some scenarios it would even be a nuisance. I understand that conversely in some cases it would be very convenient, we would need a way to enable those only in some cases, via some rules, like we do for interfaces.

1 Like

@jamesh, it seems that I am doing something wrong, because the prepare-device hook doesn’t allow me to modify the file system.

Run prepare-device hook

2019-06-22T06:09:42Z ERROR run hook "prepare-device": mkdir: cannot create directory ‘/etc/systemd/system/snap.screenly-client.viewer.service.d’: Permission denied

PS. I used mkdir -p

Finally, I got it working. We have an initrd file in our gadget snap. I put the bash script that creates all the directories and files during the boot process into the initrd and it worked fine. Just one thing - all the paths should be prepended with /root/writable/system-data/, eg /root/writable/system-data/etc/systemd/system/...

Thanks for help!

1 Like