Заметки о Kubernetes Security и DevSecOps

DevSecOps для самых маленьких. 4\n. Харденинг Kubernetes: как превратить алмазную броню в незеритовую

19 сентября 2026 г., 4 минуты

В Minecraft есть кожаная, железная, золотая и алмазная броня. Долгое время алмазная была топом, пока не появилась незеритовая. И вот нюанс: незеритовую нельзя скрафтить с нуля. Берёшь готовую алмазную броню, идёшь к столу кузнеца, находишь шаблон улучшения в бастионе, добываешь древние обломки в аду — и только потом собираешь всё вместе. С харденингом похожая история. Не нужно переписывать систему с нуля. Берёшь то, что уже работает, проверяешь настройки, закрываешь лишнее и оставляешь только то, что действительно нужно.

Харденинг — снижение поверхности атаки за счёт безопасной конфигурации: убрать лишние привилегии, отключить ненужные функции, ограничить доступ.

Почему дефолт — плохой ориентир
Механизмы безопасности в Kubernetes есть, но «есть» не значит «включён и настроен». Pod Security Standards ничего не требуют, пока их не применили к namespace. NetworkPolicy без поддержки в сетевом плагине (CNI) — просто YAML. RBAC с широкими правами теряет смысл. Поэтому в кластерах встречаются root-контейнеры, образы с лишними утилитами, поды без лимитов и сервисные аккаунты с избыточными правами.

Обычно это не злой умысел. Разработчику нужно запустить приложение, а временное решение становится постоянным. Первый шаг харденинга — признать, что работающая конфигурация не обязательно безопасна.

Как выглядит «подтянутый» под


apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  automountServiceAccountToken: false
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: registry.example.com/app@sha256:<digest>
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: [ALL]
      resources:
        requests: {cpu: 100m, memory: 128Mi}
        limits: {memory: 256Mi}
      volumeMounts:
        - name: tmp
          mountPath: /tmp
  volumes:
    - name: tmp
      emptyDir: {}


Что здесь происходит:

runAsNonRoot. Если атакующий получит выполнение команд в приложении, он будет не root. Это не заменяет остальную изоляцию, но сильно сужает возможности.
readOnlyRootFilesystem. Писать можно только в явно смонтированные тома (здесь emptyDir для /tmp). Проверь, что приложение не пишет логи и кэш в корень: иначе оно сломается.
allowPrivilegeEscalation: false и drop: [ALL]. Процесс не получает новых привилегий и Linux capabilities. Если нужна конкретная, верни её по одной, например NET_BIND_SERVICE.
seccompProfile: RuntimeDefault. Фильтр системных вызовов.
automountServiceAccountToken: false. Приложению, которое не ходит в API кластера, токен доступа не нужен.
requests и limits. Нужны для планирования и устойчивости: превышение лимита памяти убивает контейнер. Это защита от «съедания» ресурсов, а не от эксплойтов.
Образ по digest, а не по тегу. Тег можно переклеить, digest нет.
Отдельно про опасные вещи. privileged: true снимает большую часть изоляции, считай его близким к root на хосте. Не включай без конкретной причины. То же про hostPath, hostNetwork и hostPID: они нужны системным агентам, обычному приложению нет. Если исключение необходимо, ограничь его и запиши, зачем оно.

Про образы: distroless убирает shell и утилиты, scratch подходит для статических бинарей. Меньше образ — проще инвентаризировать зависимости, но уязвимостей это не отменяет, образы нужно обновлять.

Pod Security Standards
В Kubernetes три стандартных профиля: privileged, baseline и restricted. Restricted — хороший ориентир: требует non-root, сброса capabilities (разрешён только NET_BIND_SERVICE), seccomp и запрета privilege escalation. Read-only корневая файловая система в него не входит, её включают отдельно. Применяет профиль встроенный Pod Security Admission.

Не включай enforce сразу. Начни с audit и warn, посмотри, какие поды нарушают профиль, исправь, и только потом переключай:

kubectl label ns my-app \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted


Чем проверять
kube-bench проверяет узлы и control plane по CIS Kubernetes Benchmark. Хорошая точка старта для аудита, но результаты читай с учётом версии Kubernetes и способа развёртывания. Kubescape анализирует конфигурации и риски по фреймворкам, в том числе NSA и CISA. Trivy config и kubesec проверяют манифесты до деплоя (kubesec проверь на актуальность, Trivy закрепи по версии, см. часть 6). Проверка живого кластера и проверка манифестов в CI не заменяют друг друга, нужны оба.

Из российских решений: Deckhouse Kubernetes Platform, Kaspersky Container Security, Luntry, PT Container Security. Это не прямые аналоги: сверь, что именно входит в твою редакцию (аудит конфигураций, политики, runtime), и проверь сертификаты по реестру.

План без героизма
Запусти kube-bench на тестовом кластере и разбери, какие замечания относятся к твоей версии. Не применяй исправления механически.
Добавь в CI проверку манифестов (Trivy, Kubescape). Реши, какие нарушения блокируют релиз, а какие нужно оценивать отдельно.
Включи Pod Security Admission в режимах audit и warn, потом переходи к enforce, сначала для новых приложений.
Переведи приложения на non-root, запрети повышение привилегий, сбрось capabilities, включи read-only там, где можно. Исключения документируй.
Задай requests и limits по метрикам, обновляй образы и Kubernetes по процессу и регулярно повторяй аудит.

За кадром
Эта статья про поды. RBAC, kubelet, API-сервер и etcd — отдельная тема; kube-bench покажет, где там смотреть.

Незеритовую броню тоже не добывают за одну ночь, и она не делает бессмертным: так и одна настройка Kubernetes не защищает от всего. Начни с non-root и drop ALL, добавь проверки в CI, потом ужесточай Pod Security Standards. Не одно магическое зачарование, а несколько правильно подобранных улучшений.

Напоминаю, что статьи мы обсуждаем в Telegram-канале. Недушный ИнфоБез.

Social Media
Telegram
Powered by BS5 Simply Blog and Bludit
Navigation