«Kubernetes приносит безопасность на новой границе, где инфраструктура становится кодом. Главная проблема — не в самих механизмах, а в том, что их применяют отрывочно, не выстраивая целостную оборону по принципу слоёной защиты.»
Поверхность атаки в Kubernetes гораздо шире, чем кажется
Типичный взгляд на безопасность кластера сводится к изоляции Worker-узлов и настройке RBAC. Это важные шаги, но они охватывают лишь часть возможных векторов. Поверхность атаки Kubernetes состоит из нескольких взаимосвязанных уровней:
- Конфигурация самого кластера: параметры API Server, etcd, kubelet.
- Сетевые политики (Network Policies): изоляция трафика между подами внутри кластера.
- Взаимодействие с образами контейнеров: уязвимости, сигнатуры, сканирование.
- Runtime-безопасность: контроль действий запущенных контейнеров.
- Конфигурация безопасности пода (Pod Security): Security Context и Security Policies.
- Управление секретами: хранение и доступ к чувствительным данным.
Настройка одного уровня без учёта других создаёт бреши. Атака, начавшись с уязвимости в образе контейнера, может через скомпрометированный под перейти на узел, а оттуда — в другие неймспейсы или в etcd.
Упущение №1: Неадекватная изоляция уровня Runtime
Подавляющее большинство развёртываний полагается на базовые возможности контейнеризации, не используя механизмы, которые резко сужают возможности потенциального злоумышленника внутри контейнера.
Security Context и возможности Linux
Security Context в манифесте пода, это минимальная, но критически важная настройка.
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
seccompProfile:
type: RuntimeDefault
Ключевые моменты:
- runAsNonRoot: Запрещает запуск пода от имени root, что является базовой практикой.
- capabilities.drop: Убирает все привилегированные возможности (capabilities), а затем добавляет только необходимые минимальные (например, NET_BIND_SERVICE для веб-сервера).
- allowPrivilegeEscalation: false: Блокирует возможность для процессов внутри пода повысить свои привилегии, даже если есть уязвимость в SUID-бинарнике или другом механизме.
- seccompProfile: Применяет дефолтный профиль seccomp, который ограничивает множество системных вызовов, доступных контейнеру.
Эти настройки часто опускают, особенно в Helm-чартах сторонних приложений, что оставляет контейнеры с избыточными правами.
AppArmor и SELinux — забытые оболочки
Если seccomp работает на уровне системных вызовов, то AppArmor и SELinux добавляют ещё один уровень контроля на основе путей к файлам, прав доступа и возможностей процессов. В Kubernetes можно применять готовые или кастомные профили AppArmor к подам. Профиль, запрещающий запись в каталоги, не предназначенные для данных приложения, или блокирующий выполнение посторонних бинарников, способен остановить многие виды атак на этапе выполнения. В российских окружениях чаще встречается SELinux, чью политику также можно адаптировать для контейнеров, хотя это требует большей подготовки.
Упущение №2: Сетевая изоляция «по умолчанию запрещено»
Сетевые политики (Network Policies) в Kubernetes, это stateful firewall на уровне pod’ов. Главная ошибка — их отсутствие или политика «разрешить всё». Идеальная начальная точка — политика «по умолчанию запрещено» (default-deny).
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
Эта политика, применённая ко всему неймспейсу, блокирует весь входящий трафик к подам. После этого вы явно разрешаете только необходимые соединения между компонентами. Например, разрешаете доступ к подам frontend только от ingress-контроллера, а к подам backend — только от frontend и из определённого CIDR админской сети. Такой подход резко сокращает поверхность для lateral movement внутри кластера.
Упущение №3: Игнорирование политик безопасности пода (PSP и их наследники)
Pod Security Policies (PSP) устарели, но их идея жива в новых механизмах: Pod Security Admission (PSA) и сторонних валидаторах, таких как Kyverno или OPA Gatekeeper. Суть в том, чтобы централизованно задавать требования к безопасности всех пода в кластере или неймспейсе, не полагаясь на сознательность разработчиков.
Pod Security Admission использует встроенные в Kubernetes Labels для неймспейсов и определяет три уровня: privileged, baseline и restricted. Наиболее строгий уровень restricted требует соблюдения всех современных практик, включая запрет root, отказ от привилегий и использование seccomp. Настройка уровня restricted для рабочих неймспейсов автоматически отклоняет или предупреждает о подах с небезопасными настройками.
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
Это простейший способ внедрить базовый стандарт безопасности, который многие пропускают.
Упущение №4: Работа с секретами как с конфигами
Secret в Kubernetes — не шифрованный объект, а закодированный в base64. Он хранится в etcd в открытом виде, если не включено шифрование на уровне etcd. Даже с шифрованием, секрет доступен в виде plaintext любому поду, которому он смонтирован или передан как переменная окружения.
Критические упущения:
- Нет ротации секретов: Пароли и токены живут годами.
- Секреты в логах и переменных окружения: При аварийном дампе переменные окружения могут попасть в логи.
- Отсутствие интеграции с внешними Vault: Такие системы, как HashiCorp Vault или его аналоги, предоставляют динамические секреты, аудит и автоматическую ротацию.
Подход «хранить секреты в Kubernetes Secrets и обновлять их вручную» не соответствует требованиям регуляторики 152-ФЗ, где необходимы контроль доступа и учёт операций.
Упущение №5: Слепота к событиям кластера и аудит
API Server Kubernetes ведёт детальный аудит событий: кто, когда и что сделал с каким объектом. По умолчанию политика аудита часто настроена минимально или логи теряются в общем потоке системных логов.
Для соответствия требованиям необходимо:
- Настроить политику аудита, которая записывает события создания, изменения и удаления критических объектов (Secrets, ConfigMaps, Roles, Pods).
- Направлять аудит-логи в защищённое внешнее хранилище (не в etcd), куда у привилегированных пользователей кластера нет прямого доступа.
- Реализовать мониторинг и алертинг на подозрительные события: массовое создание подов, попытки доступа к Secrets из неожиданных неймспейсов или service accounts.
Без этого вы не сможете обнаружить и восстановить ход компрометации.
Практический чеклист: с чего начать усиление
Не пытайтесь внедрить всё сразу. Двигайтесь от наиболее критичных и простых в реализации пунктов.
| Приоритет | Область | Действие |
|---|---|---|
| Высокий | Конфигурация пода | Во всех манифестах добавить runAsNonRoot: true и allowPrivilegeEscalation: false. |
| Высокий | Сетевая безопасность | Применить политику default-deny-ingress ко всем production-неймспейсам. |
| Высокий | Управление доступом | Проверить и ограничить права service accounts, особенно default в каждом неймспейсе. |
| Средний | Безопасность образов | Внедрить сканирование образов в CI/CD на уязвимости и внедрить политики (например, запрет образов с critical-уязвимостями). |
| Средний | Политики безопасности | Включить Pod Security Admission на уровне restricted для ключевых неймспейсов. |
| Средний | Аудит | Настроить и вынести в отдельную систему логи аудита Kubernetes API Server. |
| Низкий | Runtime-защита | Рассмотреть внедрение специализированных инструментов (Falco, Tracee) для детектирования аномалий. |
Каждое из этих упущений не является фатальным само по себе, но их совокупность превращает кластер в хрупкую конструкцию. Безопасность Kubernetes требует не единичного действия, а режима постоянного контроля и адаптации политик под меняющуюся среду. Начните с базиса — минимальных привилегий и явного разрешения сетевых правил — и постепенно наращивайте глубину защиты.