Что изолируется между контейнерами
Что проверяют
Понимаете ли вы, что контейнер это не виртуальная машина, а обычный процесс с ограничениями ядра, и можете ли назвать, какой механизм за что отвечает. Ответ уровня «контейнеры изолированы друг от друга» закрывает тему не в вашу пользу.
Как отвечать
Разделить на два разных механизма.
Пространства имён отвечают за видимость:
mnt: своё дерево файловой системы, корень собран из слоёв образа;pid: своя нумерация процессов, главный процесс контейнера видит себя первым;net: свои интерфейсы, адреса, маршруты и диапазон портов;ipc,utsдля имени хоста,userдля отображения идентификаторов,cgroup,time.
Контрольные группы отвечают за количество: лимиты процессорного времени, памяти, числа процессов, дискового ввода и вывода. Сверху идут средства безопасности: урезанный набор capabilities, профиль seccomp, обязательные политики AppArmor или SELinux, корень только для чтения.
Главное, что стоит произнести вслух: ядро общее, поэтому граница слабее, чем у виртуальной машины.
Для Go важно следствие: рантайм по умолчанию видит процессоры хоста, а не квоту группы, поэтому GOMAXPROCS оказывается завышенным и растёт задержка из-за вытеснения. Лимит памяти рантайм тоже сам не читает, сборщик не успевает, процесс убивают по нехватке памяти. Лечится явной установкой GOMAXPROCS и GOMEMLIMIT.
Где спотыкаются
Называют контейнер лёгкой виртуальной машиной. Гипервизора нет, системные вызовы идут в общее ядро, и уязвимость ядра пробивает границу сразу для всех контейнеров узла.
Считают, что изолировано всё. Ядро и его модули общие, значительная часть параметров /proc/sys тоже, а запуск в привилегированном режиме, проброс сокета демона или монтирование каталогов хоста убирают границу полностью.
Забывают, что без лимитов контейнер видит ресурсы всей машины. Квота процессора ограничивает время, а не число видимых ядер, поэтому nproc внутри показывает ядра хоста, приложение поднимает по этому числу пулы потоков и упирается в квоту, получая рваные задержки вместо ожидаемой скорости.