Всем привет, меня зовут Чжан Цзиньтао.
В настоящее время технология контейнеров и технология виртуализации, о которых мы упоминали (независимо от уровня абстракции технологии виртуализации), могут обеспечить изоляцию и ограничение на уровне ресурсов.
Для технологии контейнеров она реализует ограничения и изоляцию на уровне ресурсов и опирается на технологии cgroup и namespace, предоставляемые ядром Linux.
Давайте сначала суммируем роль этих двух технологий:
- Основная роль cgroup: управлять выделением и ограничением ресурсов;
- Основная роль пространства имен: инкапсулировать абстракцию, ограничение, изоляцию, чтобы процессы в пространстве имен имели свои собственные глобальные ресурсы;
Это серия статей, друзья, которым интересна эта серия, могут проверить:
- Тщательно изучите краеугольный камень контейнерной технологии: cgroup
- Тщательно изучите краеугольный камень технологии контейнеров: пространство имен (включено)
В этой статье мы продолжим разговор о пространствах имен.
Тип пространства имен
Давайте сначала взглянем на типы пространств имен, которые были представлены вам в предыдущей статье.Cgroup
, IPC
, Network
иMount
4 типа пространств имен. Давайте перейдем к остальным.
имя пространства имен | Используемые флаги - Флаг | контролировать содержимое |
---|---|---|
Cgroup | CLONE_NEWCGROUP | Корневой каталог cgroup Корневой каталог cgroup |
IPC | CLONE_NEWIPC | System V IPC, очереди сообщений POSIX, семафоры, очереди сообщений |
Network | CLONE_NEWNET | Сетевые устройства, стеки, порты и т. д. |
Mount | CLONE_NEWNS | Точки монтирования |
PID | CLONE_NEWPID | Идентификаторы процессов Идентификаторы процессов |
Time | CLONE_NEWTIME | Загрузочные и монотонные часы |
User | CLONE_NEWUSER | Идентификаторы пользователей и группПользователи и группы пользователей |
UTS | CLONE_NEWUTS | Имя хоста и доменное имя NIS |
PID namespaces
Мы знаем, что в системе Linux каждый процесс будет иметь свой собственный независимый PID, и пространство имен PID в основном используется для изоляции номера процесса. То есть один и тот же идентификатор процесса может содержаться в разных пространствах имен PID.
Номер процесса в каждом пространстве имен PID начинается с 1. В этом пространстве имен PID его можно вызвать, вызвавfork(2)
, vfork(2)
иclone(2)
Дождитесь системных вызовов для создания других процессов с отдельными PID.
Для использования пространства имен PID требуется поддержка ядра.CONFIG_PID_NS
опции. следующее:
(MoeLove) ➜ grep CONFIG_PID_NS /boot/config-$(uname -r)
CONFIG_PID_NS=y
процесс инициализации
Все мы знаем, что в системе Linux есть специальный процесс, так называемый процесс init, то есть процесс с PID 1.
Мы уже говорили, что номер процесса в каждом пространстве имён PID начинается с 1, так каковы же его характеристики?
Во-первых, процесс 1 в пространстве имен PID является родителем всех потерянных процессов.
Во-вторых, если этот процесс завершится, ядро вызоветSIGKILL
Сигнал для завершения всех процессов в этом пространстве имен.Эта часть связана с изящным завершением/плавным обновлением приложений в Kubernetes.(Партнеры, которые заинтересованы в этой части, могут оставить сообщение для связи. Если вам интересно это содержание, я могу написать специальную статью, чтобы рассказать об этом)
Наконец, начиная с версии ядра Linux v3.4, если это происходит в пространстве имен PIDreboot()
системный вызов, процесс инициализации в пространстве имен PID немедленно завершится.Это довольно специфический прием, который можно использовать для работы с выходами из контейнера на сильно загруженных машинах.
Иерархия пространств имен PID
Пространство имен PID поддерживает вложенность.За исключением начального пространства имен PID, остальные пространства имен PID имеют пространство имен PID своего родительского узла.
Другими словами, пространство имен PID также является древовидной структурой, и все пространства имен PID в этой структуре можно проследить до пространства имен предка PID. Конечно, эта глубина не безгранична, так как в версии ядра Linux v3.7 максимальная глубина дерева ограничена 32.
Если эта максимальная глубина будет достигнута, он выброситNo space left on device
ошибка.(Я столкнулся с этим, когда пытался вложить контейнеры раньше)
Процессы видны друг другу в пределах одного и того же (и родственного) пространства имен PID.
Но если процесс находится в дочернем пространстве имен PID, то процесс не может видеть процесс на верхнем уровне (то есть в родительском пространстве имен PID).
От того, виден процесс или нет, зависит, есть ли между процессами определенная ассоциация и вызывающая связь, друзья должны быть знакомы с этим, поэтому я не буду здесь вдаваться в подробности.
Итак, можно ли запланировать процессы на разные уровни пространства имен PID?
Начнем с заключения,Планирование процессов в пространстве имен PID может быть только односторонним (от высокого до низкого).. который:
- Процессы могут быть отправлены только из пространства имен родительского PID в пространство имен дочернего PID;
- Процессы не могут быть отправлены из пространства имен дочернего PID в пространство имен родительского PID;
Рисунок 1. Описание процесса планирования с помощью setns(2)
Иерархические отношения пространства имен PID фактически определяютсяioctl_ns(2)
Системный вызов используется для обнаружения и обслуживания (NS_GET_PARENT), который здесь не будет раскрываться. Итак, как достигается планирование в приведенном выше контенте?
Чтобы ответить на этот вопрос, мы должны сначала осознать, что в начале создания пространства имен PID были определены процессы, имеющие разрешения пространства имен. Что касается планирования, мы можем просто понимать его как реляционную карту или символическую ссылку.
Потоки должны находиться в одном и том же пространстве имен PID, чтобы гарантировать, что потоки в процессе могут взаимодействовать друг с другом. Это ведет кCLONE_NEWPID
не может быть сCLONE_THREAD
использовать одновременно. Но что, если несколько процессов, распределенных в разных пространствах имен PID, должны взаимодействовать друг с другом? Это можно решить с помощью общей очереди сигналов.
Кроме того, мы часто сталкиваемся/proc
В каталоге много/proc/${PID}
, где вы можете увидеть процессы в пространстве имен PID. В то же время этим каталогом также можно управлять напрямую путем монтирования. Например:
(MoeLove) ➜ mount |grep proc
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
Есть ли способ узнать текущее максимальное количество PID?
Это также возможно, так как версия ядра Linux v3.3 добавила новый/proc/sys/kernel/ns_last_pid
Файл, в котором записан идентификатор последнего процесса.
Когда необходимо выделить следующий идентификатор процесса, ядро ищет самый большой неиспользуемый идентификатор для выделения, а затем обновляет информацию о PID в этом файле.
Time namespaces
Прежде чем говорить о пространстве имен времени, нам нужно поговорить оМонотонное время. Прежде всего, системное время, на которое мы обычно ссылаемся, относится к часам реального времени, то есть к отображению текущего времени машиной. Его можно настроить вперед или назад (понимается в связке со службой NTP). Монотонные часы представляют запись времени после определенного момента, это одностороннее обратное абсолютное время, и на него не влияют изменения системного времени.
Для использования пространства имен time требуется поддержка ядра.CONFIG_TIME_NS
опции. Такие как:
(MoeLove) ➜ grep CONFIG_TIME_NS /boot/config-$(uname -r)
CONFIG_TIME_NS=y
time не виртуализирует часы CLOCK_REALTIME. Вам может быть интересно, почему ядро поддерживает пространства имен времени? В основном для некоторых особых сценариев.
Все процессы в пространстве имен time совместно используют следующие два параметра, предоставляемые пространством имен time:
- CLOCK_MONOTONIC - монотонное время, неустанавливаемые часы;
- CLOCK_BOOTTIME (см. параметр ядра CLOCK_BOOTTIME_ALARM) - неустанавливаемые часы, включая время приостановки работы системы.
time может в настоящее время использовать только идентификатор CLONE_NEWTIME, вызываяunshare(2)
системный вызов для создания. Процесс, который создает пространство имен времени, не зависит от вновь созданного пространства имен времени, и последующие дочерние процессы процесса будут помещены во вновь созданное пространство имен времени. Процессы в одном и том же пространстве имен времени совместно используют CLOCK_MONOTONIC и CLOCK_BOOTTIME.
Когда родительский процесс создает дочерний процесс, принадлежность пространства имен времени дочернего процесса будет показана в файле /proc/[pid]/ns/time_for_children.
(MoeLove) ➜ ls -al /proc/self/ns/time_for_children
lrwxrwxrwx. 1 tao tao 0 12月 14 02:06 /proc/self/ns/time_for_children -> 'time:[4026531834]'
Файл /proc/PID/timens_offsets определяет монотонные часы и часы запуска для начального пространства имен времени и записывает смещения. (Если новое пространство имен времени еще не вступило в процесс, его можно изменить. Здесь оно не будет расширено. Заинтересованные друзья могут оставить сообщение в области обсуждения для обмена и обсуждения.)
Следует отметить, что в начальном пространстве имен времени все смещения, отображаемые в /proc/self/timens_offsets, равны 0.
(MoeLove) ➜ cat /proc/self/timens_offsets
monotonic 0 0
boottime 0 0
Значения второго и третьего столбцов следующие:
- Может быть отрицательным, единица измерения: секунда (с)
- беззнаковое значение в наносекундах (нс)
Следующие интерфейсы часов связаны с этим пространством имен:
-
clock_gettime(2)
-
clock_nanosleep(2)
-
nanosleep(2)
-
timer_settime(2)
-
timerfd_settime(2)
В целом пространства имен времени полезны в некоторых особых сценариях.
User namespaces
Пространства имен пользователей, как следует из названия, изолируют идентификаторы пользователей, идентификаторы групп и т. д.
Использование пространств имен пользователей требует, чтобы ядро поддерживало опцию CONFIG_USER_NS. Такие как:
➜ local_time grep CONFIG_USER_NS /boot/config-$(uname -r)
CONFIG_USER_NS=y
Идентификатор пользователя и идентификатор группы процесса могут различаться внутри и вне пространства имен пользователя.
Например, пользователь и группа процесса в пользовательском пространстве имен могут быть привилегированным пользователем (root), но за пределами пользовательского пространства имен могут быть обычным непривилегированным пользователем. Это включает сопоставление пользователей, групп (uid_map, gid_map) и другой связанный контент.
Начиная с ядра Linux v3.5,/proc/[pid]/uid_map
и/proc/[pid]/gid_map
В файле мы можем просмотреть содержимое сопоставления.
(MoeLove) ➜ cat /proc/self/uid_map
0 0 4294967295
(MoeLove) ➜ cat /proc/self/gid_map
0 0 4294967295
Пространство имен пользователя также поддерживает вложенность, которая создается с помощью флага CLONE_NEWUSER и системных вызовов, таких как unshare(2) или clone(2).Максимальный уровень вложенности — 32.
Если дочерний процесс, созданный fork(2) или clone(2), не имеет флага CLONE_NEWUSER, то же самое верно, дочерний процесс находится в том же пользовательском пространстве имен, что и родительский процесс. Древовидная связь также поддерживается через интерфейс системного вызова ioctl(2).
Однопоточный процесс может настроить свое пользовательское пространство имен с помощью системного вызова setns(2).
Кроме того, пространство имен пользователей имеет очень важное правило, а именно отношения наследования возможностей Linux. Я не буду распространяться о возможностях Linux, вот краткая запись:
-
Когда пространство имен пользователя, в котором находится процесс, имеет возможность в наборе эффективных возможностей, процесс имеет возможность.
-
Когда у процесса есть возможность в этом пользовательском пространстве имен, у процесса есть эта возможность во всех дочерних пользовательских пространствах имен этого пользовательского пространства имен.
-
Пользователь, создавший пространство имен пользователя, будет записан ядром как владелец, то есть будет иметь все возможности в пространстве имен пользователя.
Для Docker он может изначально поддерживать эту возможность, тем самым обеспечивая защиту среды контейнера.
UTS namespaces
Пространства имен UTS изолируют имена хостов и доменные имена NIS.
Использование пространств имен UTS требует поддержки ядром опции CONFIG_UTS_NS. Такие как:
(MoeLove) ➜ grep CONFIG_UTS_NS /boot/config-$(uname -r)
CONFIG_UTS_NS=y
В одном и том же пространстве имен UTS настройки и изменения, сделанные системными вызовами sethostname(2) и setdomainname(2), совместно используются и просматриваются всеми процессами, но для разных пространств имен UTS они изолированы друг от друга и невидимы.
Основной API пространств имен
В предыдущем материале упоминалось много системных вызовов, здесь мы выберем несколько важных для представления.
clone(2)
Система вызывает clone(2) для создания нового процесса, который будет реализовывать соответствующие функции конфигурации одну за другой в соответствии с настройками CLONE_NEW* в параметрах. Конечно, этот системный вызов также реализует некоторые функции, независимые от пространства имен. Для систем с ядром ниже Linux 3.8 в большинстве случаев требуется возможность CAP_SYS_ADMIN.
unshare(2)
Система вызывает unshare(2), чтобы назначить процесс новому пространству имен, а также настраивает и реализует соответствующую функцию конфигурации в соответствии с настройками CLONE_NEW* в параметрах. Для систем ниже Linux 3.8 в большинстве случаев требуется возможность CAP_SYS_ADMIN.
setns(2)
Системный вызов setns(2) перемещает процесс в существующее пространство имен, что приводит к изменению содержимого каталога, соответствующего /proc/[pid]/ns. Дочерний процесс, созданный процессом, может настроить пространство имен, к которому он принадлежит, вызвав unshare(2) и setns(2). Обычно для этого требуется возможность CAP_SYS_ADMIN.
Некоторые ключевые описания каталогов
/proc/[pid]/ns/ каталог
У каждого процесса есть подкаталог /proc/[pid]/ns/, на содержимое которого влияет системный вызов setns(2). Пока файл в каталоге открыт, соответствующее пространство имен не может быть уничтожено. Система может изменить содержимое этих файлов, вызвав setns(2).
- Linux 3.7 и более ранние версии — файлы жестко связаны;
- Начиная с Linux 3.8 - файл существует в виде мягкой ссылки;
(MoeLove) ➜ ls -l --time-style='+' /proc/$$/ns
总用量 0
lrwxrwxrwx. 1 tao tao 0 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx. 1 tao tao 0 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx. 1 tao tao 0 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx. 1 tao tao 0 net -> 'net:[4026532008]'
lrwxrwxrwx. 1 tao tao 0 pid -> 'pid:[4026531836]'
lrwxrwxrwx. 1 tao tao 0 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx. 1 tao tao 0 time -> 'time:[4026531834]'
lrwxrwxrwx. 1 tao tao 0 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx. 1 tao tao 0 user -> 'user:[4026531837]'
lrwxrwxrwx. 1 tao tao 0 uts -> 'uts:[4026531838]'
Если пространства имен двух процессов совпадают, то содержимое их каталога должно быть одинаковым.
Ниже приводится подробное описание файлов в этом каталоге:
имя файла | начальная версия | описывать |
---|---|---|
/proc/[pid]/ns/cgroup | Linux 4.6 | Пространство имен cgroup процесса |
/proc/[pid]/ns/ipc | Linux 3.0 | Пространство имен IPC процесса |
/proc/[pid]/ns/mnt | Linux 3.8 | Пространство имен монтирования процесса |
/proc/[pid]/ns/net | Linux 3.0 | сетевое пространство имен процесса |
/proc/[pid]/ns/pid | Linux 3.8 | Пространство имен PID процесса является постоянным на протяжении всего жизненного цикла процесса. |
/proc/[pid]/ns/pid_for_children | Linux 4.12 | Пространство имен PID дочернего процесса, созданного процессом, не обязательно совпадает с /proc/[pid]/ns/pid. |
/proc/[pid]/ns/time | Linux 5.6 | пространство имен времени процесса |
/proc/[pid]/ns/time_for_children | Linux 5.6 | Пространство имен времени, в котором процесс создает дочерний процесс. |
/proc/[pid]/ns/user | Linux 3.8 | пользовательское пространство имен процесса |
/proc/[pid]/ns/uts | Linux 3.0 | пространство имен UTS процесса |
/proc/sys/каталог пользователя
Файлы в каталоге /proc/sys/user записывают соответствующие ограничения для каждого пространства имен. Когда лимит будет достигнут, соответствующий вызов сообщит об ошибке ENOSPC.
имя файла | Описание контента с ограниченным доступом |
---|---|
max_cgroup_namespaces | Максимальное количество пространств имен cgroup, которое может создать каждый пользователь в пользовательском пространстве имен. |
max_ipc_namespaces | Максимальное количество пространств имен ipc, которое может создать каждый пользователь в пользовательском пространстве имен. |
max_mnt_namespaces | Максимальное количество пространств имен монтирования, которое может создать каждый пользователь в пространстве имен пользователя. |
max_net_namespaces | Максимальное количество сетевых пространств имен, которое может создать каждый пользователь в пользовательском пространстве имен. |
max_pid_namespaces | Максимальное количество пространств имен PID, которые каждый пользователь может создать в пространстве имен пользователя. |
max_time_namespaces | Linux 5.7 максимальное количество пространств имен времени, которое может создать каждый пользователь в пользовательском пространстве имен |
max_user_namespaces | Максимальное количество пространств имен пользователей, которое может создать каждый пользователь в пространстве имен пользователей. |
max_uts_namespaces | Максимальное количество пространств имен uts, которые каждый пользователь может создать в пространстве имен пользователя. |
Жизненный цикл пространства имен
Жизненный цикл нормального пространства имен связан с завершением и уходом последнего процесса.
Но бывают случаи, когда пространство имен не может быть уничтожено, даже если последний процесс завершился. Вот небольшой разговор об этих особых случаях:
-
/proc/[pid]/ns/*
Файл открывается или монтируется и не может быть уничтожен, даже если завершается последний процесс; -
Пространство имен является многоуровневым, а подпространство имен все еще существует.Даже если последний процесс завершается, его нельзя уничтожить;
-
Пользовательское пространство имен имеет некоторые непользовательские пространства имен (такие как пространство имен PID и другие пространства имен), даже если последний процесс завершается, его нельзя уничтожить;
-
Для пространства имен PID, если оно совпадает с
/proc/[pid]/ns/pid_for_children
Когда есть ассоциативное отношение, даже если последний процесс завершается, он не может быть уничтожен;
Конечно, есть и другие ситуации, которые будут добавлены, когда у меня будет время.
Суммировать
В предыдущей статье и этой статье я в основном представил процесс разработки пространства имен Linux, основные типы, основные API и некоторые сценарии использования и применения.
Пространство имен — очень важная часть контейнерной технологии. В последующих сериях мы продолжим рассказывать вам о таких технологиях, как контейнеры и Kubernetes, так что следите за обновлениями.
Добро пожаловать, чтобы подписаться на мой публичный аккаунт статьи [MoeLove]