Как изолировать процессы друг от друга на одной машине
Что проверяют
Знаете ли вы, из каких механизмов ядра Linux собрана изоляция и где проходит её граница. Контейнер не отдельная машина, и интервьюер почти наверняка спросит, чем контейнер слабее виртуалки по безопасности и когда этого недостаточно.
Как отвечать
Разложите ответ по уровням, от лёгкого к тяжёлому:
- пользователи и права: отдельный системный пользователь на сервис, права на файлы, capabilities вместо полного root. Самый дешёвый слой, про который забывают;
- namespaces: процесс видит своё дерево PID, свою сеть, точки монтирования, hostname, IPC, а user namespace отображает root внутри на обычного пользователя снаружи. Это ответ на вопрос «что процесс видит»;
- cgroups v2: сколько процесс может потребить,
memory.max,cpu.max,pids.max, лимиты на I/O. Без них сосед выедает память всей машины; - seccomp и LSM: фильтр системных вызовов и политики SELinux или AppArmor ограничивают, что процесс может сделать, даже если выбрался из своего окружения;
- контейнеры: Docker, Podman, containerd собирают всё перечисленное в удобную упаковку. Rootless-режим снижает ущерб от побега;
- песочницы и виртуализация: gVisor перехватывает системные вызовы в пространстве пользователя, Kata Containers и Firecracker дают микро-ВМ с отдельным ядром, KVM даёт полноценную виртуалку.
Упомяните и systemd: без всяких контейнеров юнит изолируется директивами PrivateTmp=, ProtectSystem=strict, NoNewPrivileges=, DynamicUser=, MemoryMax=.
Главная мысль: контейнеры делят одно ядро, поэтому уязвимость в ядре пробивает всех соседей. Для недоверенного кода, чужих сборок и мультиарендности нужна граница с отдельным ядром.
Где спотыкаются
Называют chroot механизмом безопасности. Он меняет только корень файловой системы, и процесс с правами root из него выбирается.
Запускают контейнеры с --privileged или монтируют /var/run/docker.sock внутрь. И то и другое фактически отдаёт root на хосте.
Говорят про изоляцию, но забывают про ресурсы: без лимитов cgroups один контейнер с утечкой памяти вызывает OOM на всём узле.