Назад к блогу

Kubernetes 1.37: опции bind mount и режимы прав для временных томов

Kubernetes 1.37: опции bind mount и режимы прав для временных томов

В Kubernetes 1.37 появились долгожданные механизмы управления безопасностью временных томов: флаги bind mount и настройка прав доступа к каталогам. Теперь администраторы могут запретить выполнение бинарников, использование специальных устройств и смену привилегий на смонтированных томах, а также гибко управлять правами доступа вместо жёстко заданного режима 0777. Эти изменения закрывают пробелы в безопасности, которые годами обходили через init-контейнеры с chmod, и делают соответствие требованиям аудита значительно проще.

В Kubernetes 1.37 появились две возможности, закрывающие давно отмеченные пробелы в безопасности хранилищ: опции bind mount и режимы прав создания каталогов для временных томов. Обе выходят в статусе Alpha и по умолчанию выключены — их нужно включать feature gate.

Раньше тома монтировались в контейнеры через bind mounts без флагов noexec, nosuid и nodev, а временные тома создавали каталоги с жёстко заданным режимом 0777. Изменить это нативно было нельзя — приходилось либо мириться, либо городить init-контейнеры с chmod.

Что именно изменилось

Bind mount options. В манифесте Pod появилось поле, которое применяет к монтированию тома security-флаги Linux bind mount. Допустимы три значения:

  • noexec — запрещает выполнение бинарников на смонтированном томе;
  • nodev — игнорирует специальные файлы устройств;
  • nosuid — игнорирует биты set-user-identifier и set-group-identifier.

Опции задаются для каждого контейнера отдельно, поэтому разные контейнеры одного Pod могут монтировать один и тот же том с разными флагами. С image volumes поле не поддерживается.

Режимы прав временных томов. В секции временного тома манифеста Pod появилось поле mode, задающее режим прав при создании тома:

emptyDir:
  mode: 01777

Режим 01777 — это sticky bit. В отличие от bind mount options, для mode поддержка контейнерного рантайма не требуется.

Если mode не задан, сохраняется прежнее поведение с правами 0777. Если в security context пода заданы групповые права, они переопределяют указанный mode. На Windows поле пропускается — там нет Unix-прав.

Предыстория

До 1.37 механизма задать noexec, nosuid или nodev на bind mount, который создаёт контейнерный рантайм для любого типа тома, не существовало. Флаги уровня файловой системы, применяемые CSI-драйвером на узле, задачу не решали: они не транслируются надёжно в bind mount внутри контейнера.

Тома временного хранения по умолчанию создавали каталоги с режимом 0777, поэтому любой процесс, обнаруживший том, мог читать, писать и удалять в нём что угодно, независимо от того, кто его создал. В многоконтейнерных подах это означало, что один контейнер не мог помешать другому удалить свои файлы. Sticky bit 01777 проблему решает, но задать его нативно было нельзя.

Обходной путь — init-контейнер, задающий другой режим доступа. Он работает и сейчас, но сложнее в настройке и трудно проверяем для комплаенса. Для sticky bit или более строгих прав вроде 0750 применяли init-контейнеры с chmod либо альтернативные типы томов.

Почему это сделали

Пробелы зафиксированы в двух issue. Issue #48912 — признанный пробел безопасности: невозможность задать mount options для временного тома была отмечена в аудите и оставалась нерешённой. Issue #119627 — аудит безопасности Kubernetes 1.24 (Finding NCC-E003660-7HM), где внешние аудиторы отдельно отметили, что невозможность смонтировать временный том с noexec, представляет собой отказ безопасности.

Мотивирующие сценарии:

  • Предотвращение повышения привилегий. Разработчик монтирует временные рабочие тома (временный том или /tmp) с nosuid и noexec, чтобы скомпрометированное приложение не могло выполнить загруженную полезную нагрузку или повысить привилегии на узле. Без noexec процесс мог скачать бинарник, сделать chmod +x и запустить его даже при readOnlyRootFilesystem: true.
  • Общее рабочее пространство в многоконтейнерных подах CI/CD. mode: 01777 делает общий каталог похожим на традиционный Unix /tmp: каждый контейнер пишет независимо, но скомпрометированный процесс в одном контейнере не может удалить артефакты другого.
  • Принцип наименьших привилегий. mode: 0750 на временном томе у пода с базой данных даёт доступ только конкретному пользователю и группе БД, явно запрещая чтение и запись другим процессам и сайдкарам в том же поде.

Что это меняет на практике

Обновлять существующие манифесты не нужно: обе возможности аддитивны, а без новых полей поведение остаётся прежним, включая права 0777. Обе доступны как Alpha в 1.37 и по умолчанию выключены — чтобы ими пользоваться, администратор кластера включает соответствующие гейты на API-сервере и kubelet.

Обратная совместимость при рассинхронизации версий различается для двух возможностей:

  • Для режима прав томов: если gate включён на API-сервере, но не на kubelet, поле принимается, но игнорируется — kubelet откатывается к 0777.
  • Для опций bind mount: планировщик использует node declared features. Если под всё же попадёт на узел без поддержки рантайма, kubelet его отклонит — тихой деградации нет.

Для эксплуатации важно, что опции bind mount требуют поддержки со стороны контейнерного рантайма: если он её не заявляет, kubelet отклоняет поды, использующие опции bind mount. Для режима прав томов поддержка рантайма не нужна.

Проверить, что ограничения реально применяются, можно изнутри контейнера. На томе с noexec попытка запустить скрипт даёт sh: ./test.sh: Permission denied — ядро отказывает в выполнении, потому что MS_NOEXEC применяется на уровне bind mount. Для sticky bit проверка прав каталога показывает drwxrwxrwt, а попытка удалить файл, созданный другим пользователем, завершается rm: can't remove '/tmp/guest_file': Operation not permitted.

Ограничения и открытые вопросы

В CSI-плагине остаются известные ограничения. Сопоставление режимов доступа между Kubernetes и CSI помечено как требующее улучшения, и из списка режимов берётся только первый элемент. Период ресинхронизации описан как значение по умолчанию с пометкой, что его стоит увеличить до чего-то полезного.

Взаимодействие с CSI-драйверами зависит от их возможностей. Применение FSGroup делегируется драйверу, если он сообщает о наличии capability VOLUME_MOUNT_GROUP — то есть о том, что драйвер сам умеет применять групповое владение и права на томе; в этом случае Kubernetes не меняет владельца и права, и политика смены владельца и прав тома не действует. Монтирование с SELinux-меткой выполняется только при включённом feature gate SELinuxMountReadWriteOncePod и поддержке со стороны драйвера.

Отдельно от этих двух возможностей в 1.37 появилась ещё одна, связанная с томами, которые используют память узла: изменение предельного размера у таких томов без перезапуска Pod или его контейнеров. Она тоже Alpha с 1.37, выключена по умолчанию и требует включения соответствующего feature gate для всех соответствующих компонентов кластера.

Источники

Похожее