Skip to content

Give a container the swap it asks for - #2182

Closed
MayCXC wants to merge 3 commits into
apple:mainfrom
MayCXC:cli-swap
Closed

Give a container the swap it asks for#2182
MayCXC wants to merge 3 commits into
apple:mainfrom
MayCXC:cli-swap

Conversation

@MayCXC

@MayCXC MayCXC commented Aug 27, 2026

Copy link
Copy Markdown

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Motivation and Context

Closes #2181.

A container whose workload exceeds its memory limit 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 takes a size on the command line, kept on the container's resources beside the memory limit it plays against, and the area is made from it at bootstrap: 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. 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. A container that asks for none gets none, which is what one expected to stay within its memory wants. The area 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 swap 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.

Swap was also the only container resource a user could ask for but not configure a default for, so [container] swap sits beside cpus and memory and resolves the way they do, defaulting to zero.

Dependency and Merge Order

The guest half is in Containerization: apple/containerization#878, discussed in apple/containerization#877. That must land, and this repository's Containerization dependency be advanced past it, before this can build. This branch targets stock apple/container:main and its diff is the CLI, configuration, and runtime-service halves alone.

Testing

  • Tested locally
  • Added/updated tests
  • Added/updated docs

Unit coverage for the configuration resolution and the size arithmetic. Verified end to end against a Containerization checkout carrying apple/containerization#878: a container given --memory 128m --swap 256m survives a workload that the same container without swap is killed for, and the bundle's swap file gives blocks back as the guest stops using them.

Integration suite: 397 passed. Unit suite: 772 passed. make fmt, make check clean.

MayCXC added 3 commits August 27, 2026 20:16
A container whose workload exceeds its memory limit 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.

Take a size on the command line, keep it on the container's resources beside
the memory limit it plays against, and make the area from it at bootstrap:
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.

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. A
container that asks for none gets none, which is what one expected to stay
within its memory wants.

The area holds nothing that outlives the container, so it is made afresh at
each bootstrap and the host is told not to synchronize it.
The guest reaches the swap 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. A sparse backing costs the host
only the pages the guest has actually swapped out and gives them back
on discard.
https://github.com/torvalds/linux/blob/master/mm/swapfile.c
Swap was the only container resource a user could ask for but not
configure a default for: --swap existed with nothing behind it, while
--cpus and --memory both fall back to their [container] keys. Add
[container] swap, defaulting to zero so a container still gets no area
unless one is asked for, and resolve it the way the other two resolve.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Request]: --swap and a [container] swap default, so a container over its memory limit is reclaimed rather than killed

2 participants