opencontainers / opencontainers/runc
cgroup2: confusing error when `linux.resources.cpu.shares=1`
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 13.5k
- Forks
- 2.3k
- Avg merge
- 2d 8h
- Merged PRs (30d)
- 30
Description
When passed a spec with an out-of-range CPU shares value, runc will fail to start the container and reports an error message. On a cgroup1 host the returned error message makes it clear which part of the container config is the problem.
minimum allowed cpu-shares is 2
However, on a cgroup2 host, the error message makes no mention of CPU shares.
failed to write "70369281052672": write /sys/fs/cgroup/.../cpu.weight: numerical result out of range
$ docker run --rm --cpu-shares 1 hello-world
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error setting cgroup config for procHooks process: failed to write "70369281052672": write /sys/fs/cgroup/docker/4139b57a20695ff4f62dda799b1c4052791f59bac4611534cb3a213a3e446add/cpu.weight: numerical result out of range: unknown.
It is not at all obvious that a CPU weight of 70369281052672 has anything to do with "shares": 1 in the container config.
Expected: runc returns an error message which flags the CPU shares configuration as being out of range, irrespective of the host system's configuration.
Why this is a runc bug
- According to the runtime-spec, it is valid for
sharesto be set to any value within the range of a uint64, [0, 2^32). Therefore it is not a bug in whatever produces the spec to set the CPU shares to 1. - runc (libcontainer) is the party responsible for mapping the cpu-shares value in the container config to a cpu-weight value for cgroups v2.
https://github.com/opencontainers/runc/blob/8d90e3dba696ac787ee64de4445517ddf1063b04/libcontainer/specconv/spec_linux.go#L826-L831
https://github.com/opencontainers/cgroups/blob/9657f5a18b8d60a0f39fbb34d0cb7771e28e6278/fs2/cpu.go#L30 - The
ConvertCPUSharesToCgroupV2Valuefunction is documented to only take inputs in the range [2, 262144]. Calling the function with values outside that range is therefore a bug in the caller, by definition.
https://github.com/opencontainers/cgroups/blob/9657f5a18b8d60a0f39fbb34d0cb7771e28e6278/utils.go#L416-L426 - runc calls the conversion function without validating that its argument is within the valid range. Therefore the bug is in runc for not validating. QED.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read libcontainer/specconv/spec_linux.go around the CPU shares conversion and the cgroups fs2/cpu.go and utils.go conversion functions linked in the issue. Trace how shares=1 reaches the cgroup v2 conversion without validation. Done means an out-of-range shares value produces an error that identifies CPU shares rather than only the cpu.weight write failure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, linux
- Domain
- cli, operating-systems
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100