1

我们有一个库,它使用 POSIX 消息队列在进程之间传递数据,并且需要将 msgqueue 内核参数设置为无限制,否则进程将返回错误too many open files。通常我们使用ulimit -qand来查看/设置它ulimit -q unlimited,但是对于一些 Kubernetes 容器,我们希望能够通过 go 代码直接设置它。

我们已经确认 pod 规范允许更改 mqueue 设置(通过 Kubernetes 1.14+ 的 securityContext)并且特定容器可以调整资源设置:

...
kind: Deployment
...
spec:
  template:
    spec:
      securityContext:
        sysctls:
        - name: fs.mqueue.msg_max
          value: "10000"
        - name: fs.mqueue.msgsize_max
          value: "102400"
      containers:
      - name: testing
        securityContext:
          capabilities:
            add:
            - SYS_RESOURCE
...

如果没有这些设置,甚至ulimit -q unlimited会出现错误:

bash:ulimit:POSIX消息队列:无法修改限制:不允许操作

但是我们如何使用syscall.Setrlimit从我们的代码中调整限制值呢?

4

1 回答 1

1

看起来 syscall 包在没有RLIMIT_MSGQUEUE = 0xC常量的情况下被冻结,并且它还定义syscall.RLIM_INFINITY = -0x1了在尝试使用该值时会导致错误:

系统调用:Rlimit 常量 -1 溢出 uint64

因此,您必须手动定义常量

const RLIMIT_MSGQUEUE int = 0xC
const RLIM_INFINITY uint64 = 0xffffffffffffffff // https://github.com/golang/go/issues/22731
err = syscall.Setrlimit(RLIMIT_MSGQUEUE, &syscall.Rlimit{RLIM_INFINITY,RLIM_INFINITY}))

或切换到使用https://godoc.org/golang.org/x/sys/unix中的方法:

err = unix.Setrlimit(unix.RLIMIT_MSGQUEUE, &unix.Rlimit{Cur: unix.RLIM_INFINITY, Max: unix.RLIM_INFINITY})

另请注意,限制值仅针对该进程及其子进程设置,因此要确认您还必须/proc/<pid>/limits从代码中检查或调用 Getrlimit/ulimit:

var rLimit syscall.Rlimit
err := syscall.Getrlimit(0xC, &rLimit)
if err != nil {
    fmt.Println("Error Getting Rlimit ", err)
}
fmt.Println(rLimit)

// construct bash command
cmd := &exec.Cmd {
    Path: "/bin/bash",
    Args: []string{ "/bin/bash", "-c", "ulimit -q"},
    Stdout: os.Stdout,
    Stderr: os.Stdout,
}

// run `cmd` in background and wait for it to finish
cmd.Start()
cmd.Wait()

{18446744073709551615 18446744073709551615}

无限

于 2020-05-20T19:10:32.330 回答