client: do not disable memory swappiness if kernel does not support it (#17625)

* client: do not disable memory swappiness if kernel does not support it

This PR adds a workaround for very old Linux kernels which do not support
the memory swappiness interface file. Normally we write a "0" to the file
to explicitly disable swap. In the case the kernel does not support it,
give libcontainer a nil value so it does not write anything.

Fixes #17448

* client: detect swappiness by writing to the file

* fixup changelog

Co-authored-by: James Rasell <jrasell@users.noreply.github.com>

---------

Co-authored-by: James Rasell <jrasell@users.noreply.github.com>
This commit is contained in:
Seth Hoenig 2023-06-22 09:36:31 -05:00 committed by GitHub
parent 9f5c02d947
commit 5138c5b99e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 3 deletions

3
.changelog/17625.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
client: Fixed a bug where Nomad incorrectly wrote to memory swappiness cgroup on old kernels
```

View File

@ -11,6 +11,7 @@ import (
"path/filepath"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/nomad/helper/pointer"
"github.com/hashicorp/nomad/helper/uuid"
"github.com/opencontainers/runc/libcontainer/cgroups"
lcc "github.com/opencontainers/runc/libcontainer/configs"
@ -148,3 +149,26 @@ func CopyCpuset(source, destination string) error {
return nil
}
// MaybeDisableMemorySwappiness will disable memory swappiness, if that controller
// is available. Always the case for cgroups v2, but is not always the case on
// very old kernels with cgroups v1.
func MaybeDisableMemorySwappiness() *uint64 {
bypass := (*uint64)(nil)
zero := pointer.Of[uint64](0)
// cgroups v2 always set zero
if UseV2 {
return zero
}
// cgroups v1 detect if swappiness is supported by attempting to write to
// the nomad parent cgroup swappiness interface
e := &editor{fromRoot: "memory/nomad"}
err := e.write("memory.swappiness", "0")
if err != nil {
return bypass
}
return zero
}

View File

@ -130,3 +130,12 @@ func TestUtil_CopyCpuset(t *testing.T) {
require.Equal(t, "0-1", strings.TrimSpace(value))
})
}
func TestUtil_MaybeDisableMemorySwappiness(t *testing.T) {
ci.Parallel(t)
// will return 0 on any reasonable kernel (both cgroups v1 and v2)
value := MaybeDisableMemorySwappiness()
must.NotNil(t, value)
must.Eq(t, 0, *value)
}

View File

@ -689,9 +689,8 @@ func configureCgroups(cfg *lconfigs.Config, command *ExecCommand) error {
cfg.Cgroups.Resources.Memory = memHard * 1024 * 1024
cfg.Cgroups.Resources.MemoryReservation = memSoft * 1024 * 1024
// Disable swap to avoid issues on the machine
var memSwappiness uint64
cfg.Cgroups.Resources.MemorySwappiness = &memSwappiness
// Disable swap if possible, to avoid issues on the machine
cfg.Cgroups.Resources.MemorySwappiness = cgutil.MaybeDisableMemorySwappiness()
}
cpuShares := res.Cpu.CpuShares