itmo_conspects

Extra 2. Механизмы контейнеризации

Контейнеризация - это метод виртуализации на уровне операционной системы, позволяющий запускать приложения в изолированных окружениях, которые называют контейнерами

В отличие от виртуальных машин, которые эмулируют аппаратное обеспечение, контейнеры используют ядро хостовой системы, что делает их значительно более легковесными и быстрыми в запуске

В операционной системе Linux контейнеризация возможна с помощью этих механизмов:

  1. Пространства имён (Namespaces) отвечают за изоляцию процессов, создавая иллюзию того, что контейнер владеет собственным экземпляром системы
  2. Контрольные группы (cgroups) отвечают за ограничение и учёт ресурсов, потребляемых группой процессов
  3. И других, таких как объединённые файловые системы

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

Пространства имён - это механизм ядра, который изолирует и виртуализирует глобальные системные ресурсы. Процессы внутри одного пространства имён видят свой собственный изолированный набор этих ресурсов и не могут влиять на процессы в других пространствах имён или видеть их

Linux поддерживает несколько типов пространств имён, каждый из которых изолирует определённый аспект системы:

  1. Cgroup - изолирует корневую директорию контрольных групп, чтобы процесс в контейнере видел свою иерархию контрольных групп.
  2. IPC (от Inter-Process Communication) - изолирует ресурсы для межпроцессного взаимодействия (такие как очереди сообщений или разделяемая память)
  3. Network - изолирует сетевые устройства, стеки, порты и таблицы маршрутизации
  4. Mount - изолирует точки монтирования файловых систем
  5. PID (от Process ID) изолирует пространство идентификаторов процессов. Процесс внутри контейнера видит только свои процессы и считает, что его идентификатор равен 1, а не реальному идентификатору на хосте
  6. Time - изолирует системное время, позволяя контейнеру иметь своё представление о времени (появилось в Linux 5.6)
  7. User - изолирует идентификаторы пользователей и групп, что позволяет процессу в контейнере быть пользователем root внутри контейнера
  8. UTS (от UNIX Time-Sharing System) - изолирует имена хоста и домена NIS (Network Information Service, системы для распространения конфигурации между несколькими узлами)

Самый простой способ создать пространств имён - это использовать утилиту unshare. Она запускает программу в новых, изолированных пространствах имён. Например, для создания пространства UTS используется команда:

sudo unshare --uts /bin/bash

Далее командой hostname <новое имя хоста> можно задать другое имя. Для создания других пространств используются флаги --ipc, --mount, --net, --pid, --uts, --user, --cgroup, --time

Важно заметить, что для создания пространства PID нужно использовать флаг --fork, иначе просто изменится псевдофайловая система /proc

Контрольные группы

Контрольные группы позволяют ограничивать, приоритизировать и учитывать использование таких ресурсов, как центральный процессор, память, ввод/вывод диска и сеть

Существует две версии контрольных групп:

Начиная с Linux 5.10, вторая версия является предпочтительной, и многие современные дистрибутивы используют её по умолчанию

Все операции с контрольными группами второй версии производятся через псевдофайловую систему cgroup2, которая обычно смонтирована в /sys/fs/cgroup

Далее, чтобы создать контрольную группу, нужно:

  1. Создать директорию для новой группы:

     sudo mkdir /sys/fs/cgroup/my-group
    

    Созданная директория наполнится нужными файлами. Группы могут выстраивать иерархию с наследованием ограничений

  2. Настроить лимиты в нужных файлах

  3. Запустить процесс и поместить его в группу - для этого нужно записать идентификатор процесса в файл cgroup.procs:

     echo $APP_PID | sudo tee /sys/fs/cgroup/my-group/cgroup.procs
    

Всего контроллеров во второй версии контрольных групп девять:

Список доступных контроллеров можно узнать в файле /sys/fs/cgroup/cgroup.controllers. Чтобы добавить контроллер, можно воспользоваться командой:

echo "+cpu" | sudo tee /sys/fs/cgroup/cgroup.subtree_control

Управлять списком контроллеров можно в каждой группе, выстраивая иерархию. Контроллер создает нужные файлы в каталоге группы, например:

Другие механизмы изоляции

По умолчанию контейнер, созданный с изолированным сетевым пространством имён, будет полностью отрезан от сети. Чтобы обеспечить связь, необходимо создать виртуальные сетевые интерфейсы

Для этого используют veth (Virtual Ethernet) - пару виртуальных сетевых интерфейсов, которые действуют как туннель

Обычно один конец пары veth1 помещается в сетевое пространство имён контейнера, а другой veth0 остаётся на хосте или подключается к сетевому мосту

Чтобы контейнер имел доступ к внешней сети, на хосте необходимо настроить трансляцию адресов - это позволит контейнеру выходить в интернет через IP-адрес хоста


Для изоляции файловой системы внутри используются два основных системных вызова:


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

Одна из первых реализаций была UnionFS. Сейчас используют OverlayFS, которая устроена через три слоя:

Для обеспечения атомарности операций используется 4-ый каталог workdir

Когда процесс читает файл из merged, OverlayFS сначала ищет его в upperdir. Если его там нет, то файл ищется в lowerdir. Все операции записи (создание, изменение, удаление) всегда происходят только в upperdir

Создать объединенную файловую систему можно с помощью команды mount:

sudo mount -t overlay overlay \
  -o lowerdir=$HOME/overlayEX/lower,upperdir=$HOME/overlayEX/upper,workdir=$HOME/overlayEX/work \
  $HOME/overlayEX/merged

Сейчас на практике используют Docker - платформу контейнеризации, которая упрощает работу с пространствами имён, контрольными группами и объединёнными файловыми системами