Skip to content

Commit

Permalink
expose NOMAD_MEMORY_MAX_LIMIT env var (#10514)
Browse files Browse the repository at this point in the history
Follow up to memory oversubscription - expose an env-var to indicate when memory oversubscription is enabled and what the limit is.

This will be helpful for setting hints to app for memory management.

Co-authored-by: Seth Hoenig <shoenig@hashicorp.com>
  • Loading branch information
Mahmood Ali and shoenig authored May 5, 2021
1 parent e15d504 commit fcfa578
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 11 deletions.
10 changes: 10 additions & 0 deletions client/taskenv/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ const (
// MemLimit is the environment variable with the tasks memory limit in MBs.
MemLimit = "NOMAD_MEMORY_LIMIT"

// MemMaxLimit is the environment variable with the tasks maximum memory limit in MBs.
MemMaxLimit = "NOMAD_MEMORY_MAX_LIMIT"

// CpuLimit is the environment variable with the tasks CPU limit in MHz.
CpuLimit = "NOMAD_CPU_LIMIT"

Expand Down Expand Up @@ -393,6 +396,7 @@ type Builder struct {

cpuLimit int64
memLimit int64
memMaxLimit int64
taskName string
allocIndex int
datacenter string
Expand Down Expand Up @@ -479,6 +483,9 @@ func (b *Builder) buildEnv(allocDir, localDir, secretsDir string,
if b.memLimit != 0 {
envMap[MemLimit] = strconv.FormatInt(b.memLimit, 10)
}
if b.memMaxLimit != 0 {
envMap[MemMaxLimit] = strconv.FormatInt(b.memMaxLimit, 10)
}
if b.cpuLimit != 0 {
envMap[CpuLimit] = strconv.FormatInt(b.cpuLimit, 10)
}
Expand Down Expand Up @@ -667,9 +674,11 @@ func (b *Builder) setTask(task *structs.Task) *Builder {
// COMPAT(0.11): Remove in 0.11
if task.Resources == nil {
b.memLimit = 0
b.memMaxLimit = 0
b.cpuLimit = 0
} else {
b.memLimit = int64(task.Resources.MemoryMB)
b.memMaxLimit = int64(task.Resources.MemoryMaxMB)
b.cpuLimit = int64(task.Resources.CPU)
}
return b
Expand Down Expand Up @@ -722,6 +731,7 @@ func (b *Builder) setAlloc(alloc *structs.Allocation) *Builder {
if tr, ok := alloc.AllocatedResources.Tasks[b.taskName]; ok {
b.cpuLimit = tr.Cpu.CpuShares
b.memLimit = tr.Memory.MemoryMB
b.memMaxLimit = tr.Memory.MemoryMaxMB

// Copy networks to prevent sharing
b.networks = make([]*structs.NetworkResource, len(tr.Networks))
Expand Down
21 changes: 15 additions & 6 deletions client/taskenv/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,21 @@ func TestEnvironment_AsList(t *testing.T) {
}
a := mock.Alloc()
a.Job.ParentID = fmt.Sprintf("mock-parent-service-%s", uuid.Generate())
a.AllocatedResources.Tasks["web"].Networks[0] = &structs.NetworkResource{
Device: "eth0",
IP: "127.0.0.1",
ReservedPorts: []structs.Port{{Label: "https", Value: 8080}},
MBits: 50,
DynamicPorts: []structs.Port{{Label: "http", Value: 80}},
a.AllocatedResources.Tasks["web"] = &structs.AllocatedTaskResources{
Cpu: structs.AllocatedCpuResources{CpuShares: 500},
Memory: structs.AllocatedMemoryResources{
MemoryMB: 256,
MemoryMaxMB: 512,
},
Networks: []*structs.NetworkResource{{
Device: "eth0",
IP: "127.0.0.1",
ReservedPorts: []structs.Port{{Label: "https", Value: 8080}},
MBits: 50,
DynamicPorts: []structs.Port{{Label: "http", Value: 80}},
}},
}

a.AllocatedResources.Tasks["ssh"] = &structs.AllocatedTaskResources{
Networks: []*structs.NetworkResource{
{
Expand Down Expand Up @@ -196,6 +204,7 @@ func TestEnvironment_AsList(t *testing.T) {
"NOMAD_NAMESPACE=not-default",
"NOMAD_REGION=global",
"NOMAD_MEMORY_LIMIT=256",
"NOMAD_MEMORY_MAX_LIMIT=512",
"NOMAD_META_ELB_CHECK_INTERVAL=30s",
"NOMAD_META_ELB_CHECK_MIN=3",
"NOMAD_META_ELB_CHECK_TYPE=http",
Expand Down
10 changes: 5 additions & 5 deletions website/content/docs/runtime/environment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ tell you which resources have been allocated after evaluation and placement.

### CPU and Memory

Nomad will pass CPU and memory limits to your job as `NOMAD_CPU_LIMIT` and
`NOMAD_MEMORY_LIMIT`. Your task should use these values to adapt its behavior to
fit inside the resource allocation that nomad provides. For example, you can use
the memory limit to inform how large your in-process cache should be, or to
decide when to flush buffers to disk.
Nomad will pass CPU and memory limits to your job as `NOMAD_CPU_LIMIT`,
`NOMAD_MEMORY_LIMIT`, and `NOMAD_MEMORY_MAX_LIMIT`. Your task should use these
values to adapt its behavior to fit inside the resource allocation that nomad
provides. For example, you can use the memory limit to inform how large your
in-process cache should be, or to decide when to flush buffers to disk.

Both CPU and memory are presented as integers. The unit for CPU limit is
`1024 = 1GHz`. The unit for memory is `1 = 1 megabyte`.
Expand Down
9 changes: 9 additions & 0 deletions website/content/partials/envvars.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@
</td>
<td>Memory limit in MB for the task</td>
</tr>
<tr>
<td>
<code>NOMAD_MEMORY_MAX_LIMIT</code>
</td>
<td>
The maximum memory limit the task may use if client has excess memory
capacity, in MB. Omitted if task isn't configured with memory oversubscription.
</td>
</tr>
<tr>
<td>
<code>NOMAD_CPU_LIMIT</code>
Expand Down

0 comments on commit fcfa578

Please sign in to comment.