Kubernetes v1.37 представляет важные функции безопасности хранилищ: режимы прав доступа для emptyDir и параметры bind mount. Они помогают разработчикам приложений и специалистам по безопасности внедрять строгие политики безопасности, например, запрет на удаление файлов между контейнерами или выполнение произвольных бинарных файлов из доступных для записи томов, непосредственно в Kubernetes без сложных обходных путей.
Основы работы с хранилищами и правами доступа в Linux
Прежде чем углубляться в новые функции Kubernetes, давайте кратко рассмотрим низкоуровневые механизмы безопасности Linux, которые делают их возможными.
Флаги bind mount
Когда Linux монтирует или перемонтирует каталог, флаги виртуальной файловой системы (VFS) контролируют, какие действия разрешены в этой файловой системе:
- noexec: запрещает прямое выполнение любых бинарных файлов в смонтированной файловой системе.
- nosuid: запрещает использование битов set-user-identifier или set-group-identifier.
- nodev: запрещает интерпретацию специальных символьных или блочных устройств в файловой системе.
Права доступа к каталогам и sticky bit
Стандартные права доступа Unix регулируют доступ в трех областях: владелец, группа и остальные (например, 0755 или 0777).
Помимо стандартных битов чтения, записи и выполнения, Linux поддерживает sticky bit (например, в режиме 01777). При применении к каталогу sticky bit гарантирует, что файл внутри этого каталога может быть удален или переименован только владельцем файла или пользователем root. Это критически важно для общих каталогов с правами записи, таких как /tmp.
Мотивация для улучшений
Почему Kubernetes нуждается в параметрах bind mount и правах доступа для emptyDir?
Основная цель этих функций — повысить безопасность рабочих нагрузок Kubernetes за счет разрешения параметров bind mount, связанных с безопасностью, при монтировании томов. По умолчанию тома монтируются в контейнеры средой выполнения контейнеров и kubelet без флагов noexec, nosuid или nodev. Это значение по умолчанию может снижать уровень безопасности. Например, при отсутствии noexec скомпрометированный процесс может использовать любой доступный для записи том (emptyDir, PersistentVolume и т. д.) для загрузки, выполнения chmod +x и запуска произвольных бинарных файлов, даже если у контейнера файловая система root доступна только для чтения (readOnlyRootFilesystem: true). Поддержка noexec, nodev и nosuid дает пользователям встроенный способ усилить защиту монтируемых томов в соответствии со стандартами безопасности и политиками.
Этот пробел наиболее заметен в томах emptyDir, которые являются наиболее распространенным типом доступных для записи томов и неоднократно становились объектом замечаний по безопасности:
- Проблема №48912: Признанный пробел в безопасности — невозможность установки параметров монтирования для emptyDir была отмечена в аудите, но оставалась нерешенной до сих пор.
- Проблема №119627: Аудит безопасности Kubernetes 1.24 (находка NCC-E003660-7HM) — внешние аудиторы особо отметили, что невозможность смонтировать emptyDir с параметром noexec представляет собой уязвимость безопасности.
Однако этот же пробел касается всех типов томов. PersistentVolumes имеют поле mountOptions, но эти параметры являются флагами уровня файловой системы, применяемыми драйвером CSI на узле, поэтому они не транслируются надежно в флаги bind mount внутри контейнера. Ранее не существовало механизма установки noexec, nosuid или nodev для bind mount, который среда выполнения контейнера создает для любого типа тома.
Кроме того, тип тома emptyDir по умолчанию создает каталоги с жестко заданным режимом 0777. Ранее это означало, что любой процесс, который может обнаружить том, мог читать, записывать и удалять все, что находится в томе, независимо от того, кто его создал.
Вы могли — и до сих пор можете — использовать инициализационный контейнер (init container) для установки другого режима доступа, но это сложнее и трудно поддается проверке на соответствие требованиям.
Это вызывает реальные проблемы:
- Поды с несколькими контейнерами, использующие общий emptyDir, не могли предотвратить удаление файлов одного контейнера другим. Sticky bit (01777) решает эту проблему, но не было встроенного способа его установки.
- Некоторые приложения и фреймворки безопасности ожидают, что каталоги /tmp будут иметь установленный sticky bit (режим 01777). Без встроенной поддержки установки режима emptyDir пользователям приходилось использовать init-контейнеры или альтернативные типы томов для выполнения этого требования.
- Инженерам платформ, которым нужны более строгие права доступа (например, 0750 только для владельца и группы), приходится использовать init-контейнеры, запускающие chmod, что добавляет ненужную сложность.
Тип тома emptyDir был заметным пробелом. Будучи одним из самых распространенных типов записываемых томов в Kubernetes, он не имел возможности контролировать права доступа при создании.
Реальные сценарии использования
Разработчики приложений, тесно сотрудничая с инженерами по безопасности, несут ответственность за поддержание уровня безопасности своих приложений и обеспечение того, чтобы рабочие нагрузки не создавали рисков для инфраструктуры в целом. Эти функции позволяют командам разработки уверенно решать критические задачи безопасности:
Предотвращение повышения привилегий на монтируемых томах с правами записи: Разработчик приложения, настраивающий временные рабочие тома (например, emptyDir или монтирования /tmp), может гарантировать, что они смонтированы с параметрами nosuid и noexec. Это гарантирует, что даже если приложение будет скомпрометировано и будет загружена вредоносная полезная нагрузка, рабочая нагрузка не сможет выполнить ее или использовать для повышения привилегий на узле.
Защита общего временного пространства в подах с несколькими контейнерами: Разработчик, настраивающий поды CI/CD конвейеров, часто нуждается в том, чтобы несколько контейнеров (например, контейнер сборки и sidecar-контейнер логирования) использовали общее рабочее пространство. Установив mode: 01777 для emptyDir, разработчик гарантирует, что общее рабочее пространство ведет себя как традиционный каталог /tmp в Unix. Каждый контейнер может независимо записывать файлы, но скомпрометированный процесс в одном контейнере не сможет удалить артефакты сборки, созданные другим.
Применение принципа наименьших привилегий для данных приложения: Разработчик приложения, развертывающий под базы данных, может ограничить доступ к временному хранилищу базы данных. Установив mode: 0750 для emptyDir, разработчик гарантирует, что только конкретный пользователь и группа базы данных могут читать или записывать данные в том, явно запрещая доступ любым другим процессам или sidecar-контейнерам в том же поде.
Примечание: Обе функции находятся за Alpha feature gates в Kubernetes v1.37. Чтобы использовать их, включите VolumeBindMountOptions и EmptyDirVolumeMode на сервере API и kubelet.
Пример 1: Принудительное применение параметров bind mount
Этот полный манифест пода монтирует том emptyDir в /tmp с параметрами bindMountOptions: [noexec, nosuid].
Пример 2: Режим прав доступа тома emptyDir со sticky bit
Этот полный манифест создает том emptyDir с использованием режима mode: 01777 для обеспечения стандартной защиты Unix /tmp sticky bit между контейнерами.
Проверка функций в Linux
Чтобы убедиться, что эти функции активно обеспечивают ограничения, вы можете выполнить kubectl exec внутри контейнера. Следующие примеры имитируют попытки выполнения действий, которые успешно блокируются этими функциями.
Проверка noexec
Попытка записать и запустить скрипт на томе, смонтированном с noexec:
Ожидаемый результат:
Даже если исполняемый файл создан, ядро Linux отказывает в выполнении, поскольку MS_NOEXEC применяется на уровне bind mount.
Проверка sticky bit
Попытка удалить файл другого пользователя в emptyDir с режимом доступа 01777:
Ожидаемый результат:
Ядро блокирует удаление, поскольку бита липкости (sticky bit, 01777) разрешает удаление файлов строго только их владельцу.
Что нужно знать
Держите в уме эти ключевые детали, когда наччнете использовать данные функции. Полная информация доступна в официальной документации по параметрам привязанных монтирований (bind mount options), режиму томов emptyDir и томам emptyDir.
- Поведение по умолчанию не изменилось: если вы опустите параметр bindMountOptions или не укажете режим emptyDir, вы получите стандартное поведение по умолчанию (например, права 0777) точно так же, как и раньше.
- Широкая поддержка томов: bindMountOptions работает с emptyDir, PersistentVolumes, томами CSI, проектными томами (projected volumes), ConfigMaps, Secrets и другими. Единственным исключением являются тома образов (image volumes), для которых поддержка явно не предусмотрена. Поле mode работает со всеми типами носителей emptyDir: default (на диске), Memory (tmpfs) и HugePages.
- Возможности среды выполнения имеют значение (для bindMountOptions): среда выполнения контейнера должна поддерживать поле CRI mount_options и заявлять о нем через runtimeFeatures. Планировщик использует заявленные узлом функции, чтобы избегать размещения подов на несовместимых узлах. Если под все же попадает на такой узел, kubelet отклоняет его. Тихого ухудшения работы не происходит. Тем не менее, использование mode для emptyDir не требует поддержки со стороны среды выполнения.
- Не путайте с mountOptions для PV: параметры mountOptions для PersistentVolume применяются на уровне хранилища через драйвер CSI. Новый параметр bindMountOptions управляет флагами привязанного монтирования (bind mount), применяемыми внутри контейнера средой выполнения. Они работают на разных уровнях и не конфликтуют.
- Взаимодействие с fsGroup: если fsGroup задана в контексте безопасности (security context) пода, групповые разрешения, применяемые fsGroup, переопределят режим, указанный для тома emptyDir. Это такое же поведение, которое существует для defaultMode на томах Secret и ConfigMap.
- Только для Linux: такие флаги, как noexec, nosuid, nodev, и режимы прав Unix — это концепции Linux. Параметр bindMountOptions не оказывает никакого влияния на узлы Windows. В Windows поле mode также пропускается для томов emptyDir, так как Windows не поддерживает права доступа к файлам в стиле Unix.
- Безопасность при несоответствии версий: обе функции являются аддитивными. Для режима emptyDir: если в API-сервере включен ограничитель (feature gate), но в kubelet нет, поле принимается, но игнорируется — kubelet возвращается к значению 0777. Для bindMountOptions: планировщик использует функции, заявленные узлом, чтобы предотвратить размещение подов на узлах без поддержки среды выполнения; если под попадает на такой узел, kubelet отклоняет его, вместо того чтобы молча игнорировать параметры.
- Финчи (Feature Gates): обе возможности доступны в качестве функций альфа-версии в Kubernetes v1.37: VolumeBindMountOptions: управляет флагами привязанного монтирования на томах. EmptyDirVolumeMode: управляет режимами прав создания для томов emptyDir.
- VolumeBindMountOptions: управляет флагами привязанного монтирования на томах.
- EmptyDirVolumeMode: управляет режимами прав создания для томов emptyDir.
Как принять участие?
Эти новые функции разрабатываются силами SIG Node и SIG Storage. Подробную информацию можно найти в KEP (Kubernetes Enhancement Proposals) для этих улучшений: KEP-5855 (параметры привязанного монтирования) и KEP-5502 (режим разрешений emptyDir).
Свяжитесь с SIG Node:
- Slack: #sig-node
- Список рассылки
Свяжитесь с SIG Storage:
- Slack: #sig-storage
- Список рассылки







