dea870f4ea
Many of the fields in LinuxResources struct are pointers to scalars for some reason, presumably to differentiate between set-to-zero and unset when unmarshaling from JSON, despite zero being outside the acceptable range for the corresponding kernel tunables. When creating the OCI spec for a container, the daemon sets the container's OCI spec CPUShares and BlkioWeight parameters to zero when the corresponding Docker container configuration values are zero, signifying unset, despite the minimum acceptable value for CPUShares being two, and BlkioWeight ten. This has gone unnoticed as runC does not distingiush set-to-zero from unset as it also uses zero internally to represent unset for those fields. However, kata-containers v3.2.0-alpha.3 tries to apply the explicit-zero resource parameters to the container, exactly as instructed, and fails loudly. The OCI runtime-spec is silent on how the runtime should handle the case when those parameters are explicitly set to out-of-range values and kata's behaviour is not unreasonable, so the daemon must therefore be in the wrong. Translate unset values in the Docker container's resources HostConfig to omit the corresponding fields in the container's OCI spec when starting and updating a container in order to maximize compatibility with runtimes. Signed-off-by: Cory Snider <csnider@mirantis.com>
75 lines
1.6 KiB
Go
75 lines
1.6 KiB
Go
package daemon // import "github.com/docker/docker/daemon"
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/docker/docker/api/types/container"
|
|
libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
|
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
)
|
|
|
|
func toContainerdResources(resources container.Resources) *libcontainerdtypes.Resources {
|
|
var r libcontainerdtypes.Resources
|
|
|
|
if resources.BlkioWeight != 0 {
|
|
r.BlockIO = &specs.LinuxBlockIO{
|
|
Weight: &resources.BlkioWeight,
|
|
}
|
|
}
|
|
|
|
cpu := specs.LinuxCPU{
|
|
Cpus: resources.CpusetCpus,
|
|
Mems: resources.CpusetMems,
|
|
}
|
|
if resources.CPUShares != 0 {
|
|
shares := uint64(resources.CPUShares)
|
|
cpu.Shares = &shares
|
|
}
|
|
|
|
var (
|
|
period uint64
|
|
quota int64
|
|
)
|
|
if resources.NanoCPUs != 0 {
|
|
period = uint64(100 * time.Millisecond / time.Microsecond)
|
|
quota = resources.NanoCPUs * int64(period) / 1e9
|
|
}
|
|
if quota == 0 && resources.CPUQuota != 0 {
|
|
quota = resources.CPUQuota
|
|
}
|
|
if period == 0 && resources.CPUPeriod != 0 {
|
|
period = uint64(resources.CPUPeriod)
|
|
}
|
|
|
|
if period != 0 {
|
|
cpu.Period = &period
|
|
}
|
|
if quota != 0 {
|
|
cpu.Quota = "a
|
|
}
|
|
|
|
if cpu != (specs.LinuxCPU{}) {
|
|
r.CPU = &cpu
|
|
}
|
|
|
|
var memory specs.LinuxMemory
|
|
if resources.Memory != 0 {
|
|
memory.Limit = &resources.Memory
|
|
}
|
|
if resources.MemoryReservation != 0 {
|
|
memory.Reservation = &resources.MemoryReservation
|
|
}
|
|
if resources.KernelMemory != 0 {
|
|
memory.Kernel = &resources.KernelMemory
|
|
}
|
|
if resources.MemorySwap > 0 {
|
|
memory.Swap = &resources.MemorySwap
|
|
}
|
|
|
|
if memory != (specs.LinuxMemory{}) {
|
|
r.Memory = &memory
|
|
}
|
|
|
|
r.Pids = getPidsLimit(resources)
|
|
return &r
|
|
}
|