Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nomad client fails to start a job #17448

Closed
akamensky opened this issue Jun 7, 2023 · 10 comments · Fixed by #17625
Closed

Nomad client fails to start a job #17448

akamensky opened this issue Jun 7, 2023 · 10 comments · Fixed by #17625
Assignees
Labels
stage/accepted Confirmed, and intend to work on. No timeline committment though. theme/cgroups cgroups issues type/bug
Milestone

Comments

@akamensky
Copy link

akamensky commented Jun 7, 2023

Nomad version

Installed from official RPM repo

Nomad v1.5.6
BuildDate 2023-05-19T18:26:13Z
Revision 8af70885c02ab921dedbdf6bc406a1e886866f80

Operating system and Environment details

$ cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

$ uname -a
Linux hostname.redacted 3.10.0-123.20.1.el7.x86_64 #1 SMP Thu Jan 29 18:05:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ cat /proc/cmdline 
BOOT_IMAGE=/vmlinuz-3.10.0-123.20.1.el7.x86_64 root=/dev/mapper/VolGroup-lv_root ro nomodeset rd_NO_PLYMOUTH rd.lvm.lv=VolGroup/lv_swap vconsole.keymap=us plymouth.enable=0 rd.lvm.lv=VolGroup/lv_root crashkernel=auto vconsole.font=latarcyrheb-sun16 rhgb quiet LANG=en_US.UTF-8 rcu_nocbs=1,3 nohz_full=1,3 intel_pstate=disable

$ cat /etc/nomad.d/nomad.json 
{
  "data_dir": "/data/nomad",
  "bind_addr": "0.0.0.0",
  "datacenter": "perf",
  "region": "hk",
  "server": {
    "enabled": false,
  },
  "client": {
    "enabled": true,
    "chroot_env": {
      "/bin": "/bin",
      "/etc": "/etc",
      "/lib": "/lib",
      "/lib32": "/lib32",
      "/lib64": "/lib64",
      "/run/resolvconf": "/run/resolvconf",
      "/sbin": "/sbin",
      "/usr": "/usr"
    }
  },
  "consul": {
    "server_service_name": "nomad-server",
    "client_service_name": "nomad-client",
    "address": "127.0.0.1:8500",
    "auto_advertise": true,
    "client_auto_join": true,
    "server_auto_join": true
  }
}

Issue

Submitting job fails with:

Jun 07 12:48:08 hostname.redacted nomad[7485]: 2023-06-07T12:48:08.590+0800 [INFO]  client.alloc_runner.task_runner: Task event: alloc_id=c6998dae-aa8a-f030-462b-e31aa2db2233 task=sleep type="Driver Failure" msg="failed to launch command with executor: rpc error: code = Unknown desc = unable to start container process: error during container init: error setting cgroup config for procHooks process: failed to write \"0\": write /sys/fs/cgroup/memory/nomad/2f4cdd07-1faa-9b22-178c-b5c9b1dadafd/memory.swappiness: invalid argument" failed=false
Jun 07 12:48:08 hostname.redacted nomad[7485]: 2023-06-07T12:48:08.692+0800 [ERROR] client.alloc_runner.task_runner: running driver failed: alloc_id=c6998dae-aa8a-f030-462b-e31aa2db2233 task=sleep error="failed to launch command with executor: rpc error: code = Unknown desc = unable to start container process: error during container init: error setting cgroup config for procHooks process: failed to write \"0\": write /sys/fs/cgroup/memory/nomad/2f4cdd07-1faa-9b22-178c-b5c9b1dadafd/memory.swappiness: invalid argument"

Reproduction steps

  • Try to start a job in an env as described above

Expected Result

  • Job started

Actual Result

  • Job allocation fails

Job file (if appropriate)

job "hello-world" {
  datacenters = ["perf"]
  group "servers" {
    task "sleep" {
      driver = "exec"
      config {
        command = "sleep"
        args    = ["infinity"]
      }
    }
  }
}

Nomad Server logs (if appropriate)

N/A

Nomad Client logs (if appropriate)

See above

@shoenig
Copy link
Member

shoenig commented Jun 7, 2023

@akamensky can you ensure cgroups are enabled on the node?

https://developer.hashicorp.com/nomad/docs/drivers/exec#resource-isolation

@akamensky
Copy link
Author

akamensky commented Jun 7, 2023

@shoenig cgroups are enabled. As you can see from the logs it fails to set swappiness to 0 in cgroup. If I recall correctly Centos 7 kernel version just doesn't have separate swappiness for cgroup it is inherited from the main namespace. (Hence the Docker versions that can run on C7.x don't have that either as well as any other sysctl overrides).

$ awk '{print $1 " " $4}' /proc/cgroups
#subsys_name enabled
cpuset 1
cpu 1
cpuacct 1
memory 1
devices 1
freezer 1
net_cls 1
blkio 1
perf_event 1
hugetlb 1

@akamensky
Copy link
Author

@shoenig sorry to ping you on this, but do you have any feedback? This is a make or break issue for us as we have to run older systems in our infra. If we have no workaround or fix, then we would have to abandon Nomad.

@shoenig
Copy link
Member

shoenig commented Jun 15, 2023

It might be possible to provide a fix for this. Looking at the libcontainer implementation it should bypass writing to the swappiness interface file if we pass in a nil Resources.Swappiness. Currently we hardcode a Zero value struct here indicating swappiness should be disabled.

@akamensky are you able to test out such a fix yourself? We don't have any machines this old in our CI systems.

@akamensky
Copy link
Author

akamensky commented Jun 16, 2023

@shoenig I would be able to test if you can provide compiled binary or at least a patch and build instructions.

@tgross tgross added this to Needs Triage in Nomad - Community Issues Triage via automation Jun 20, 2023
@tgross tgross moved this from Needs Triage to Triaging in Nomad - Community Issues Triage Jun 20, 2023
shoenig added a commit that referenced this issue Jun 20, 2023
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
@shoenig shoenig self-assigned this Jun 20, 2023
@shoenig shoenig moved this from Triaging to In Progress in Nomad - Community Issues Triage Jun 20, 2023
@shoenig shoenig added the stage/accepted Confirmed, and intend to work on. No timeline committment though. label Jun 20, 2023
shoenig added a commit that referenced this issue Jun 20, 2023
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
@shoenig
Copy link
Member

shoenig commented Jun 20, 2023

@akamensky The PR #17625 contains a fix I think should work, but like I mentioned we simply don't have kernels that old handy to test with.

Probably the easiest way to check yourself would be to run the test case.

  1. Install Go 1.20
  2. Install make, git, gcc
  3. Clone nomad, checkout branch in the PR
  4. cd client/lib/cgutil
  5. Run go test -v -run MaybeDisableMemorySwappiness
  6. The test should fail on your older kernel (that implies it's correctly not setting the memory swappiness)

You can also build Nomad yourself
7. export PATH=$PATH:$HOME/go/bin
8. make bootstrap
9. make dev
10. your nomad binary should be in the bin directory

@akamensky
Copy link
Author

akamensky commented Jun 21, 2023

Thanks @shoenig

I got the code and follow the steps you outlined:

The MaybeDisableMemorySwappiness is passing (not failing):

# go test -v -run MaybeDisableMemorySwappiness
=== RUN   TestUtil_MaybeDisableMemorySwappiness
=== PAUSE TestUtil_MaybeDisableMemorySwappiness
=== CONT  TestUtil_MaybeDisableMemorySwappiness
--- PASS: TestUtil_MaybeDisableMemorySwappiness (0.00s)
PASS
ok  	github.com/hashicorp/nomad/client/lib/cgutil	0.010s

Not sure if this is expected. Next I will build the binary, but I need to hack your GNUmakefile as it requires internet connection even if I vendor all dependencies in, which does not work in our systems as it is secured air-gapped network.

Update:

Built Nomad binary and swap the one installed from RPM. Version shows as:

# nomad version
Nomad v1.6.0-dev
BuildDate 2023-06-20T20:41:12Z
Revision 78e67adf35a9b46d2debed2129b40ee55d65275c+CHANGES

However the task still fails:

Jun 21 11:03:18 hostname.redacted nomad[17221]: 2023-06-21T11:03:18.566+0000 [INFO]  client.alloc_runner.task_runner: Task event: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d task=test type=Received msg="Task received by client" failed=false
Jun 21 11:03:18 hostname.redacted nomad[17221]: 2023-06-21T11:03:18.566+0000 [WARN]  client.gc: garbage collection skipped because no terminal allocations: reason="disk usage of 86 is over gc threshold of 80"
Jun 21 11:03:18 hostname.redacted nomad[17221]: 2023-06-21T11:03:18.615+0000 [INFO]  client.alloc_runner.task_runner: Task event: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d task=test type="Task Setup" msg="Building Task Directory" failed=false
Jun 21 11:03:19 hostname.redacted nomad[17221]: 2023-06-21T11:03:19.507+0000 [WARN]  client.gc: garbage collection skipped because no terminal allocations: reason="disk usage of 86 is over gc threshold of 80"
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.241+0000 [INFO]  client.driver_mgr.exec: starting task: driver=exec driver_cfg="{Command:sleep Args:[infinity] ModePID: ModeIPC: CapAdd:[] CapDrop:[]}"
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.315+0000 [INFO]  client.driver_mgr.exec.executor: plugin process exited: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d driver=exec task_name=test path=/usr/bin/nomad pid=18450
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.315+0000 [INFO]  client.alloc_runner.task_runner: Task event: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d task=test type="Driver Failure" msg="failed to launch command with executor: rpc error: code = Unknown desc = unable to start container process: error during container init: error setting cgroup config for procHooks process: failed to write \"0\": write /sys/fs/cgroup/memory/nomad/8b43802a-9cf8-ff74-fb0f-e498d4ede9ee/memory.swappiness: invalid argument" failed=false
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.449+0000 [ERROR] client.alloc_runner.task_runner: running driver failed: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d task=test error="failed to launch command with executor: rpc error: code = Unknown desc = unable to start container process: error during container init: error setting cgroup config for procHooks process: failed to write \"0\": write /sys/fs/cgroup/memory/nomad/8b43802a-9cf8-ff74-fb0f-e498d4ede9ee/memory.swappiness: invalid argument"
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.449+0000 [INFO]  client.alloc_runner.task_runner: not restarting task: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d task=test reason="Error was unrecoverable"
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.449+0000 [INFO]  client.alloc_runner.task_runner: Task event: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d task=test type="Not Restarting" msg="Error was unrecoverable" failed=true
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.687+0000 [INFO]  client.alloc_runner.task_runner.task_hook.logmon: plugin process exited: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d task=test path=/usr/bin/nomad pid=18439
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.688+0000 [INFO]  client.gc: marking allocation for GC: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.688+0000 [INFO]  client.gc: garbage collecting allocation: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d reason="disk usage of 86 is over gc threshold of 80"
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.748+0000 [INFO]  client.alloc_runner.task_runner: Task event: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d task=test type=Killing msg="Sent interrupt. Waiting 5s before force killing" failed=false
Jun 21 11:03:23 hostname.redacted nomad[17221]: 2023-06-21T11:03:23.865+0000 [INFO]  client.gc: marking allocation for GC: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d
Jun 21 11:03:32 hostname.redacted nomad[17221]: 2023-06-21T11:03:32.032+0000 [INFO]  client.gc: garbage collecting allocation: alloc_id=2904e97e-08cc-6f20-91f8-7d8103731b1d reason="disk usage of 86 is over gc threshold of 80"

When I check the cgroups sys dir contents I see:

# ll /sys/fs/cgroup/memory/nomad/*
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/cgroup.clone_children
--w--w--w- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/cgroup.event_control
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/cgroup.procs
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.failcnt
--w------- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.force_empty
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.failcnt
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.limit_in_bytes
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.max_usage_in_bytes
-r--r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.slabinfo
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.tcp.failcnt
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.tcp.limit_in_bytes
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.tcp.max_usage_in_bytes
-r--r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.tcp.usage_in_bytes
-r--r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.kmem.usage_in_bytes
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.limit_in_bytes
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.max_usage_in_bytes
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.memsw.failcnt
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.memsw.limit_in_bytes
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.memsw.max_usage_in_bytes
-r--r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.memsw.usage_in_bytes
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.move_charge_at_immigrate
-r--r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.numa_stat
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.oom_control
---------- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.pressure_level
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.soft_limit_in_bytes
-r--r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.stat
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.swappiness
-r--r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.usage_in_bytes
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/memory.use_hierarchy
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/notify_on_release
-rw-r--r-- 1 root root 0 Jun 21 10:57 /sys/fs/cgroup/memory/nomad/tasks

So it does show memory.swappiness there, but it appears it is unable to set it? I've tried doing it manually as:

[root@redacted nomad]# cat /sys/fs/cgroup/memory/nomad/memory.swappiness
10
[root@redacted nomad]# echo 0 > /sys/fs/cgroup/memory/nomad/memory.swappiness
bash: echo: write error: Invalid argument
[root@redacted nomad]# echo 1 > /sys/fs/cgroup/memory/nomad/memory.swappiness
bash: echo: write error: Invalid argument
[root@redacted nomad]# echo '1' > /sys/fs/cgroup/memory/nomad/memory.swappiness
bash: echo: write error: Invalid argument
[root@redacted nomad]#

Looking at the diff (I left similar comment there). The file it stats exists, however it cannot be written to even as root. It appears to always be a read-only value of the global vm.swappiness value:

[root@redacted nomad]# stat /sys/fs/cgroup/memory/memory.swappiness
  File: ‘/sys/fs/cgroup/memory/memory.swappiness’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: 18h/24d	Inode: 9307        Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-06-19 16:40:58.501000000 +0800
Modify: 2023-06-19 16:40:58.501000000 +0800
Change: 2023-06-19 16:40:58.501000000 +0800
 Birth: -
[root@redacted nomad]# cat /sys/fs/cgroup/memory/memory.swappiness
10
[root@redacted nomad]# echo 0 > /sys/fs/cgroup/memory/memory.swappiness
bash: echo: write error: Invalid argument
[root@redacted nomad]# sysctl -w vm.swappiness=1
vm.swappiness = 1
[root@redacted nomad]# cat /sys/fs/cgroup/memory/memory.swappiness
1
[root@redacted nomad]#

@akamensky
Copy link
Author

akamensky commented Jun 21, 2023

@shoenig I throw together a simple check whether the sys fs path is actually writeable (not specific to control groups):

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	cgOptions := []string{
		"/sys/fs/cgroup/memory/memory.swappiness",
	}

	for _, cgOption := range cgOptions {
		if !isCgOptionExists(cgOption) {
			// if cgroup option does not exist,
			// then nothing to do
			continue
		}

		if _, err := isCgOptionWritable(cgOption); err != nil {
			fmt.Println(cgOption, "is not writable due to:", err.Error())
		} else {
			fmt.Println(cgOption, "ok")
		}
	}
}

func isCgOptionExists(sysFsPath string) bool {
	_, err := os.Stat(sysFsPath)
	if os.IsNotExist(err) {
		return false
	}

	return true
}

func isCgOptionWritable(sysFsPath string) (bool, error) {
	currValue, err := readCgOption(sysFsPath)
	if err != nil {
		return false, err
	}

	err = writeCgOption(sysFsPath, currValue)
	if err != nil {
		return false, err
	}

	return true, nil
}

func readCgOption(sysFsPath string) ([]byte, error) {
	fd, err := os.Open(sysFsPath)
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	return io.ReadAll(fd)
}

func writeCgOption(sysFsPath string, value []byte) error {
	fd, err := os.OpenFile(sysFsPath, os.O_TRUNC|os.O_WRONLY|os.O_SYNC, 0644)
	if err != nil {
		return err
	}
	defer fd.Close()

	_, err = fd.Write(value)
	if err != nil {
		return err
	}

	return nil
}

On the kernel in question it produces:

[root@redacted ~]# go run main.go 
/sys/fs/cgroup/memory/memory.swappiness is not writable due to: write /sys/fs/cgroup/memory/memory.swappiness: invalid argument
[root@redacted ~]# uname -a
Linux redacted 3.10.0-123.20.1.el7.x86_64 #1 SMP Thu Jan 29 18:05:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

On somewhat newer kernel it produces:

[root@redacted ~]# go run main.go 
/sys/fs/cgroup/memory/memory.swappiness ok
[root@redacted ~]# uname -a
Linux redacted 4.18.0-80.11.2.el8_0.x86_64 #1 SMP Tue Sep 24 11:32:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

On very recent kernel it produces:

[root@redacted cgcheck]# go run main.go 
[root@redacted cgcheck]# echo $?
0
[root@redacted cgcheck]# uname -a
Linux redacted 6.2.13-100.fc36.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 26 20:11:01 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Update:

I then applied below patch on your branch (note: this would need to be checked in same way for any sysctl params set for control group as older kernels don't support some/all sysctl params override -- those are always inherited from system):

diff --git a/client/lib/cgutil/cgutil_linux.go b/client/lib/cgutil/cgutil_linux.go
index 85aff63cd..155115436 100644
--- a/client/lib/cgutil/cgutil_linux.go
+++ b/client/lib/cgutil/cgutil_linux.go
@@ -7,6 +7,7 @@ package cgutil
 
 import (
        "fmt"
+       "io"
        "os"
        "path/filepath"
 
@@ -163,10 +164,60 @@ func MaybeDisableMemorySwappiness() *uint64 {
        }
 
        // cgroups v1 check if the root and swappiness interface exist
-       _, err := os.Stat("/sys/fs/cgroup/memory/memory.swappiness")
-       if os.IsNotExist(err) {
+       if !isCgOptionExists("/sys/fs/cgroup/memory/memory.swappiness") {
+               return bypass
+       }
+       if _, err := isCgOptionWritable("/sys/fs/cgroup/memory/memory.swappiness"); err != nil {
                return bypass
        }
 
        return zero
 }
+
+func isCgOptionExists(sysFsPath string) bool {
+       _, err := os.Stat(sysFsPath)
+       if os.IsNotExist(err) {
+               return false
+       }
+
+       return true
+}
+
+func isCgOptionWritable(sysFsPath string) (bool, error) {
+       currValue, err := readCgOption(sysFsPath)
+       if err != nil {
+               return false, err
+       }
+
+       err = writeCgOption(sysFsPath, currValue)
+       if err != nil {
+               return false, err
+       }
+
+       return true, nil
+}
+
+func readCgOption(sysFsPath string) ([]byte, error) {
+       fd, err := os.Open(sysFsPath)
+       if err != nil {
+               return nil, err
+       }
+       defer fd.Close()
+
+       return io.ReadAll(fd)
+}
+
+func writeCgOption(sysFsPath string, value []byte) error {
+       fd, err := os.OpenFile(sysFsPath, os.O_TRUNC|os.O_WRONLY|os.O_SYNC, 0644)
+       if err != nil {
+               return err
+       }
+       defer fd.Close()
+
+       _, err = fd.Write(value)
+       if err != nil {
+               return err
+       }
+
+       return nil
+}

compiled and ran, and it can run tasks/jobs on this kernel just fine now:

image

@shoenig
Copy link
Member

shoenig commented Jun 21, 2023

Thanks @akamensky that is super helpful. I added a commit to the branch which should be a succinct version of what you have. (We can get away with just trying to write to the /nomad parent cgroup since we own it). Let me know if that still works for you.

@akamensky
Copy link
Author

Thanks @shoenig I've tested updated patch and it works as expected now. I have not tried any other job configuration options with this, but if I find any issues with those old kernels will report them separately.

@shoenig shoenig added this to the 1.6.0 milestone Jun 22, 2023
shoenig added a commit that referenced this issue Jun 22, 2023
#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>
Nomad - Community Issues Triage automation moved this from In Progress to Done Jun 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage/accepted Confirmed, and intend to work on. No timeline committment though. theme/cgroups cgroups issues type/bug
Projects
Development

Successfully merging a pull request may close this issue.

3 participants