Skip to content

Commit 4549f98

Browse files
author
Mahmood Ali
committed
Support Nomad memory oversubscription
Nomad 1.1.0 introduced Memory Oversubscription: Now, the NomadResources.Memory struct contains a `MemoryMaxMB` which, if set, specifies a hard limit on the task. The `MemoryMB` in such case is to be interpreted as a soft limit.
1 parent 763249f commit 4549f98

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

containerd/containerd.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type ContainerConfig struct {
4545
AllocDirDest string
4646
Env []string
4747
MemoryLimit int64
48+
MemoryHardLimit int64
4849
CPUShares int64
4950
}
5051

@@ -196,7 +197,7 @@ func (d *Driver) createContainer(containerConfig *ContainerConfig, config *TaskC
196197
opts = append(opts, oci.WithEnv(containerConfig.Env))
197198

198199
// Set cgroups memory limit.
199-
opts = append(opts, oci.WithMemoryLimit(uint64(containerConfig.MemoryLimit)))
200+
opts = append(opts, WithMemoryLimits(containerConfig.MemoryLimit, containerConfig.MemoryHardLimit))
200201

201202
// Set CPU Shares.
202203
opts = append(opts, oci.WithCPUShares(uint64(containerConfig.CPUShares)))

containerd/driver.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,8 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
454454

455455
// memory and cpu are coming from the resources stanza of the nomad job.
456456
// https://www.nomadproject.io/docs/job-specification/resources
457-
containerConfig.MemoryLimit = cfg.Resources.LinuxResources.MemoryLimitBytes
457+
containerConfig.MemoryLimit = cfg.Resources.NomadResources.Memory.MemoryMB * 1024 * 1024
458+
containerConfig.MemoryHardLimit = cfg.Resources.NomadResources.Memory.MemoryMaxMB * 1024 * 1024
458459
containerConfig.CPUShares = cfg.Resources.LinuxResources.CPUShares
459460

460461
container, err := d.createContainer(&containerConfig, &driverConfig)

containerd/utils.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,28 @@ func WithSysctls(sysctls map[string]string) oci.SpecOpts {
6060
return nil
6161
}
6262
}
63+
64+
// WithMemoryLimits accepts soft (`memory`) and hard (`memory_max`) limits as parameters and set the desired
65+
// limits. With `Nomad<1.1.0` releases, soft (`memory`) will act as a hard limit, and if the container process exceeds
66+
// that limit, it will be OOM'ed. With `Nomad>=1.1.0` releases, users can over-provision using `soft` and `hard`
67+
// limits. The container process will only get OOM'ed if the hard limit is exceeded.
68+
func WithMemoryLimits(soft, hard int64) oci.SpecOpts {
69+
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
70+
if s.Linux != nil {
71+
if s.Linux.Resources == nil {
72+
s.Linux.Resources = &specs.LinuxResources{}
73+
}
74+
if s.Linux.Resources.Memory == nil {
75+
s.Linux.Resources.Memory = &specs.LinuxMemory{}
76+
}
77+
78+
if hard > 0 {
79+
s.Linux.Resources.Memory.Limit = &hard
80+
s.Linux.Resources.Memory.Reservation = &soft
81+
} else {
82+
s.Linux.Resources.Memory.Limit = &soft
83+
}
84+
}
85+
return nil
86+
}
87+
}

0 commit comments

Comments
 (0)