Контейнер под минимальными правами
Выпуск открывается вопросом к гостю: если выбрать хотя бы один паттерн из частей про безопасность и продвинутые приёмы, что обязательно изучить разработчику сервиса, которому надо запуститься в Kubernetes. Стас делит ответ на два набора разработчиков: прикладным — контейнмент и сетевая сегментация, хотя сегментация, по его словам, глубже, чем описано в книге; тем, кто строит платформы, — всё про управление доступами. Дальше сам контейнмент: если ничего специально не делать, базовый образ в Dockerfile даёт рутовые права, а один флажок — привилегированный контейнер. Инструменты из книги — запускаться не от root через runAsUser и runAsGroup, запретить эскалацию привилегий, урезать capabilities (например, отобрать открытие портов у приложения, которое с сетью не работает), вынести повышенные права в init-контейнер, если они нужны только на старте, и запретить запись на файловую систему: через диск в контейнер доставляют чужой софт.
Стас настаивает, что дело не столько в конфигурации кластера, сколько в умении приложения жить без привилегий — это сильно меняет то, как его пишут. Полный отказ выходит не всегда: некоторым инструментам нужны конкретные разрешения, и при проектировании платформы приходится разбираться, какие именно и надолго ли. Отдельная боль — механизм принудительного контроля доступа в Linux: любой найденный совет сводится к «включите permissive и не переживайте», и это работает ровно до визита коллег из SOC. В конце главы — три профиля: привилегированный по умолчанию, промежуточный baseline с запретом привилегированного режима и самый строгий restricted, который ограничивает изменение части параметров и список доступных действий; профиль выставляется аннотациями, а нарушение можно проаудировать или отклонить. К аудиту у участников скепсис: гарантированной доставки логов не бывает. Общий вывод главы — контейнер становится не только способом упаковки, но и границей безопасности; а начинается она со статических и динамических анализаторов и типовых уязвимостей из известного открытого проекта по безопасности приложений.
Доступ к API, сеть и секреты
Главу про access control ведущий предлагает сократить: она сводится к перечислению вариантов аутентификации и авторизации, а за деталями проще идти в документацию Kubernetes. Подробно разобран только RBAC: сервис-аккаунты живут по-своему и получают собственные токены, а токен по умолчанию монтируется в контейнер — авторы советуют это выключать, иначе скомпрометированное приложение, которое в API вообще не ходит, отдаёт ключ от кластера. В сетевой части по умолчанию все поды видят друг друга; Стас объясняет это вынужденным решением — иначе первичная настройка кластера была бы на порядок сложнее и превращалась бы в конфигурационный ад. Оставлять так нельзя, но первая же добавленная политика режет весь остальной доступ: плохо задокументированная особенность, на которой погорел не один человек, включая самого гостя, — контейнер за секретами работал, а доступ приложения к базе отвалился.
Сетевые политики работают не со всеми плагинами и разрешают трафик по лейблам: на картинке в книге бэкенду до базы можно, фронтенду нет. Гость добавляет, что service mesh дают куда более богатое управление политиками через собственные кастомные ресурсы, у каждого своё, потому что общей модели пока не договорились; ограничивать можно не по IP, а по доменному имени, что спасает в динамических средах, где адреса за именем меняются. Глава про конфигурацию понравилась ему меньше всего во всей книге: разобраны все варианты доставки секретов, кроме самого безопасного — когда не хранишь ничего, а секрет подставляется в команду запуска и живёт только в памяти контейнера. Разобраны зашифрованный файл в репозитории, который расшифровывает оператор; внешний менеджер секретов; решение от Mozilla из свежего техрадара, шифрующее не весь файл целиком; забор данных из Vault и sidecar. Все они кладут секрет в etcd, а это шифрование и PKI вокруг.
Контроллеры, автоскейлинг и сборка образов
Самое интересное — контроллеры: цикл согласования, подписка на события об изменении ресурсов и приведение фактического состояния к описанному, без чего декларативная модель не работает. Одному из участников это напомнило chain of responsibility, но он сам называет параллель неточной, и другой ведущий пересказывает доклад пятилетней давности с конференции по Kubernetes: микроволновку проектируют как конечный автомат, но с ростом числа состояний и переходов он перестаёт помещаться в голове; альтернатива — ортогональные оси, где отдельный контроллер держит температуру в 21 градус, влажность в 60 процентов и освещённость. Пока зоны ответственности ортогональны, всё хорошо; если два контроллера правят одно поле, состояние начинает ходить по синусоиде — это один из антипаттернов. Границу с операторами книга проводит по наличию кастомного ресурса, а цитата звучит так: оператор — контроллер, который знает два домена. На практике, по опыту гостя, операторы — крупные доменные модули со своим жизненным циклом, а контроллеры пишут на каждый чих.
Из инструментов побеждает kubebuilder с богатой документацией и примерами; оператор-фреймворк в итоге переехал на него, и участники считают правильным не тянуть две параллельные ветки. Зрителя в чате интересовало, почему не писать на голом client-go: технически можно, но informers и удобная работа с моделями дорогого стоят. В масштабировании HPA не умеет опускаться до нуля, а самое сложное — найти метрику, которая коррелирует с числом подов; KEDA подключается почти к любому источнику, например к глубине топика в Kafka, и закрывает переход от нуля. VPA гость хвалит, но память без перезапуска не отдать, поэтому приложение должно быстро стартовать — это ещё и MTTR. Сборка образов кластером выглядит спорно: пайплайн собирается из последовательных init-контейнеров с общей папкой, а на стрелке в продакшен, по мнению участников, должен стоять большой замок. Итог четырёх выпусков: Kubernetes всё больше похож на операционную систему; следующая встреча — не в понедельник, а в субботу, с ИТ-фестиваля в Казани, дальше снова голосование за книгу.
Что стоит унести с собой
- 01Минимальные права — вопрос не столько конфигурации кластера, сколько приложения: non-root, запрет эскалации, урезанные capabilities и запрет записи на диск, а повышенные права выносятся в init-контейнер на старте.
- 02Первая же сетевая политика закрывает весь остальной доступ — плохо задокументированная особенность, на которой погорели многие; политики поддерживают не все плагины, а ограничения по доменам и L7 — уже про service mesh.
- 03Самый безопасный способ доставки секретов в книге не разобран: не хранить их нигде, подставляя в команду запуска, чтобы секрет жил только в памяти контейнера — ценой зависимости от хранилища при старте.
- 04Контроллеры делят большую машину состояний на ортогональные оси; если два контроллера правят одно поле, состояние ходит по синусоиде, а оператор в книге отличается от контроллера наличием кастомного ресурса.