Контейнер как процесс: namespaces, OverlayFS и rootless Podman
Автор: Казачкин Даниил Михайлович · Обновлено
У контейнера есть PID на хосте, открытые файлы и системные вызовы того же ядра. Его обособленность складывается из нескольких механизмов. Мы исследуем границы видимости и прав, чтобы понимать rootless-запуск и диагностировать сеть. Сборка образов, Compose и публикация приложений подробно разобраны в [треке Docker](/lessons/without-university/docker-containerization/docker-developer-35).
Что изолирует namespace
PID namespace меняет видимые номера процессов; net — интерфейсы, маршруты, сокеты и сетевые настройки; mnt — дерево монтирований; uts — hostname; user — отображение UID/GID и область привилегий. IPC разделяет соответствующие механизмы межпроцессного общения. Один процесс одновременно принадлежит пространствам разных видов.
readlink /proc/self/ns/pid
readlink /proc/self/ns/net
readlink /proc/self/ns/mnt
readlink /proc/self/ns/userВы увидите обозначения вроде net:[4026531840]; конкретные числа зависят от машины. Совпадение идентификатора одного вида у двух живых процессов означает общее пространство этого вида. Namespace не задаёт лимит RAM, а chroot сам по себе не создаёт ни новый PID namespace, ни полноценную границу безопасности. Виды namespaces.
Свой root без root хоста
На машине, где разрешены непривилегированные user namespaces, попробуйте:
unshare --user --map-root-user --uts sh -c '
id
cat /proc/self/uid_map
hostname lab-box
hostname
'
hostnameВ дочернем shell UID выглядит как ноль, но uid_map связывает его с вашим UID снаружи. Изменённый hostname виден внутри нового uts namespace; после выхода имя хоста остаётся прежним. Operation not permitted может означать запрет user namespaces или дополнительную политику среды. Не отключайте защиту хоста ради примера: выполните упражнение в предназначенной для него VM.
Это объясняет rootless Podman: контейнерный root не становится глобальным root. Для диапазонов дополнительных UID/GID обычно нужны subordinate mappings в /etc/subuid и /etc/subgid, helpers и поддержка среды. Проверяйте podman info --debug; некоторые операции с сетью, bind mounts и контроллерами cgroup имеют ограничения. Rootless не означает «любой контейнер безопасен»: приложение сохраняет доступ к явно переданным данным пользователя.
Один жизненный цикл Podman
В учебном окружении с доступом к registry:
podman run -d --name lab-view --memory=128m --cpus=0.5 \
docker.io/library/alpine:3.22 sh -c 'echo ready; sleep 120'
podman logs lab-view
podman exec lab-view id
podman stats --no-stream lab-view
podman inspect --format '{{.State.Pid}}' lab-view
podman stop lab-view
podman rm lab-viewОжидается строка ready. PID из inspect относится к среде Podman, а не обязательно к вашей внешней машине при удалённом соединении. Потребление stats изменяется; проверить факт применения лимитов помогают inspect и файлы cgroup. Если контроллер недоступен или не делегирован, фиксируйте сообщение runtime. Нельзя считать, что --memory сработал только потому, что его написали. Параметры Podman.
Посмотреть сеть и файловые слои
Для собственного контейнера на Linux-хосте определите PID и используйте sudo nsenter --target PID --net ip address. Команда запускает инструмент хоста в сетевом пространстве процесса. Она не копирует туда весь контейнерный filesystem; подключение только к net не меняет mount namespace. В rootless-сценарии могут понадобиться согласованный вход в user namespace и инструменты самого Podman. Исчезнувший PID означает гонку с завершением контейнера, поэтому сначала проверьте его состояние.
OverlayFS объединяет нижний слой и верхний записываемый слой. При изменении нижнего файла происходит copy-up; удаление представляется служебной записью верхнего слоя. Поэтому удаление большого файла из нижнего слоя не уменьшает размер исходного образа. upperdir и workdir должны отвечать требованиям файловой системы, в частности находиться на одной файловой системе; не монтируйте вручную storage работающего runtime. Rootless может использовать иной драйвер, включая fuse-overlayfs. Модель OverlayFS.
Видимость, бюджет и разрешение
Namespaces отвечают за видимое окружение, cgroups — за учёт и ресурсные ограничения, capabilities — за отдельные привилегии, seccomp — за допустимые системные вызовы. Отсутствие процесса в контейнерном ps не означает, что он не существует на хосте. Отказ системного вызова не доказывает нехватку памяти: причиной может быть профиль seccomp или capability.
Задание: объясните три наблюдения — внутри id показывает 0, hostname отличается, memory.max равен 134217728. Назовите механизм каждого эффекта и проверку снаружи. Затем сравните ошибку EPERM при запрещённом вызове с ростом memory.events при OOM. За интерпретацией счётчиков перейдите к [cgroup v2](/lessons/without-university/linux-developer-foundations/linux-developer-27).