Расширение сред Kubernetes (K8s), добавление новых кластеров и приложений — необходимые процессы для развития сервисов. В таких условиях для каждого администратора Kubernetes критически важно обеспечить последовательность и непрерывность соблюдения политик безопасности (ПБ) для всех новых и существующих ресурсов. Но сделать это вручную почти невозможно: сложно, дорого, снижает гибкость разработки, повышает риск ошибок из-за человеческого фактора. Администратору для комфортной работы с ПБ нужна автоматизация. И в этом ему поможет Gatekeeper.

Меня зовут Александр Чадин, я ведущий программист VK Cloud Solutions. У нас в облаке есть Gatekeeper, и я расскажу, как с его помощью автоматизировать работу с политиками безопасности в Kubernetes, как работает этот инструмент и когда он нужен.

Главное о Gatekeeper


Gatekeeper — специфическая реализация Open Policy Agent (OPA) для Kubernetes, которая работает в качестве Webhook для валидации манифестов. Этот инструмент предназначен для аудита и автоматического применения к ресурсам Kubernetes политик безопасности, написанных на языке Rego.

Gatekeeper встраивается между сервером API Kubernetes и OPA, принимает все поступающие в кластер запросы и в реальном времени проверяет их на соответствие предварительно настроенным политикам безопасности. 

При такой схеме Gatekeeper регистрируется в качестве контроллера с помощью Webhook-проверки в API Kubernetes

Gatekeeper запускается при каждом создании, обновлении или удалении ресурсов в кластере. Gatekeeper Webhook перехватывает запросы, направленные в Kubernetes API, и проверяет их цепочкой политик, определенных администратором кластера. Ограничения оцениваются как логические, и если они не выполняются, то запрос отклоняется.

Прелесть Gatekeeper в том, что он позволяет:

  • контролировать действия пользователя в кластере;
  • автоматически применять установленные политики безопасности ко всему кластеру.

Одновременно с этим Gatekeeper упрощает взаимодействие DevOps-специалистов и разработчиков: DevOps-инженеры могут не переживать по поводу ошибок при разработке, а разработчики получают мгновенную обратную связь о том, что не так и где нужны изменения.
В актуальной версии Gatekeeper контроллер допуска интегрирован с OPA Constraint Framework. Он обеспечивает соблюдение политик на основе CRD и надежность совместного использования декларативно настроенных политик. 

Gatekeeper отвечает за контроль допуска и аудита. Это позволяет:

  • создавать шаблоны политик на языке Rego; 
  • формировать политики в виде CRD;
  • хранить результаты аудита в CRD политики. 


Схема работы Gatekeeper

Политики Gatekeeper состоят из двух манифестов:

  • Шаблон ограничений (Constraint Template). Позволяет объявлять новые ограничения и отделять логику ограничения от конкретных ресурсов, к которым она применяется. Шаблон содержит всю информацию для работы ограничения, включая тип объекта, к которому оно применяется, и параметры, которые ограничение должно предоставлять.
  • Ограничения (Constraints). Это объединение шаблонов с параметрами — ресурсами разных типов: поды, деплойменты, секреты и другие. Спецификацию ограничений также используют для выбора принудительного действия (Deny, Warn или Dry Run). По умолчанию для него установлено значение Deny: отклоняются любые приводящие к нарушениям запросы на добавление, изменение или удаление ресурса.

В связке с Gatekeeper работает аудитор. Он позволяет администраторам видеть, какие из уже существующих ресурсов нарушают вводимые политики безопасности. Фактически аудитор помогает привести к соответствию политикам все ресурсы на кластере, независимо от того, когда они были созданы — до принятия политики или после.

Особенности работы с Gatekeeper 


Рассмотрим особенности каждого этапа работы с Gatekeeper. 

Проверка контроля допуска


После установки всех компонентов Gatekeeper в кластере сервер API вызывает Webhook Gatekeeper Admission для обработки запросов в API Kubernetes. Запуск происходит при каждом создании, обновлении или удалении ресурса в кластере.

При проверке Gatekeeper действует как мост между сервером API и OPA. Сервер API применяет все политики, выполняемые OPA.

Политики и ограничения


Каждое ограничение записывают с помощью декларативного языка Rego, который использует OPA для перечисления экземпляров данных, нарушающих ожидаемое состояние системы. Все ограничения оцениваются как логические: если одно не выполнено, отклоняется весь запрос.

Перед определением ограничения создают шаблон, который позволяет объявлять новые ограничения.

Пример шаблона ограничения CRD, которое требует наличия определенных лейблов на произвольном объекте:

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
        listKind: K8sRequiredLabelsList
        plural: k8srequiredlabels
        singular: k8srequiredlabels
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            labels:
              type: array
              items: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels

        deny[{"msg": msg, "details": {"missing_labels": missing}}] {
        provided:={label|input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("you must provide labels: %v", [missing])
        }        

После развертывания шаблона ограничения в кластере на его основе можно создать ограничение для конкретных типов объектов.

Пример CRD-ограничения, которое требует, чтобы метка hr присутствовала во всех пространствах имен:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-hr
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels: ["hr"]

Пример CRD-ограничения, которое требует присутствия метки finance во всех пространствах имен:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-finance
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels: ["finance"]

Таким образом, ограничения позволяют:

  • повторно использовать предварительно созданные шаблоны;
  • определять область применения с помощью поля Match;
  • предоставлять ограничениям параметры, выбранные пользователем, для настройки индивидуального поведения каждого ограничения.

Аудит


Аудит позволяет оценивать ресурсы в соответствии с принятыми в кластере ограничениями. Это помогает выявлять неправильные конфигурации, созданные ранее.

Gatekeeper хранит результаты аудита как Violations в поле Status
соответствующего ограничения.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-hr
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels: ["hr"]
status:
  auditTimestamp: "2019-08-06T01:46:13Z"
  byPod:
  - enforced: true
    id: gatekeeper-controller-manager-0
  violations:
  - enforcementAction: deny
    kind: Namespace
    message: 'you must provide labels: {"hr"}'
    name: default
  - enforcementAction: deny
    kind: Namespace
    message: 'you must provide labels: {"hr"}'
    name: gatekeeper-system
  - enforcementAction: deny
    kind: Namespace
    message: 'you must provide labels: {"hr"}'
    name: kube-public
  - enforcementAction: deny
    kind: Namespace
    message: 'you must provide labels: {"hr"}'
    name: kube-system

Репликация данных


Перед оценкой ресурсов на соответствие политикам безопасности может потребоваться подгрузка данных из Kubernetes в Gatekeeper. Она нужна в тех случаях, когда недостаточно оцениваемых объектов и требуется информация по ресурсам из кластера. Например, ограничение, которое обеспечивает уникальность имени хоста входа, должно иметь доступ ко всем другим входам в кластере.

Для настройки репликации данных Kubernetes используют ресурс конфигурации синхронизации с реплицируемыми в OPA ресурсами.

Пример репликации всего пространства имен и ресурсов pod в OPA:

apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: "gatekeeper-system"
spec:
  sync:
    syncOnly:
      - group: ""
        version: "v1"
        kind: "Namespace"
      - group: ""
        version: "v1"
        kind: "Pod"

После синхронизации данных с OPA правила могут получить доступ к кэшированным данным в документе data.inventory. Он имеет следующий формат:

  • Для объектов с кластерной областью:
     data.inventory.cluster[<groupVersion>][<kind>][<name>] 
  • Пример ссылки на пространство имен Gatekeeper:
    data.inventory.cluster["v1"].Namespace["gatekeeper"]
  • Для объектов, ограниченных пространством имен:
    data.inventory.namespace[<namespace>][groupVersion][<kind>][<name>]
  • Пример ссылки на модуль Gatekeeper:
    data.inventory.namespace["gatekeeper"]["v1"]["Pod"]["gatekeeper-controller-manager-d4c98b788-j7d92"]

Зачем вам нужен Gatekeeper?


Зачастую политики безопасности для ресурсов Kubernetes разрабатывают с запасом — в них добавляют как обязательные, так и необязательные параметры. Это усложняет разработку и создает трудности, если ресурсы настраивают разные команды. 

Gatekeeper помогает стандартизировать настройку всех ресурсов в кластере и автоматически блокировать создание или обновление тех из них, которые не соответствуют принятым политикам. С его помощью чаще всего проверяют:

  • Resource requests and limits (запросы на ограничения и лимиты). Применяют, когда важно, чтобы в каждом контейнере были указаны запросы и ограничения ресурсов. Например, это помогает исключить «проблему шумного соседа» — когда один контейнер чрезмерно потребляет ресурсы хоста и создает их дефицит на сервере.
  • Соответствия разрешенному пространству имен. Используют, если нужно разделить права доступа к ресурсу или кластеру для разных команд. Например, работать с ресурсами может только команда, использующая соответствующее пространство имен.
  • Ограничения на права входных ресурсов. Применяют, когда важно ограничить права входных ресурсов на обслуживание трафика. Например, если нужно применить стандарт в стратегии шлюза API, используя nginx-ingress, где только один входной ресурс может обрабатывать запросы /api/${resource}.
  • Ограничений на запуск от неразрешенных имен. Используют, когда важно ограничить запуск контейнеров от пользователя Root, если они не находятся в списке разрешений, определенном в политиках.
  • Готовность контейнеров. Например, если нужно, чтобы liveness-/readiness-пробы могли гарантировать, что трафик не достигнет контейнера, который не готов к нему, и что контейнеры перезапускаются, когда они переходят в невосстановимое состояние;
  • Ограничения на монтирование папок на под. Позволяют ограничить возможность подключения отдельных папок с хоста на под или наоборот — разрешить маунт только определенных папок. Актуально, если в кластере с общим доступом есть папки с конфиденциальной системной информацией.

Главное по теме: что нужно знать о Gatekeeper


  1. Gatekeeper обеспечивает интеграцию с OPA и Kubernetes.
  2. Инструмент встраивается между сервером API Kubernetes и OPA, принимает поступающие в кластер запросы и проверяет их на соответствие актуальным политикам безопасности.
  3. Решение позволяет настроить политики один раз и быть уверенным, что все создаваемые ресурсы в кластере им соответствуют.
  4. Gatekeeper незначительно влияет на производительность системы и практически не сказывается на скорости обработки запросов.
  5. Инструмент может работать с политиками безопасности, содержащими разные ограничения.
В Kubernetes от VK Cloud Solutions доступен Gatekeeper. Его можно протестировать — для этого новым пользователям при регистрации начисляем 3000 бонусных рублей. Будем рады, если вы попробуете и оставите обратную связь.

Комментарии (2)


  1. turbotankist
    08.06.2022 19:19

    "Opa" прикольная штука, мы её используем для некоторых валидаций, но как же взрывается мозг когда нужно написать какое-то сложное правило. Тратишь несколько часов если не знаешь синтаксис rego, вроде работает, вроде разобрался с синтаксисом. Но потом через 2 месяца нужно написать ещё одно правило и изучение начинается с нуля.

    Может я просто полный ноль в функциональных языках.


  1. r0binak
    08.06.2022 20:27
    +2

    OPA конечно хорошо, но всё-таки более Kubernetes native будет Kyverno. Да и правила там писать куда проще.