На каких механизмах ядра Linux основана изоляция Docker-контейнеров

Ответ

Изоляция Docker-контейнеров достигается за счет комбинации двух фундаментальных механизмов ядра Linux, которые позволяют запускать процессы в изолированных окружениях, используя общее ядро хост-системы.

  1. Пространства имен (Namespaces) Namespaces обеспечивают изоляцию системных ресурсов. Каждый контейнер получает свой собственный набор ресурсов, невидимый для других контейнеров и хост-системы.

    • PID (Process ID): Изоляция процессов. Процессы внутри контейнера имеют свою собственную нумерацию, начиная с PID 1.
    • NET (Network): Изоляция сетевого стека. У контейнера свой IP-адрес, таблица маршрутизации и сетевые интерфейсы.
    • MNT (Mount): Изоляция файловой системы. Контейнер видит только свою файловую систему, смонтированную из образа.
    • UTS (UNIX Time-sharing System): Изоляция имени хоста и домена.
    • IPC (Inter-Process Communication): Изоляция межпроцессного взаимодействия.
    • User: Изоляция идентификаторов пользователей (UID/GID).
  2. Контрольные группы (Control Groups, cgroups) Cgroups отвечают за ограничение и учет потребления системных ресурсов процессами.

    • Ограничение ресурсов: Можно задать лимиты на использование CPU, оперативной памяти (RAM), дискового I/O.
    • Приоритизация: Можно управлять приоритетом процессов контейнера.
    • Учет: Cgroups собирают статистику по потреблению ресурсов.

Пример ограничения ресурсов с помощью cgroups:

Запуск контейнера, которому будет доступно не более 50% одного ядра CPU и 512 МБ оперативной памяти:

# --cpus="0.5" ограничивает использование CPU
# --memory="512m" ограничивает использование RAM
docker run --cpus="0.5" --memory="512m" -it ubuntu:latest bash

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

Ответ 18+ 🔞

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

Представь себе, что ядро линукса — это наш главный управдом, сука, на всю общагу. А Docker — это такой хитрожопый завхоз, который в этой общаге берет и отгораживает каждому жильцу (контейнеру) его собственную комнату-коробку. И жилец думает, что он один такой царь и бог в своей квартире, а на самом деле туалет-то на всех один, просто он его не видит!

И делается это двумя основными пиздюлинами:

1. Пространства имен (Namespaces) Это как будто ты каждому контейнеру даёшь свои собственные обои, свой номер на двери и наушники. Он нихуя не видит и не слышит, что творится у соседей.

  • PID (Процессы): У каждого в его коробке процессы нумеруются с единички. Он думает, что он самый первый процесс в системе, а на самом деле на хосте у него какой-нибудь 12456-й PID. Обман, блядь, чистой воды!
  • NET (Сеть): Каждому — свой личный IP-адрес, свой интернет-кабель (виртуальный, конечно). Он может там сервер поднять на 80-м порту, и другой контейнер ровно так же. Конфликтов не будет, потому что они друг друга в гробу видали, изолированы же.
  • MNT (Файловая система): Вот это вообще магия. Каждому подсовывают его личную файловую систему, собранную из образа. Он думает, что у него там корень системы (/), а на хосте это просто папка какая-то. Ёперный театр!
  • UTS (Имя хоста): Может назвать свою коробку как хочет, хоть super-puper-server, и ему похуй, что хост называется ubuntu-old-pc.
  • IPC (Общая память): Чтобы процессы из разных контейнеров не могли общаться через shared memory, как какие-нибудь шпионы.
  • User (Пользователи): Внутри контейнера у тебя может быть пользователь с UID 0 (root), а на хосте он будет мапиться на какого-нибудь UID 100999. Безопасность, мать её!

2. Контрольные группы (cgroups) А вот это уже не обман зрения, а реальный начальник-бухгалтер. Его задача — чтобы какой-нибудь жадный контейнер не сожрал все ресурсы и не положил всю систему.

  • Ограничение: Можно сказать: "Вася-контейнер, тебе — не больше 10% процессорного времени и 512 МБ оперативки. Больше — ни-ни".
  • Учёт: Считает, сколько кто сожрал. Для отчётности, блядь.
  • Приоритет: Можно какому-нибудь важному контейнеру дать больше жрать в первую очередь.

Вот тебе живой пример, как этого бухгалтера (cgroups) использовать:

# Сказали контейнеру: на процессоры не больше, чем пол-ядра, а оперативки — 512 мегов, и ни байтом больше!
docker run --cpus="0.5" --memory="512m" -it ubuntu:latest bash

И вся фишка в том, что никакой виртуализации, ёпта, нет! Все эти коробки — просто процессы, которые хитрожопо обманывают сами себя, работая напрямую с тем же самым ядром хоста. Поэтому они такие быстрые и легковесные, в рот меня чих-пых! Не то что эти монструозные виртуальные машины, которые тащат за собой своё отдельное ядро, как чемодан без ручки.