I need to configure a cgroup v2 controller for a pre-existing cgroup, such as cpu.max
. How can I do this with puppet?
On the shell, one would do this by writing to the interface file:
echo "19200000 100000" > /sys/fs/cgroup/system.slice/existing-group/cpu.max
However, the obvious approach of defining a file
resource with desired content does not work. If I define the resource:
file {
'/sys/fs/cgroup/system.slice/existing-group/cpu.max':
content => "19200000 100000\n",
;
}
then puppet can successfully manage metadata of the file (owner, mode, …), detects the content mismatch, but upon writing fails because it wants to create-and-swap a temporary file:
Notice: /Stage[main]/MyModule::Resource/File[/sys/fs/cgroup/system.slice/existing-group/cpu.max]/content:
--- /sys/fs/cgroup/system.slice/existing-group/cpu.max 2025-06-24 19:48:16.022215949 +0200
+++ /tmp/puppet-file20250624-212062-ico87p 2025-06-24 19:50:59.628083549 +0200
@@ -1 +1 @@
-max 100000
+19200000 100000
Error: Permission denied @ rb_sysopen - /sys/fs/cgroup/system.slice/existing-group/cpu.max20250624-212062-1tugk2r
Error: /Stage[main]/MyModule::Resource/File[/sys/fs/cgroup/system.slice/existing-group/cpu.max]/content: change from '{sha256}04afe0d058a8924a172509ae2f711347aca93cbca3879c64bd8d3d1b2e559ee7' to '{sha256}c987d0dfaf6ae53cd6df8e04c69756e356a924577c893a747088be76fb78da67' failed: Permission denied @ rb_sysopen - /sys/fs/cgroup/system.slice/existing-group/cpu.max20250624-212062-1tugk2r
It is clear to me why this fails (the cgroup representation is not a real, writeable directory), but not how to approach this instead.
An approach based on File
resources feels like it should be best, but if you can't get that to work then there are other alternatives. Among them,
Better: Write a custom resource type. The provider implementation you create for it will be written in Ruby, and you will have substantially complete control of how it does its work.
Quick and dirty: Use an Exec
resource. In this case, everything will remain in your Puppet manifests, and the main work will be implemented as shell commands. This is a little quirky and it has some limitations, but it's often good for a jerry-rig prototype, and occasionally it makes sense for a permanent solution.