Покажу сразу на простом примере. Запустим оболочку bash с отдельными namespace PID и mount. То есть мы получим изолированную среду на уровне процессов и точек монтирования. Новый процесс bash в этом namespace получит id 1.
# unshare --pid --fork --mount-proc --mount /bin/bash# ps ax PID TTY STAT TIME COMMAND 1 pts/0 S 0:00 /bin/bash 45 pts/0 R+ 0:00 ps axТеперь на условном примере покажу изоляцию mount. Здесь же в изолированных namespaces добавляем монтирование:
# mkdir /tmp/dir1 /mnt/dir1# mount --bind /tmp/dir1 /mnt/dir1# mount | grep dir1/dev/sda2 on /mnt/dir1 type ext4 (rw,relatime,errors=remount-ro)При этом на самом хосте вы этого mount не увидите. Если в изолированном namespace создать что-то в /tmp/dir1, оно появится в /mnt/dir1, а если на хосте зайти в /mnt/dir1 там будет пусто, потому что для хоста этого монтирования не существует.
Посмотреть существующие namespaces можно командой
lsns:# lsns................................................4026532129 mnt 2 853 root unshare --pid --fork --mount-proc --mount /bin/bash4026532130 pid 1 854 root └─/bin/bash.................................................Там будет видно в том числе созданные нами namespaces для форка bash. Это будут mnt и pid. Если у вас на хосте запущены контейнеры, то здесь же их и увидите. Работа контейнеров основана на этом механизме ядра.
Из показанного примера видно, что использовать изоляцию можно и без контейнеров. Можно создавать юниты systemd с использованием namespaces. Базово в системе уже есть некоторые юниты, работающие в своём пространстве. Их видно по
lsns. С помощью утилиты nsenter можно запускать процессы в произвольных namespaces. Откроем отдельную консоль и запустим процесс в созданном ранее namespace с bash. Для этого с помощью
lsns узнаём pid процесса в ns pid и подцепляем к нему, к примеру, команду sleep.# lsns | grep /bin/bash4026532129 mnt 2 853 root unshare --pid --fork --mount-proc --mount /bin/bash4026532130 pid 1 854 root └─/bin/bash#
nsenter -t 854 -m -p sleep 60Возвращаемся в консоль с unshare и смотрим список процессов:
# ps ax PID TTY STAT TIME COMMAND 1 pts/0 S 0:00 /bin/bash 50 pts/2 S+ 0:00 sleep 60 51 pts/0 R+ 0:00 ps axВидим процесс со sleep. Базово всё это попробовать довольно просто, но на самом деле там очень много нюансов. Поэтому все и пользуются готовыми решениями на базе этой технологии, типа Docker.
Всего существует следующий набор namespaces:
- mount - изоляция на уровне монтирования файловых систем;
- UTS - изоляция hostname и domainname, т.е. в каждом ns может быть своё имя хоста;
- IPC - изоляция межпроцессорного взаимодействия (Inter-process communication);
- network - свои сетевые настройки для разных ns, включая ip адреса, маршруты, правила файрволов;
- PID - изоляция процессов;
- user - изоляция пользовательских UIDs и GIDs;
- cgroup - ограничивает потребляемый объём аппаратных ресурсов, cpu, ram, io и т.д.;
- time - изоляция некоторых параметров времени, а конкретно только MONOTONIC и BOOTTIME, установить разное текущее время в разных ns нельзя.
Все эти ns можно использовать с помощью утилит unshare и nsenter. Также существует отдельный продукт systemd-nspawn, один из компонентов systemd, который реализует возможности для создания легковесных контейнеров. Он как-то не особо распространён, не знаю почему. По идее, благодаря тесной интеграции с systemd это должно быть удобно, так как systemd сейчас везде.
#linux