Технологии Linux, лежащие в основе контейнеров

Kate

Administrator
Команда форума
Рассказываем, как благодаря использованию некоторых специальных технологий Linux, включая пространства имён и группы управления, появились контейнеры.

Технологии Linux составляют основу построения и запуска контейнерного процесса в вашей системе. Они включают:

  • Пространства имён (namespaces)
  • Контрольные группы (cgroups)
  • Seccomp
  • SELinux
f7db00082393092f7669d6d6a0fc0bcc.png

Пространства имён​

Пространства имён обеспечивают уровень изоляции, задавая контейнеру представление о том, что является его собственной файловой системой Linux. Это ограничивает то, что может видеть процесс, и, следовательно, ограничивает доступные ему ресурсы: каждый процесс (контейнер) может видеть или использовать только ресурсы, связанные с этим пространством имён. Таким образом, каждый контейнер может иметь уникальное представление о ресурсе.

В ядре Linux есть несколько пространств имён, которые используются Docker, Podman и прочими при создании контейнера:

$ docker container run alpine ping 8.8.8.8
$ sudo lsns -p 29413
NS TYPE NPROCS PID USER COMMAND
4026531835 cgroup 299 1 root /usr/lib/systemd/systemd --
switched...
4026533105 mnt 1 29413 root ping 8.8.8.8
4026533106 uts 1 29413 root ping 8.8.8.8
4026533105 ipc 1 29413 root ping 8.8.8.8
[...]

User​

Пространство имён «user» изолирует пользователей и группы внутри контейнера. Это делается путём предоставления контейнерам другого представления диапазонов UID и GID по сравнению с хост-системой. Пространство имён user позволяет программному обеспечению запускаться внутри контейнера от имени пользователя root. Но если злоумышленник взламывает контейнер, а затем перемещается на хост-машину, его UID больше не будет соответствовать пользователю root.

Mnt​

Пространство имён «mnt» предоставляет контейнерам унифицированное представление об иерархии файловой системы ОС. Вы можете найти точки монтирования для каждого контейнерного процесса в каталоге /proc/<PID>/mounts в вашей системе Linux.

UTS​

Пространство имён Unix Timesharing System (UTS) позволяет контейнерам иметь уникальное имя хоста и доменное имя. Когда вы запускаете контейнер, случайный идентификатор используется в качестве имени хоста даже при использовании тега — name. Вы можете использовать команду unshare, чтобы получить представление о том, как это работает:

$ docker container run -it --name nived alpine sh
/ # hostname
9c9a5edabdd6
/ #
$ sudo unshare -u sh
# hostname isolated.hostname
# hostname
# exit
$ hostname
homelab.redhat.com

IPC​

Пространство имён межпроцессной связи (IPC) позволяет различным процессам-контейнерам взаимодействовать, получая доступ к общему диапазону памяти или используя общую очередь сообщений:

# ipcmk -M 10M
Shared memory id: 0
# ipcmk -M 20M
Shared memory id: 1
# ipcs
---- Message Queues ----
key msqid owner perms used-bytes messages

---- Shared Memory Segments
key shmid owner perms bytes nattch status
0xd1df416a 0 root 644 10485760 0
0xbd487a9d 1 root 644 20971520 0
[...]

PID​

Пространство имён Process ID (PID) гарантирует, что процессы, запущенные внутри контейнера, изолированы от внешнего мира. Когда вы запускаете команду ps внутри контейнера, вы видите процессы, запущенные только внутри контейнера, а не на хост-компьютере. Это обеспечивается данным пространством имён.

Net​

Сетевое пространство имён позволяет контейнеру иметь своё собственное представление сетевого интерфейса, IP-адресов, таблиц маршрутизации, номеров портов и так далее. Как контейнер может взаимодействовать с внешним миром? Все создаваемые вами контейнеры подключаются к специальному виртуальному сетевому интерфейсу для связи.

Контрольные группы (cgroups)​

Группы — это фундаментальные блоки для создания контейнера. Cgroup выделяет и ограничивает ресурсы, такие как процессор, память, сетевой ввод‑вывод, которые используются контейнерами. Механизм создания контейнеров автоматически создаёт файловую систему cgroup каждого типа и устанавливает значения для каждого контейнера при запуске контейнера.

SECCOMP​

Seccomp в основном означает безопасные вычисления. Это функция Linux, используемая для ограничения набора системных вызовов, которые разрешено выполнять приложению. Профиль seccomp по умолчанию для Docker, например, отключает плюс‑минус 44 системных вызовов (доступно более 300).

Идея том, чтобы предоставлять доступ только к тем ресурсам, которые могут понадобиться контейнеру. Например, если вам не нужно, чтобы контейнер изменял время на хост‑машине, то, вероятно, вам не нужны вызовы clock_adjtime и clock_settime, и имеет смысл заблокировать их. Аналогично, вы не хотите, чтобы контейнеры изменяли модули ядра, поэтому им не нужно делать вызовы create_module, delete_module.

SELinux​

SELinux расшифровывается как security‑enhanced Linux. Если вы используете на своих хостах дистрибутивы Red Hat, SELinux включён по умолчанию. SELinux позволяет ограничить доступ приложения только к его собственным файлам и запретить доступ к ним любым другим процессам. Таким образом, если приложение скомпрометировано, это ограничит количество файлов, на которые оно может влиять или контролировать. Это достигается путём создания контекстов для файлов и процессов, а также путем определения политик, которые будут контролировать то, что процесс может видеть и изменять.

Политики SELinux для контейнеров определяются пакетом container‑selinux. По умолчанию контейнеры запускаются с меткой container_label, им разрешено читать ® и выполнять (x) в каталоге /usr и читать большую часть содержимого из каталога /etc. Метка container_var_lib_t является общей для файлов, относящихся к контейнерам.

В итоге​

Контейнеры — важнейшая часть современной ИТ‑инфраструктуры, да и просто интересная технология. Даже если ваша роль не связана непосредственно с контейнеризацией, понимание нескольких фундаментальных концепций и подходов к контейнеризации позволит вам оценить, как они могут помочь вашей организации. Тот факт, что контейнеры построены на технологиях Linux с открытым исходным кодом, делает их ещё лучше!

 
Сверху