Настройка контрольных групп

#linux #go #system-calls

#linux #Вперед #системные вызовы

Вопрос:

У меня есть некоторый код go, который создает корневую систему скелета, а затем в каждом пространстве имен Linux подключается к нему, настраивает cgroups, а затем запускает процесс внутри этой cgroup / chroot.

Я заставил большую часть этого работать, но у меня возникли проблемы с получением контрольных групп для работы.

Я следил за этим на протяжении большей части своей работы с cgroups, и я все еще новичок в них как в концепции.

Если я вручную создам эту среду и выполню следующие команды, кажется, что все работает нормально. (Я добавил к ним номера для справки позже)

 1) mount -t proc proc /proc
2) mount -t sysfs sysfs /sys
3) mount -t tmpfs cgroup_root /sys/fs/cgroup
4) mkdir /sys/fs/cgroup/pids
5) mount -t cgroup pids -o pids /sys/fs/cgroup/pids
  

Как вы можете видеть из выходных данных cat / proc / mounts

 proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,relatime 0 0
cgroup_root /sys/fs/cgroup tmpfs rw,relatime 0 0
pids /sys/fs/cgroup/pids cgroup rw,relatime,pids 0 0
  

У меня есть смонтированная /proc, /sys, /sys/fs/cgroup и pids /sys/fs/cgroup/pids -группа. Теперь я могу настроить эту cgroup pids с любыми настройками, которые я хочу, и все работает нормально.

Моя проблема в том, что я пытаюсь сделать то же самое в Go, и у меня возникают проблемы.

В моем коде я могу успешно выполнить до шага 4) mkdir /sys/fs/cgroup/pids , и я даже проверил, что этот файл создается, но у меня возникают проблемы с получением системного вызова.Mount(), чтобы сделать то, что я хочу для 5-й команды.

Вот что у меня есть прямо сейчас.

 func mountPid(pidsLoc string) {
    fstype := "cgroup"
    source := "pids"
    flags := uintptr(0)
    data := "pids"

    err := syscall.Mount(source, pidsLoc, fstype, flags, data)
    if err != nil {
        serverFatal(err)
    }
}
  

Где pidsLoc = /sys/fs/cgroup/pids , но когда я пытаюсь запустить это, я получаю сообщение об ошибке «операция не разрешена».

Я действительно не думаю, что это ошибка разрешений, потому что я смог смонтировать свой /sys , /proc и /sys/fs/cgroups все в порядке. Вот код, который я использовал для этих трех:

 func mountProc() {
    source := "proc"
    fstype := "proc"
    target := "/proc"
    flags := uintptr(0)
    data := ""

    err := syscall.Mount(source, target, fstype, flags, data)
    if err != nil {
        serverFatal(err)
    }
}

func mountSys() {
    source := "sysfs"
    fstype := "sysfs"
    target := "/sys"
    flags := uintptr(0)
    data := ""

    err := syscall.Mount(source, target, fstype, flags, data)
    if err != nil {
        serverFatal(err)
    }
}

//This can not be called before mountSys()
func mountCGroupFS() {
    fstype := "tmpfs"
    source := "cgroup_root"
    target := "/sys/fs/cgroup"
    flags := uintptr(0)
    data := ""

    err := syscall.Mount(source, target, fstype, flags, data)
    if err != nil {
        serverFatal(err)
    }
}
  

И я запустил все из них с теми же разрешениями, что и раньше. Может быть, я просто использую системный вызов.Mount() неправильно, но я не уверен. Документация для пакета системного вызова в Go не очень хороша, и я обнаружил, что в основном мне приходится читать документацию на C / C для методов, которые использует системный вызов, а затем пытаться установить связи между ними.

Заранее спасибо!

PS Вот ссылка на репозиторий, если вам интересно. Я пытаюсь создать программу, которая позволяет «безопасно» выполнять внешний код.

Комментарии:

1. Почему бы не использовать это: github.com/containerd/cgroups ?

2. Я не знал об этом, и похоже, что это будет отличный ресурс, но я пытаюсь создать свой собственный с нуля, чтобы учиться, поэтому я не хочу использовать другую библиотеку.