daemon: support per-device blkio throttle in ContainerUpdate#52651
Conversation
0ce2026 to
8a4a5ca
Compare
|
Note: I am able and willing to create the associated PR in the CLI if this is merged. |
vvoland
left a comment
There was a problem hiding this comment.
Thanks, I think this makes sense!
7b20ea9 to
49f984d
Compare
|
Hey @vvoland I've applied the initialization pattern based on your review, let me know if it needs further changes! |
|
Wondering if we should gate this by API version.. However, these fields are already present, it's just the daemon which hasn't been respecting them, so I think it's fine to treat this as a daemon enhancement rather than a new API addition.. @thaJeztah @corhere @cpuguy83 @tianon WDYT? |
|
@acouvreur Could you also add matching |
I believe this will be in the dedicated https://github.com/docker/cli repository right ? I can open up a PR there if you can confirm that's the case. Also, is there anything I need to do for you to make this easier to merge ? Are the CI failure expected here ? |
| assert.NilError(t, unix.Stat("/", &st), "stat /") | ||
|
|
||
| maj := unix.Major(st.Dev) | ||
| min := unix.Minor(st.Dev) |
There was a problem hiding this comment.
Linter didn't like this because min shadows the min() builtin
|
Yes it needs a change in https://github.com/docker/cli Also, we chatted a bit with @thaJeztah and actually we think it should actually be an API version gated change. Presence of these field in the API field was only a result of sharing structs, but wasn't explcitly called out in the API changelog or the initial API doc: https://github.com/moby/moby/blob/master/api/docs/v1.22.md#update-a-container |
Do you need me to do anything ? I will submit the PR to docker/cli |
|
CLI PR created: docker/cli#7031 But I did not update the moby/moby library to this specific branch version of the library, so even though the parameters are there, they will be ignored until this is merged. |
Closes docker#3325 Related to moby/moby#52651 Signed-off-by: Alexis Couvreur <[email protected]>
Closes docker#3325 Related to moby/moby#52651 Signed-off-by: Alexis Couvreur <[email protected]>
Yes, this needs an API version gate against current version (1.55) moby/daemon/server/router/container/container_routes.go Lines 519 to 520 in 2046453 |
d23e941 to
231ceba
Compare
231ceba to
d7c326b
Compare
| version := httputils.VersionFromContext(ctx) | ||
| if versions.LessThan(version, "1.40") { | ||
| updateConfig.PidsLimit = nil | ||
| } | ||
| if versions.LessThan(version, "1.55") { | ||
| updateConfig.BlkioWeightDevice = nil | ||
| updateConfig.BlkioDeviceReadBps = nil | ||
| updateConfig.BlkioDeviceWriteBps = nil | ||
| updateConfig.BlkioDeviceReadIOps = nil | ||
| updateConfig.BlkioDeviceWriteIOps = nil | ||
| } |
There was a problem hiding this comment.
No need to change, but if we want to optimise, we could;
version := httputils.VersionFromContext(ctx)
if versions.LessThan(version, "1.55") {
if versions.LessThan(version, "1.40") {
updateConfig.PidsLimit = nil
}
updateConfig.BlkioWeightDevice = nil
updateConfig.BlkioDeviceReadBps = nil
updateConfig.BlkioDeviceWriteBps = nil
updateConfig.BlkioDeviceReadIOps = nil
updateConfig.BlkioDeviceWriteIOps = nil
}| if len(resources.BlkioWeightDevice) > 0 { | ||
| cResources.BlkioWeightDevice = resources.BlkioWeightDevice | ||
| } | ||
| if len(resources.BlkioDeviceReadBps) > 0 { | ||
| cResources.BlkioDeviceReadBps = resources.BlkioDeviceReadBps | ||
| } | ||
| if len(resources.BlkioDeviceWriteBps) > 0 { | ||
| cResources.BlkioDeviceWriteBps = resources.BlkioDeviceWriteBps | ||
| } | ||
| if len(resources.BlkioDeviceReadIOps) > 0 { | ||
| cResources.BlkioDeviceReadIOps = resources.BlkioDeviceReadIOps | ||
| } | ||
| if len(resources.BlkioDeviceWriteIOps) > 0 { | ||
| cResources.BlkioDeviceWriteIOps = resources.BlkioDeviceWriteIOps | ||
| } |
There was a problem hiding this comment.
One thing to look at is if we need a way to reset these (and if that's possible); I know we've had similar cases for some other properties.
Possibly for this that could mean to distinguish and actual nil from a zero-length slice; where the latter would mean "reset".
I think that's somewhat similar to
moby/daemon/server/router/container/container_routes.go
Lines 523 to 529 in 29f6cd5
There was a problem hiding this comment.
Yeah unfortunately that's pre existing issue with this endpoint for other fields, see my comments here: #52651 (comment)
But yeah In this case we could indeed handle nil differently.. I updated the PR, let me know what you think.
d7c326b to
f6362f1
Compare
| ## v1.55 API changes | ||
|
|
||
| * `POST /containers/{id}/update` now supports per-device blkio resource |
There was a problem hiding this comment.
This will conflict with #52636, so we can do a quick rebase with "validate-only" after CI completes and the other PR is merged
The POST /containers/{id}/update API accepts BlkioWeightDevice,
BlkioDeviceReadBps, BlkioDeviceWriteBps, BlkioDeviceReadIOps, and
BlkioDeviceWriteIOps in its Resources body, but these five fields were
silently ignored when updating a running container.
The root cause was in toContainerdResources (daemon/update_linux.go):
only BlkioWeight was mapped into specs.LinuxBlockIO; the per-device
fields were never converted, so tsk.UpdateResources never wrote to
cgroupv2 io.max or the cgroupv1 blkio throttle files.
Fix by calling the existing getBlkioWeightDevices and
getBlkioThrottleDevices helpers (already used in oci_linux.go for
container creation) to populate all five fields. The function signature
is extended to return an error so that stat(2) failures on invalid
device paths are surfaced to the caller instead of being silently
dropped.
The API makes distinction between nil and zero-length slices while
doing. A nil per-device blkio field means the caller did not request an
update for that setting, while a non-nil empty slice means the caller
explicitly requested the setting to be cleared.
The Windows stub is updated to match the new signature.
Signed-off-by: Alexis Couvreur <[email protected]>
Signed-off-by: Paweł Gronowski <[email protected]>
ContainerUpdate only starts applying per-device blkio settings in the current API version. The fields existed in the Go request type before that because it shares `container.Resources` with other endpoints, but they were not documented as supported for container update and older daemons ignored them. Clear these fields when handling requests for older API versions so clients pinned to those versions keep the previous behavior, while v1.55 clients can use the newly supported fields. Signed-off-by: Paweł Gronowski <[email protected]>
f6362f1 to
dc97f25
Compare
|
Thank you all! 🥳🥳 |
Disclaimer: This was done with the help of Claude Sonnet 4.6.
But I've reviewed and tested manually the change.
Description
POST /containers/{id}/updateacceptsBlkioWeightDevice,BlkioDeviceReadBps,BlkioDeviceWriteBps,BlkioDeviceReadIOps, andBlkioDeviceWriteIOpsin itsResourcesbody, but these five fields were silently ignored — the API returns 200 OK but nothing is written to cgroupv2io.maxor the cgroupv1 blkio throttle files.Fixes #52650.
Root cause
toContainerdResourcesindaemon/update_linux.goonly mappedBlkioWeightintospecs.LinuxBlockIO; the per-device fields were never converted sotsk.UpdateResourceshad nothing to apply:Fix
Call the existing
getBlkioWeightDevicesandgetBlkioThrottleDeviceshelpers (already used inoci_linux.gofor container creation) to populate all five fields. The function signature gains anerrorreturn so thatstat(2)failures on invalid device paths are surfaced to the caller rather than being silently dropped.The Windows stub is updated to match the new signature.
Testing
Verified with a manual test against a running container on cgroupv2 (Colima / Ubuntu 24.04):