CGROUP_NAMESPACES(7)

ИМЯ
cgroup_namespaces - обзор пространств имён Linux cgroup

ОПИСАНИЕ
Обзор пространств имён смотрите в namespaces(7).

Пространства имён cgroup_namespaces виртуализируют представление о cgroup процесса (смотрите cgroups(7)) в виде /proc/[pid]/cgroup и /proc/[pid]/mountinfo.

Каждое пространство имён cgroup имеет свой набор корневых каталогов cgroup. Данные корневые каталоги являются базовыми точками относительных расположений, показываемых в соответствующих записях файла /proc/[pid]/cgroup. Когда процесс создаёт новое пространство имён cgroup с помощью clone(2) или unshare(2) с флагом CLONE_NEWCGROUP, то он входит в новое пространство имён cgroup, в котором его текущие каталоги cgroups становятся корневыми каталогами cgroup нового пространства имён (это применимо как для иерархии cgroups версии 1, так и для унифицированной иерархии cgroups версии 2).

При просмотре /proc/[pid]/cgroup путь в третьем поле каждой записи будет относительным по отношению к корневому каталогу cgroup читающего процесса для соответствующей иерархии cgroup. Если каталог cgroup процесса назначения лежит вне корневого каталоге пространства имён cgroup читающего процесса, то путь будет показан как ../ для каждого уровня предка в иерархии cgroup.

Следующий пример сеанса демонстрирует создание нового пространства имён cgroup. Сначала (от суперпользователя) создаётся дочерняя cgroup в иерархии freezer и оболочка помещается в эту cgroup:

    # mkdir -p /sys/fs/cgroup/freezer/sub
    # echo $$                      # выводим PID этой оболочки
    30655
    # sh -c 'echo 30655 > /sys/fs/cgroup/freezer/sub/cgroup.procs'
    # cat /proc/self/cgroup | grep freezer
    7:freezer:/sub

Затем с помощью unshare(1) создаётся процесс, выполняющий новую оболочку в новой cgroup и монтируется пространство имён:

    # unshare -Cm bash

Теперь содержимое файлов /proc/[pid]/cgroup содержит, соответственно, новый процесс-оболочки, запущенный командой unshare(1), процесс, находящийся в изначальном пространстве имён cgroup (init с PID 1) и процесс в родственной cgroup (sub2):

    $ cat /proc/self/cgroup | grep freezer
    7:freezer:/
    $ cat /proc/1/cgroup | grep freezer
    7:freezer:/..
    $ cat /proc/20124/cgroup | grep freezer
    7:freezer:/../sub2

В выводе первой команды мы видим, что в cgroup freezer членство новой оболочки (находящейся в той же cgroup, что и начальная оболочка) определено относительно корневого каталога cgroup freezer, который был назначен при создании нового пространства имён cgroup (в абсолютном выражении, новая оболочка находится в /sub freezer cgroup и корневой каталог иерархии freezer cgroup в новом пространстве имён cgroup также находится в /sub. То есть, членство cgroup новой оболочки показывается как '/').

Однако, если посмотреть /proc/self/mountinfo, то можно увидеть следующую аномалию:

    # cat /proc/self/mountinfo | grep freezer
    155 145 0:32 /.. /sys/fs/cgroup/freezer ...

Четвёртое поле в этой строке (/..) должно содержать каталог в файловой системе cgroup, который является корнем этого монтирования. Так как по определению пространств имён cgroup текущий каталог freezer cgroup процесса становится его корневым каталогом freezer cgroup, в этом поле мы должны увидеть '/'. Проблема здесь в том, что мы видим запись о монтировании для файловой системы cgroup, которая соответствует нашему начальному процессу с оболочкой пространства имён cgroup (чья файловая система cgroup действительно имеет корень в родительском каталоге sub). Нам нужно перемонтировать файловую систему freezer cgroup внутрь этого пространства имён cgroup, после чего мы увидим ожидаемый результат:

    # mount --make-rslave /     # не распространять события монтирования
                                # в другие пространства имён
    # umount /sys/fs/cgroup/freezer
    # mount -t cgroup -o freezer freezer /sys/fs/cgroup/freezer
    # cat /proc/self/mountinfo | grep freezer
    155 145 0:32 / /sys/fs/cgroup/freezer rw,relatime ...

Для использования пространств имён cgroup требуется, чтобы ядро было собрано с параметром CONFIG_CGROUPS.

СООТВЕТСТВИЕ СТАНДАРТАМ
Пространства имён есть только в Linux.

ЗАМЕЧАНИЯ
Пространства имён cgroup используются для поддержки виртуализации следующим образом:

*   Для предотвращения утечек информации о путях каталогов cgroup за пределами контейнера, иначе они были бы видимы процессам в контейнере. Такие утечки могли, например, выдать информацию о платформе контейнера приложениям в контейнере.

*   Для облегчения задач по переносу контейнера. Виртуализация, предоставляемая пространствами имён cgroup, позволяет контейнерам не знать информацию о путях родительских cgroup. Без такой изоляции потребовалось бы воссоздавать полные пути cgroup (показываемые в /proc/self/cgroups) в целевой системе при переносе контейнера; также эти пути должны были быть уникальными, чтобы они не пересекались с другими путями в целевой системе.

*   Для обеспечения большего ограничения контейнеризированных процессов, так как возможно смонтировать файловые системы cgroup контейнера таким образом, что процессы контейнера не смогут получить доступ к каталогам предка cgroup. Рассмотрим, например, следующий сценарий:

    •   Есть каталог cgroup /cg/1, который принадлежит пользователю с ID 9000.

    •   Есть процесс X, который также принадлежит пользователю с ID 9000, он находится в пространстве имён под /cg/1/2 (т. е., X помещён в новое пространство имён cgroup посредством clone(2) или unshare(2) с флагом CLONE_NEWCGROUP).

    Если нет пространств имён cgroup, а каталог cgroup /cg/1 принадлежит (и доступен на запись) UID 9000 и процесс X также принадлежит пользователю с ID 9000, процесс X может изменять содержимое файлов cgroups (т. е., изменять настройки cgroup) не только в /cg/1/2, но и в родительском каталоге cgroup /cg/1. Выделение для процесса X пространства имён в каталоге cgroup /cg/1/2, в комбинации с нужными операциями монтирования файловой системы cgroup (как показано выше) не даёт изменять файлы в /cg/1, так как невозможно увидеть содержимое этого каталога (или, в дальнейшем, удалить каталоге родительского cgroup). В сочетании с правильным обеспечением иерархических ограничений это не позволяет процессу X обойти ограничения, накладываемые родительскими cgroups.

СМОТРИТЕ ТАКЖЕ
unshare(1), clone(2), setns(2), unshare(2), proc(5), cgroups(7), credentials(7), namespaces(7), user_namespaces(7)