Describe the feature
Give container run and container create a --swap option, and [container] swap in the configuration to default it, so a container whose workload exceeds its memory limit is reclaimed to a swap area rather than killed.
Motivation
A container that goes over --memory today meets the out of memory killer, with nothing between the two. The runtime it sits on can hand the guest a swap area to reclaim to instead, but nothing here asks for one.
Swap is also the only container resource with no configurable default: --cpus and --memory both fall back to their [container] keys, so a --swap added without [container] swap beside it would be the odd one out.
Shape I have implemented and would propose:
--swap takes a size, kept on the container's resources beside the memory limit it plays against. The size counts swap alone rather than the memory-and-swap total the runtime spec carries, so it reads against --memory rather than including it.
- The area is made at bootstrap as a raw block file in the container's own bundle, alongside the root filesystem, which the guest agent writes a swap header to and enables. It holds nothing that outlives the container, so it is made afresh at each bootstrap and the host is told not to synchronize it.
- The backing file is sparse. The guest reaches the area as a block device, which the kernel takes as a single extent without consulting the host's layout, so the hole-free requirement that binds a swap file inside the guest does not bind the host file backing the device: https://github.com/torvalds/linux/blob/master/mm/swapfile.c . Sparse backing costs the host only the pages the guest has actually swapped out and gives them back on discard.
[container] swap defaults to zero, so a container still gets no area unless one is asked for, and resolves the way cpus and memory resolve.
Alternatives considered
Leaving the limit as a hard wall and letting the OOM killer act: that is today's behaviour, and it is the right default, which is why the default here stays zero.
Dependency
The guest half lives in Containerization: apple/containerization#877 for the design discussion and apple/containerization#878 for the implementation. A --swap here needs that to be in the runtime the CLI sits on.
Code of Conduct
Describe the feature
Give
container runandcontainer createa--swapoption, and[container] swapin the configuration to default it, so a container whose workload exceeds its memory limit is reclaimed to a swap area rather than killed.Motivation
A container that goes over
--memorytoday meets the out of memory killer, with nothing between the two. The runtime it sits on can hand the guest a swap area to reclaim to instead, but nothing here asks for one.Swap is also the only container resource with no configurable default:
--cpusand--memoryboth fall back to their[container]keys, so a--swapadded without[container] swapbeside it would be the odd one out.Shape I have implemented and would propose:
--swaptakes a size, kept on the container's resources beside the memory limit it plays against. The size counts swap alone rather than the memory-and-swap total the runtime spec carries, so it reads against--memoryrather than including it.[container] swapdefaults to zero, so a container still gets no area unless one is asked for, and resolves the waycpusandmemoryresolve.Alternatives considered
Leaving the limit as a hard wall and letting the OOM killer act: that is today's behaviour, and it is the right default, which is why the default here stays zero.
Dependency
The guest half lives in Containerization: apple/containerization#877 for the design discussion and apple/containerization#878 for the implementation. A
--swaphere needs that to be in the runtime the CLI sits on.Code of Conduct