Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов

Рейтинг: 59.6% · 10 голосов
Kubernetes для разработчиков: поды, деплойменты, сервисы, ingress, конфиги и отладка. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
anton_k8s
Сообщения: 26
Зарегистрирован: 12 май 2026, 03:23

Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов

Сообщение anton_k8s »

АкадемияKubernetes на практикеГлава 19 из 19
Оглавление курса (19)
  1. Зачем нужен Kubernetes и из чего состоит кластер
  2. Поднимаем локальный кластер: minikube и kind
  3. Поды: базовая единица запуска
  4. Deployment и ReplicaSet: управляем репликами
  5. Service: сетевой доступ к подам
  6. ConfigMap и Secret: выносим конфигурацию
  7. Ingress: пускаем трафик снаружи
  8. Хранилище: Volumes и PersistentVolumeClaim
  9. Namespaces, requests и limits
  10. Health checks: liveness и readiness пробы
  11. Отладка: почему под не стартует
  12. Helm: пакетный менеджер для Kubernetes
  13. Базовая безопасность: RBAC и доступы
  14. Job и CronJob: разовые и периодические задачи
  15. StatefulSet и DaemonSet: stateful-нагрузки и системные агенты
  16. Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints
  17. Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler
  18. Наблюдаемость: логи, метрики, events, обзор Prometheus и Grafana
  19. Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов (вы здесь)
RBAC из главы 13 решает, кто и что может делать через API. Это только один слой. Контейнер, получивший рута на ноде, RBAC не остановит. Под, который свободно ходит по всей сети кластера, тоже. Закрываем оставшиеся дыры: урезаем права процесса внутри контейнера, запрещаем опасные поды на входе в неймспейс, режем сетевой трафик и шифруем секреты в etcd.

securityContext, права процесса в контейнере:

По умолчанию контейнер запускается так, как собран образ, часто от рута и с лишними capabilities. securityContext задается на уровне пода и контейнера, контейнерный перекрывает подовый. Рабочий минимум для продакшена: не рут, без эскалации привилегий, без capabilities, корневая файловая система только на чтение, seccomp-профиль рантайма.

Код: Выделить всё

# deploy-api.yaml, фрагмент шаблона пода
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 10001
    runAsGroup: 10001
    fsGroup: 10001
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: api
    image: registry.local/shop/api:1.8.3
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}
readOnlyRootFilesystem почти всегда требует emptyDir под /tmp, иначе приложение упадет при первой же попытке записи. И проверьте образ: если в Dockerfile нет числового USER и runAsUser не задан, kubelet при runAsNonRoot: true откажется стартовать контейнер с ошибкой CreateContainerConfigError.

Pod Security Standards, запрет на уровне неймспейса:

Писать securityContext руками в каждом манифесте мало, нужен механизм, который не пустит нарушителя в кластер. PodSecurityPolicy выпилили в 1.25, ее место занял встроенный в apiserver контроллер Pod Security Admission. Он сверяет поды с тремя профилями: privileged (без ограничений), baseline (запрещает hostNetwork, hostPath, привилегированные контейнеры) и restricted (требует примерно то, что мы прописали выше). Управляется лейблами неймспейса в трех режимах: enforce блокирует создание, warn ругается в ответе kubectl, audit пишет в audit-лог.

Правильный порядок внедрения: сначала warn и audit, неделю смотрим что ломается, потом enforce.

Код: Выделить всё

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

# репетиция enforce: покажет всех нарушителей, ничего не меняя
kubectl label --dry-run=server --overwrite ns shop \
  pod-security.kubernetes.io/enforce=restricted
enforce не трогает уже запущенные поды, проверка идет при создании. После включения сделайте rollout restart и убедитесь, что деплойменты переживут пересоздание.

NetworkPolicy, сегментация трафика:

Из коробки любой под может постучаться в любой другой, включая чужие неймспейсы. Скомпрометированный фронтенд получает прямой доступ к базе биллинга. NetworkPolicy это исправляет, но с оговоркой: политики исполняет CNI-плагин. Calico и Cilium умеют, flannel в чистом виде нет, и политики молча игнорируются. Проверяйте живым трафиком через kubectl exec и curl, а не по факту наличия yaml.

Базовый паттерн: default deny на весь неймспейс плюс точечные разрешения. Политики аддитивны, они только разрешают, запретить что-то поверх разрешенного нельзя.

Код: Выделить всё

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: shop
spec:
  podSelector: {}
  policyTypes: ["Ingress", "Egress"]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-allow
  namespace: shop
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes: ["Ingress", "Egress"]
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
    ports:
    - port: 5432
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - port: 53
      protocol: UDP
    - port: 53
      protocol: TCP
Блок с kube-dns обязателен: default deny по egress режет и DNS, после чего все падает с невнятными таймаутами вместо честного connection refused.

Шифрование секретов в etcd:

base64 это кодирование, а не шифрование. Любой, у кого есть доступ к etcd или его бэкапам, читает секреты открытым текстом. Лечится через EncryptionConfiguration для kube-apiserver:

Код: Выделить всё

# /etc/kubernetes/enc/enc.yaml
# подключается к kube-apiserver флагом:
#   --encryption-provider-config=/etc/kubernetes/enc/enc.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources: ["secrets"]
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-строка 32-байтового ключа>
      - identity: {}
Первый провайдер в списке используется для записи, остальные для чтения старых данных. Для продакшена правильнее kms v2 (стабилен с 1.29) с внешним хранилищем ключей; в managed-кластерах (Yandex Cloud, VK Cloud) шифрование через KMS включается опцией при создании кластера, до apiserver вас там все равно не пустят. После включения перешифруйте существующее:

Код: Выделить всё

kubectl get secrets -A -o json | kubectl replace -f -
И не забудьте RBAC: право get на секреты должно быть у считанных сервис-аккаунтов, а не у каждого разработчика с kubectl.

Типичные грабли:

NetworkPolicy лежат в репозитории, CNI их не исполняет, команда живет с иллюзией сегментации. identity стоит первым в списке провайдеров, и секреты пишутся в открытом виде, порядок в EncryptionConfiguration критичен. enforce=restricted повесили, а старые поды-нарушители спокойно работают до первого пересоздания. readOnlyRootFilesystem уронил приложение, которое пишет логи в файл рядом с бинарником. В Dockerfile написано USER appuser вместо USER 10001, и runAsNonRoot не может доказать, что это не рут.

Итог:

Безопасность кластера собирается слоями: RBAC ограничивает API, securityContext и PSS ограничивают сам под, NetworkPolicy ограничивает сеть, шифрование защищает данные в покое. Каждый слой дешев по отдельности и бесполезен в одиночку. На этом курс закончен. Дальше есть смысл копать в GitOps (Argo CD, Flux), операторы и сертификации CKA и CKS, там та же безопасность разбирается еще глубже.
👍4 ❤️ 🔥 😄 🤔2
✔ Лучший ответ сформирован автоматически — ansible_master
anton_k8s писал(а):Calico и Cilium умеют, flannel в чистом виде нет, и политики молча игнорируются прочувствовал на своей шкуре. накатили политики на стейдж, yaml зеленый, отчет о сегментации сдан. через полгода пентестер из произвольного пода спокойно достучался до базы. кластер был на flannel. теперь первое правило: kubectl exec и curl туда, куда по идее нельзя, и только потом верить манифестам
Перейти к ответу →
Аватара пользователя
ansible_master
Сообщения: 2
Зарегистрирован: 29 май 2026, 07:53

Re: Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов

Сообщение ansible_master »

✔ Лучший ответ — сформирован автоматически
anton_k8s писал(а):Calico и Cilium умеют, flannel в чистом виде нет, и политики молча игнорируются
прочувствовал на своей шкуре. накатили политики на стейдж, yaml зеленый, отчет о сегментации сдан. через полгода пентестер из произвольного пода спокойно достучался до базы. кластер был на flannel. теперь первое правило: kubectl exec и curl туда, куда по идее нельзя, и только потом верить манифестам
👍 ❤️2 🔥 😄 🤔
Аватара пользователя
gorky
Сообщения: 1
Зарегистрирован: 12 май 2026, 02:23

Re: Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов

Сообщение gorky »

вопрос по шифрованию: в managed кластерах же нет доступа к apiserver, флаг не подсунешь. правильно понимаю, что там только опция KMS при создании кластера и если ее не включили сразу, то по сути пересоздавать? у нас прод в облаке живет с 2023, страшно представить что в бэкапах etcd лежит
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
xam1992
Сообщения: 2
Зарегистрирован: 14 май 2026, 23:51

Re: Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов

Сообщение xam1992 »

прошел все 19 глав с нуля, спасибо. отдельно зашло, что в каждой главе грабли из реальной жизни, а не пересказ доков. глава 11 про дебаг уже дважды спасала прод, теперь по этой соберу чеклист и пойду пугать команду словом pentest
👍1 ❤️1 🔥 😄 🤔1
Аватара пользователя
ansible_coder
Сообщения: 1
Зарегистрирован: 15 май 2026, 17:18

Re: Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов

Сообщение ansible_coder »

включил warn=restricted на дев неймспейсе и прослезился, половина helm чартов из интернета не проходит даже baseline. кто как патчит чужие чарты? через values не все пробрасывается, пока спасаюсь kustomize постренедером, но ощущение что костыль
👍1 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Наблюдаемость: логи, метрики, events, обзор Prometheus и Grafana

Все главы курса «Kubernetes на практике»

Поделиться темой: ✈ Telegram VK

Вернуться в «Kubernetes на практике»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость