← Назад к вопросам

Как устроены Linux namespaces?

1.8 Middle🔥 181 комментариев
#Linux и администрирование#Docker и контейнеризация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Общее представление о Linux namespaces

Linux namespaces — это механизм ядра Linux для изоляции и виртуализации системных ресурсов, позволяющий процессам видеть разные "представления" (namespaces) одной и той же глобальной сущности (например, дерева процессов, сетевых интерфейсов, точек монтирования). Это фундаментальная технология, лежащая в основе контейнеризации (Docker, LXC, Podman) и легковесных изолированных сред.

По сути, namespace создает "песочницу" для группы процессов, где они видят собственный изолированный экземпляр глобального ресурса. Например, процессы в отдельном PID namespace будут видеть только свои собственные процессы, начиная с PID 1, как будто они находятся в отдельной системе. При этом из "внешнего" namespace эти процессы по-прежнему видны со своими оригинальными PID.

Основные типы namespaces

Ядро Linux поддерживает несколько типов namespaces, каждый из которых отвечает за изоляцию определенного аспекта системы:

  • PID (Process ID) namespace: Изолирует пространство идентификаторов процессов. Процессы в разных PID ns могут иметь одинаковые PID.
  • Network (net) namespace: Изолирует сетевые стеки — интерфейсы, таблицы маршрутизации, правила iptables/nftables.
  • Mount (mnt) namespace: Изолирует точки монтирования файловых систем. Процессы могут иметь разные корневые файловые системы (chroot на стероидах).
  • IPC (Inter-Process Communication) namespace: Изолирует объекты межпроцессного взаимодействия (очереди сообщений, сегменты разделяемой памяти, семафоры).
  • UTS (UNIX Time-sharing System) namespace: Изолирует системные идентификаторы hostname и domainname.
  • User namespace: Изолирует пространство идентификаторов пользователей и групп (UID/GID). Позволяет отображать привилегированные пользователей внутри namespace на непривилегированных снаружи. Это ключевой namespace для безопасной контейнеризации без root-привилегий.
  • Cgroup namespace (с Linux 4.6): Изолирует представление иерархии контрольных групп (cgroups), делая ее "корневой" для процессов внутри namespace.
  • Time namespace (с Linux 5.6): Позволяет изолировать системные часы, создавая смещения времени для процессов внутри namespace.

Как namespaces работают на практике

Процесс может принадлежать к одному экземпляру каждого типа namespace. При создании процесса (системный вызов clone()) можно указать флаги, определяющие, в какие новые namespaces он будет помещен.

// Пример создания процесса в новых PID и Mount namespaces
pid = clone(child_function, stack + STACK_SIZE,
            CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, // CLONE_NEWNS создает новый mount namespace
            NULL);

Для существующего процесса можно перейти в новый namespace с помощью системного вызова unshare() или присоединиться к существующему через setns().

# Практический пример: создание нового network namespace с помощью утилиты ip
sudo ip netns add mynetns  # Создает новый network namespace "mynetns"
sudo ip netns exec mynetns bash  # Запуск bash в этом namespace
# Внутри этого bash будет видна только loopback-интерфейс (lo)

Управление namespaces из командной строки часто осуществляется через утилиты ip (для сетевых), unshare, nsenter и lsns.

Взаимосвязь с другими технологиями

Namespaces редко используются изолированно. Вместе с cgroups (для ограничения ресурсов) и другими функциями ядра они образуют полный стек контейнеризации:

  1. PID namespace + Mount namespace создают изолированную файловую среду.
  2. Network namespace обеспечивает сетевую изоляцию, которая может быть соединена с внешним миром через виртуальные Ethernet-пары (veth) или мосты (bridge).
  3. User namespace позволяет безопасно запускать контейнеры от непривилегированных пользователей.
  4. Cgroups ограничивают потребление CPU, памяти, дискового I/O.

Пример внутреннего устройства: PID namespace

Рассмотрим, как устроен PID namespace. Каждый процесс в системе имеет запись в виртуальной файловой системе /proc. Внутри ядра для каждого PID namespace создается собственное дерево процессов. Когда процесс запрашивает список процессов (например, через ps или чтение /proc), ядро фильтрует вывод, показывая только процессы, видимые в текущем namespace.

# Демонстрация: запуск процесса в новом PID namespace
sudo unshare --pid --fork --mount-proc bash
echo $$  # Покажет PID 1 внутри этого namespace
ps aux   # Покажет только процессы, запущенные в этом namespace

При этом "снаружи" этот процесс будет иметь обычный системный PID. Механизм "перевода" PID между разными namespaces осуществляется ядром прозрачно.

Важные аспекты реализации

  • Иерархичность: Некоторые namespaces (например, PID) образуют иерархию: дочерний namespace видит процессы родительского, но не наоборот.
  • Связь с файловой системой: Каждый namespace представлен файлом в /proc/[pid]/ns/. Эти файлы можно использовать для входа в namespace (setns()) или поддержания его существования (даже если в нем не осталось процессов).
  • Производительность: В отличие от аппаратной виртуализации, namespaces добавляют минимальные накладные расходы, так как изоляция происходит на уровне ядра без эмуляции оборудования.
  • Безопасность: Полноценная изоляция требует комбинации всех namespaces. User namespace критически важен для security, так как позволяет запускать контейнеры без привилегий root на хосте.

Namespaces предоставляют элегантный и эффективный механизм виртуализации на уровне операционной системы, став основой для современной экосистемы контейнеров и облачных вычислений.