Skip to content

Commit

Permalink
nixos/systemd-oomd: Add a new module + test
Browse files Browse the repository at this point in the history
  • Loading branch information
dasJ committed Aug 31, 2022
1 parent bacac7c commit 3284f4f
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 0 deletions.
15 changes: 15 additions & 0 deletions nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,21 @@
Add udev rules for the Teensy family of microcontrollers.
</para>
</listitem>
<listitem>
<para>
systemd-oomd is enabled by default. Depending on which systemd
units have <literal>ManagedOOMSwap=kill</literal> or
<literal>ManagedOOMMemoryPressure=kill</literal>, systemd-oomd
will SIGKILL all the processes under the appropriate
descendant cgroups when the configured limits are exceeded.
NixOS does currently not configure cgroups with oomd by
default, this can be enabled using
<link xlink:href="options.html#opt-systemd.oomd.enableRootSlice">systemd.oomd.enableRootSlice</link>,
<link xlink:href="options.html#opt-systemd.oomd.enableSystemSlice">systemd.oomd.enableSystemSlice</link>,
and
<link xlink:href="options.html#opt-systemd.oomd.enableUserServices">systemd.oomd.enableUserServices</link>.
</para>
</listitem>
<listitem>
<para>
The <literal>pass-secret-service</literal> package now
Expand Down
9 changes: 9 additions & 0 deletions nixos/doc/manual/release-notes/rl-2211.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ Use `configure.packages` instead.

- Add udev rules for the Teensy family of microcontrollers.

- systemd-oomd is enabled by default. Depending on which systemd units have
`ManagedOOMSwap=kill` or `ManagedOOMMemoryPressure=kill`, systemd-oomd will
SIGKILL all the processes under the appropriate descendant cgroups when the
configured limits are exceeded. NixOS does currently not configure cgroups
with oomd by default, this can be enabled using
[systemd.oomd.enableRootSlice](options.html#opt-systemd.oomd.enableRootSlice),
[systemd.oomd.enableSystemSlice](options.html#opt-systemd.oomd.enableSystemSlice),
and [systemd.oomd.enableUserServices](options.html#opt-systemd.oomd.enableUserServices).

- The `pass-secret-service` package now includes systemd units from upstream, so adding it to the NixOS `services.dbus.packages` option will make it start automatically as a systemd user service when an application tries to talk to the libsecret D-Bus API.

- There is a new module for AMD SEV CPU functionality, which grants access to the hardware.
Expand Down
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,7 @@
./system/boot/systemd/journald.nix
./system/boot/systemd/logind.nix
./system/boot/systemd/nspawn.nix
./system/boot/systemd/oomd.nix
./system/boot/systemd/shutdown.nix
./system/boot/systemd/tmpfiles.nix
./system/boot/systemd/user.nix
Expand Down
57 changes: 57 additions & 0 deletions nixos/modules/system/boot/systemd/oomd.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{ config, lib, ... }: let

cfg = config.systemd.oomd;

in {
options.systemd.oomd = {
enable = lib.mkEnableOption "the systemd-oomd OOM killer" // { default = true; };

# Fedora enables the first and third option by default. See the 10-oomd-* files here:
# https://src.fedoraproject.org/rpms/systemd/tree/acb90c49c42276b06375a66c73673ac351025597
enableRootSlice = lib.mkEnableOption "oomd on the root slice (-.slice)";
enableSystemSlice = lib.mkEnableOption "oomd on the system slice (system.slice)";
enableUserServices = lib.mkEnableOption "oomd on all user services ([email protected])";

extraConfig = lib.mkOption {
type = with lib.types; attrsOf (oneOf [ str int bool ]);
default = {};
example = lib.literalExpression ''{ DefaultMemoryPressureDurationSec = "20s"; }'';
description = ''
Extra config options for systemd-oomd. See man oomd.conf
for available options.
'';
};
};

config = lib.mkIf cfg.enable {
systemd.additionalUpstreamSystemUnits = [
"systemd-oomd.service"
"systemd-oomd.socket"
];
systemd.services.systemd-oomd.wantedBy = [ "multi-user.target" ];

environment.etc."systemd/oomd.conf".text = lib.generators.toINI {} {
OOM = cfg.extraConfig;
};

systemd.oomd.extraConfig.DefaultMemoryPressureDurationSec = lib.mkDefault "20s"; # Fedora default

users.users.systemd-oom = {
description = "systemd-oomd service user";
group = "systemd-oom";
isSystemUser = true;
};
users.groups.systemd-oom = { };

systemd.slices."-".sliceConfig = lib.mkIf cfg.enableRootSlice {
ManagedOOMSwap = "kill";
};
systemd.slices."system".sliceConfig = lib.mkIf cfg.enableSystemSlice {
ManagedOOMSwap = "kill";
};
systemd.services."user@".serviceConfig = lib.mkIf cfg.enableUserServices {
ManagedOOMMemoryPressure = "kill";
ManagedOOMMemoryPressureLimit = "50%";
};
};
}
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ in {
systemd-networkd-ipv6-prefix-delegation = handleTest ./systemd-networkd-ipv6-prefix-delegation.nix {};
systemd-networkd-vrf = handleTest ./systemd-networkd-vrf.nix {};
systemd-nspawn = handleTest ./systemd-nspawn.nix {};
systemd-oomd = handleTest ./systemd-oomd.nix {};
systemd-shutdown = handleTest ./systemd-shutdown.nix {};
systemd-timesyncd = handleTest ./systemd-timesyncd.nix {};
systemd-misc = handleTest ./systemd-misc.nix {};
Expand Down
37 changes: 37 additions & 0 deletions nixos/tests/systemd-oomd.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import ./make-test-python.nix ({ pkgs, ... }:

{
name = "systemd-oomd";

nodes.machine = { pkgs, ... }: {
systemd.oomd.extraConfig.DefaultMemoryPressureDurationSec = "1s"; # makes the test faster
# Kill cgroups when more than 1% pressure is encountered
systemd.slices."-".sliceConfig = {
ManagedOOMMemoryPressure = "kill";
ManagedOOMMemoryPressureLimit = "1%";
};
# A service to bring the system under memory pressure
systemd.services.testservice = {
serviceConfig.ExecStart = "${pkgs.coreutils}/bin/tail /dev/zero";
};
# Do not kill the backdoor
systemd.services.backdoor.serviceConfig.ManagedOOMMemoryPressure = "auto";

virtualisation.memorySize = 1024;
};

testScript = ''
# Start the system
machine.wait_for_unit("multi-user.target")
machine.succeed("oomctl")
# Bring the system into memory pressure
machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # NixOS tests kill the VM when the OOM killer is invoked - override this
machine.succeed("systemctl start testservice")
# Wait for oomd to kill something
# Matches these lines:
# systemd-oomd[508]: Killed /system.slice/systemd-udevd.service due to memory pressure for / being 3.26% > 1.00% for > 1s with reclaim activity
machine.wait_until_succeeds("journalctl -b | grep -q 'due to memory pressure for'")
'';
})

0 comments on commit 3284f4f

Please sign in to comment.