ADG Оставить заявку
Блог DevOps 5 мин чтения

Kubernetes 1.24 и CIS Benchmark v1.7: усиление безопасности в продакшне

После выхода CIS Kubernetes Benchmark 1.7 обновляем кластеры клиентов: новые требования к seccomp, AppArmor, Pod Security Standards и автоматизация проверок через kube-bench в CI.

Контекст момента

CIS Kubernetes Benchmark v1.7 для Kubernetes 1.24: новые требования к seccomp, AppArmor и Pod Security Standards

CIS Benchmark для Kubernetes обновляется примерно синхронно с мажорными релизами платформы. Версия 1.7 бенчмарка вышла вместе с Kubernetes 1.24 - и принесла несколько изменений, которые для продакшн-кластеров означают конкретную работу руками, а не просто чтение release notes.

Мы ведём кластеры клиентов в рамках managed-сервиса и начали проходить по ним с обновлённым чеклистом. Вот что нашли и что делаем.

Что изменилось в CIS Benchmark v1.7

Основной акцент новой версии - ужесточение вокруг трёх областей.

Seccomp теперь явно обязателен. В предыдущих версиях бенчмарка seccomp был в разряде рекомендаций с пометкой «применяйте где возможно». В v1.7 это hard-требование: для подов в production-namespace-ах должен быть явно задан профиль RuntimeDefault или Localhost. Профиль Unconfined (он же отсутствие профиля вообще) отныне считается нарушением. Звучит просто, но в реальных кластерах это затрагивает все деплои, у которых нет явного seccompProfile в securityContext.

AppArmor - требование для узлов на Linux. Если дистрибутив поддерживает AppArmor (Ubuntu, Debian, AstraLinux), кластерная конфигурация должна это отражать. Конкретно - проверяется наличие аннотации container.apparmor.security.beta.kubernetes.io/<container-name>: runtime/default для подов там, где AppArmor доступен. Узлы на дистрибутивах без AppArmor (RHEL, AlmaLinux, Rocky - там SELinux) - отдельная история, бенчмарк учитывает это через conditional.

Pod Security Standards вместо PSP. Бенчмарк v1.7 переориентирован на PSA-лейблы. Для namespace-ов с production-нагрузкой рекомендован профиль restricted, для системных компонентов - явное указание privileged. Это согласуется с тем, что мы уже делали после 1.23, но теперь это часть формальных проверок, а не только наша практика.

Как мы автоматизируем проверку через kube-bench

Ручной аудит по бенчмарку - занятие полезное ровно один раз. Потом кластер меняется, нода пересоздаётся, кто-то добавляет новый namespace - и картина снова расходится с требованиями. Поэтому мы поставили kube-bench в CI-пайплайн.

kube-bench запускается как Job в кластере и проверяет конфигурации api-server, controller-manager, scheduler, etcd и узлов против актуальной версии CIS Benchmark. Для 1.24 используется профиль cis-1.7 - он идёт в поставке инструмента.

Пример манифеста для запуска:

apiVersion: batch/v1
kind: Job
metadata:
  name: kube-bench
  namespace: kube-system
spec:
  template:
    spec:
      hostPID: true
      nodeSelector:
        node-role.kubernetes.io/control-plane: ""
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
      containers:
        - name: kube-bench
          image: aquasec/kube-bench:latest
          command: ["kube-bench", "--benchmark", "cis-1.7"]
          volumeMounts:
            - name: var-lib-kubelet
              mountPath: /var/lib/kubelet
              readOnly: true
            - name: etc-kubernetes
              mountPath: /etc/kubernetes
              readOnly: true
      restartPolicy: Never
      volumes:
        - name: var-lib-kubelet
          hostPath:
            path: /var/lib/kubelet
        - name: etc-kubernetes
          hostPath:
            path: /etc/kubernetes

В CI мы парсим вывод kube-bench и падаем при наличии FAIL по разделам с весом WARN или выше. Секции INFO пропускаем - там обычно ручные организационные проверки типа «ведётся ли журнал изменений» - kube-bench их не может проверить автоматически.

Что нашли в кластерах

Проблемы предсказуемо кластеризуются вокруг двух вещей.

Отсутствие seccompProfile в манифестах. Это массово. Большинство деплоев написаны без явного securityContext.seccompProfile, потому что Kubernetes не требовал его явно. RuntimeDefault включается автоматически только если seccompDefault включён в конфигурации kubelet (feature gate, в 1.24 он ещё не дефолтный). В итоге поды запускаются с Unconfined по факту, хотя никто так явно не писал.

Фикс на уровне кластера: включить seccompDefault: true в KubeletConfiguration. Это переключает поведение по умолчанию без правки каждого манифеста. Но включать нужно осторожно - на кластерах с экзотическими системными вызовами в приложениях могут появиться блокировки. Тестируем в staging сначала.

Namespace-ы без PSA-лейблов. Особенно грешат namespace-ы, созданные операторами или Helm-чартами. При установке чарта namespace создаётся без лейблов вообще - а значит, PSA-профиль не применяется. Добавляем лейблы через Kyverno-политику ClusterPolicy, которая мутирует namespace при создании и проставляет как минимум warn: baseline. Потом смотрим что всплыло - и думаем дальше.

Про AppArmor в нашей реальности

Клиентские кластеры у нас работают на разных дистрибутивах. Ubuntu-узлы - AppArmor доступен. AlmaLinux-узлы - SELinux, AppArmor не применим. Это значит, что единого подхода нет: нужно смотреть на конкретный кластер.

На Ubuntu-узлах kube-bench корректно определяет наличие AppArmor и проверяет соответствующую секцию. Там реально нужно убедиться, что профиль runtime/default задан. На AlmaLinux kube-bench пропускает AppArmor-проверки - и это правильно, не надо форсировать то, чего нет в системе.

Где сейчас

По кластерам идём волнами. Первая волна - включение seccompDefault на control plane и worker-нодах. Вторая - расстановка PSA-лейблов через Kyverno. Третья - правка манифестов тех деплоев, которые в staging показали проблемы после включения seccomp.

kube-bench в CI уже работает на нескольких кластерах. Пока это только репорт - он не блокирует деплой, потому что хочется сначала собрать картину и убедиться что автоматика не ловит ложные срабатывания. Блокирующий режим планируем включить после того, как пройдём основной объём исправлений.

Нулевых нарушений по CIS Benchmark v1.7 нет ни на одном кластере - что честно, потому что стандарт стал строже, а кластеры создавались под старые требования. Прогресс есть, финал пока не близко.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.