Короткий ответ
Нужно запускать контейнер от непривилегированного пользователя (runAsNonRoot), запретить привилегированный режим и повышение привилегий (allowPrivilegeEscalation: false), убрать ненужные Linux-capabilities, ограничить или полностью запретить hostPath-монтирования через PodSecurity admission/политику, и применить seccomp/AppArmor профиль, ограничивающий доступные системные вызовы.
Как это работает подробнее
контейнер по умолчанию делит ядро ОС с хостом; если процесс внутри контейнера работает как root и имеет доступ к хостовым ресурсам (hostPath с правами на запись, привилегированный режим, лишние capabilities вроде SYS_ADMIN), он получает возможность влиять на файловую систему или процессы узла, фактически выходя за пределы изоляции контейнера. Ограничение этих возможностей на уровне Pod/контейнера снижает поверхность атаки даже при компрометации самого приложения.
Пример кода
securityContext:
runAsNonRoot: true
runAsUser: 10001
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefaultЧто использовать на практике
- Практика. задают
securityContextна уровне Pod и контейнера с явным непривилегированным UID,readOnlyRootFilesystem: trueтам, где приложению не нужна запись в свою файловую систему, сбрасывают все capabilities и добавляют только необходимые; на уровне кластера применяют Pod Security Admission (профиль restricted) или политику (Kyverno/OPA Gatekeeper), которая технически не допускает создание Pod с hostPath или привилегированным режимом без явного исключения. - Проверка. Ожидаемое поведение: Pod с такой конфигурацией не запустится, если образ жёстко требует root (ошибка старта контейнера), что вынуждает пересобрать образ под непривилегированного пользователя; попытка смонтировать hostPath или включить privileged: true при включённом Pod Security Admission профиля restricted будет отклонена API-сервером ещё на этапе создания Pod — это проверяется командой kubectl apply и получением ошибки admission-контроля.
Подводные камни
- Ошибка. добавлять ограничения только в манифест одного приложения, оставляя остальные Pod'ы кластера без защиты, что не решает проблему системно; разрешать
privileged: true«временно для диагностики» и забывать убрать; не проверять реальную необходимость конкретных capabilities, оставляя избыточный набор по инерции от примера из интернета.