Перейти к содержимому

Управление политиками безопасности с помощью Kyverno

Kyverno — это приложение для управления политиками безопасности в кластере Managed Kubernetes. Руководство поможет вам развернуть Kyverno, а также настроить и проверить работу политик безопасности.

Чтобы начать работу с Kyverno:

  1. Подготовьте виртуальную машину — на нее будут установлены утилиты для работы с приложением Kyverno.

  2. Установите Kyverno в кластер Managed Kubernetes.

  3. (опционально) Установите дополнительные компоненты Kyverno:

    • Reports Server — компонент, позволяющий хранить отчеты о работе политик во внешней базе данных.
    • Policy Reporter — веб-интерфейс для визуализации, фильтрации и анализа результатов работы политик.
  4. (опционально) Изучите сценарии работы с политиками безопасности.

  1. Создайте сервисный аккаунт с именем sa-k8s и ролью registry.puller — он понадобится для работы группы узлов Managed Kubernetes, а также для авторизации в Artifact Registry.

  2. Создайте API-ключ для сервисного аккаунта sa-k8s. Сохраните значение API-ключа.

  3. Создайте кластер Managed Kubernetes и группу узлов для него. При создании группы используйте сервисный аккаунт sa-k8s.

  4. Создайте NAT-шлюз для подсети, в которой будет развернут кластер Managed Kubernetes.

  5. Создайте виртуальную машину в той же сети, где развернут кластер Managed Kubernetes.

Для работы с Kyverno установите набор утилит на виртуальную машину:

  1. Установите и настройте утилиту MWS CLI:

  2. Установите утилиту командной строки kubectl.

  3. Получите kubeconfig:

    bash
    mws mk8s get-kubeconfig <имя кластера>
  4. Убедитесь, что кластер доступен:

    bash
    kubectl cluster-info

    Если конфигурация настроена правильно, вы получите такой ответ:

    bash
    Kubernetes control plane is running at https://<IP-адрес кластера>
    KubeDNS is running at https://<IP-адрес кластера>/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

Приложение Kyverno можно развернуть двумя способами:

  • Стандартная установка — приложение и его компоненты будут развернуты в одном экземпляре. Этот вариант установки подойдет для тестовых сред.
  • Режим высокой доступности — каждый компонент приложения будет развернут в нескольких экземплярах на нескольких подах. Такая установка обеспечит отказоустойчивость Kyverno.

Для тестирования установите Kyverno в режиме стандартной установки. В дальнейшем уже установленное приложение можно обновить до версии с высокой доступностью.

Чтобы установить Kyverno:

  1. Аутентифицируйтесь в Artifact Registry:

    bash
    helm registry login -u apikey -p <API-ключ> registry.mwsapis.ru

    Значение параметра -u apikey предустановлено, изменять его не нужно. Укажите только значение для API-ключа.

  2. Скачайте Helm-чарт kyverno на виртуальную машину:

    bash
    helm pull oci://registry.mwsapis.ru/mws-mk8s-images/customer/charts/kyverno \
    --version 3.7.1 \
    --untar
  3. Установите приложение одним из способов:

    • Стандартная установка
    • Режим высокой доступности
    • Обновление до версии с высокой доступностью
    1. Установите Kyverno:

      bash
      helm install kyverno ./kyverno/ \
      -n kyverno \
      --create-namespace
    2. Убедитесь, что приложение успешно развернуто:

      bash
      kubectl get pods -n kyverno

      Ожидаемый результат:

      bash
      NAME READY STATUS RESTARTS AGE
      kyverno-admission-controller-67778dd76c-vgn5h 1/1 Running 0 28s
      kyverno-background-controller-848b659869-vjtr5 1/1 Running 0 28s
      kyverno-cleanup-controller-9979c9cd-b59bz 1/1 Running 0 28s
      kyverno-reports-controller-5dff874846-pfscw 1/1 Running 0 28s

Для проверки работы Kyverno создайте две политики безопасности:

  • MutatingPolicy с именем add-default-resources — политика проверяет, установлены ли запросы на ресурсы (requests) для новых приложений. Если запросы не установлены, она добавляет в параметры приложения ресурсы по умолчанию.
  • ValidatingPolicy с именем block-large-images — политика запрещает создание приложений, размер которых превышает установленное значение. В примере это 50 МБ.

Чтобы установить политики:

  1. Создайте файл add-default-resources.yaml.

    yaml
    apiVersion: policies.kyverno.io/v1alpha1
    kind: MutatingPolicy
    metadata:
    name: add-default-resources
    spec:
    autogen:
    podControllers:
    controllers:
    - deployments
    - cronjobs
    - jobs
    - statefulsets
    - daemonsets
    evaluation:
    mutateExisting:
    enabled: false
    admission:
    enabled: true
    matchConstraints:
    resourceRules:
    - apiGroups:
    - ""
    apiVersions:
    - v1
    operations:
    - CREATE
    - UPDATE
    resources:
    - pods
    mutations:
    - patchType: ApplyConfiguration
    applyConfiguration:
    expression: |-
    Object{
    spec: Object.spec{
    containers: object.spec.containers.map(c,
    Object.spec.containers{
    name: c.name,
    resources: Object.spec.containers.resources{
    requests: Object.spec.containers.resources.requests{
    cpu: has(c.resources) && has(c.resources.requests) && has(c.resources.requests.cpu)
    ? c.resources.requests.cpu
    : "100m",
    memory: has(c.resources) && has(c.resources.requests) && has(c.resources.requests.memory)
    ? c.resources.requests.memory
    : "100Mi"
    }
    }
    }
    )
    }
    }
  2. Создайте файл block-large-images.yaml.

    yaml
    apiVersion: policies.kyverno.io/v1alpha1
    kind: ValidatingPolicy
    metadata:
    name: block-large-images
    annotations:
    policies.kyverno.io/title: Block Large Images
    policies.kyverno.io/category: Other
    policies.kyverno.io/severity: medium
    policies.kyverno.io/minversion: 1.15.0
    policies.kyverno.io/subject: Pod
    policies.kyverno.io/description: Pods which run containers of very large image size take longer to pull and require more space to store. A user may either inadvertently or purposefully name an image which is unusually large to disrupt operations. This policy checks the size of every container image and blocks if it is over 50Mb.
    spec:
    evaluation:
    background:
    enabled: true
    validationActions:
    - Deny
    variables:
    - name: allContainers
    expression: object.spec.containers + object.spec.?initContainers.orValue([]) + object.spec.?ephemeralContainers.orValue([])
    - name: maxSizeBytes
    expression: "52428800"
    matchConstraints:
    resourceRules:
    - resources:
    - pods
    operations:
    - CREATE
    - UPDATE
    apiGroups:
    - ""
    apiVersions:
    - v1
    validations:
    - message: images with size greater than 50Mb not allowed
    expression: variables.allContainers.all(container, image.GetMetadata(container.image).manifest.layers.map(layer, layer.size).sum() <= variables.maxSizeBytes)
  3. Установите политики:

    bash
    kubectl apply -f add-default-resources.yaml && \
    kubectl apply -f block-large-images.yaml
  4. Убедитесь, что политики успешно созданы:

    bash
    kubectl get validatingpolicy,mutatingpolicy

    Ожидаемый результат:

    bash
    NAME AGE READY
    validatingpolicy.policies.kyverno.io/block-large-images 2m37s true
    NAME AGE READY
    mutatingpolicy.policies.kyverno.io/add-default-resources 2m43s true

Для проверки разверните тестовые приложения, нарушающие правила политик:

  1. Создайте файл pod-with-no-requests.yaml с манифестом пода, для которого не указаны запросы ресурсов (requests):

    yaml
    apiVersion: v1
    kind: Pod
    metadata:
    name: busybox
    spec:
    containers:
    - name: busybox
    image: busybox:latest
    command: ["echo"]
    args: ["OK, requests added by kyverno"]
    restartPolicy: Never
  2. Создайте под:

    bash
    kubectl apply -f pod-with-no-requests.yaml
  3. Убедитесь, что для пода установлены ресурсы по умолчанию:

    bash
    kubectl get pod busybox -o yaml | grep -A 4 resources

    Ожидаемый результат:

    bash
    resources:
    requests:
    cpu: 100m
    memory: 100Mi

    Политика add-default-resources установила для пода запросы ресурсов по умолчанию.

  4. Попытайтесь создать под, размеры которого превышают 50 МБ:

    bash
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
    name: large-python-pod
    spec:
    containers:
    - name: python-app
    image: python:latest
    command: ["python"]
    args: ["-c", "print('hello from python')"]
    restartPolicy: Never
    EOF

    Создание пода будет заблокировано политикой block-large-images:

    bash
    Error from server: error when creating "STDIN": admission webhook "vpol.validate.kyverno.svc-fail" denied the request: Policy block-large-images failed: images with size greater than 50Mb not allowed

5. (опционально) Установите дополнительные компоненты

Заголовок раздела «5. (опционально) Установите дополнительные компоненты»

Установите дополнительные компоненты Kyverno:

  • Reports Server — компонент, решающий проблему масштабирования при работе с большим количеством политик. По умолчанию Kyverno хранит отчеты о применении политик во внутренней базе данных кластера Kubernetes (etcd). При высокой нагрузке это может снижать производительность кластера. Reports Server выгружает отчеты во внешнюю базу данных, например в Managed PostgreSQL. Это позволяет уменьшить нагрузку на etcd и значительно повысить масштабируемость. Подробнее о Reports Server в документации Kyverno.

  • Policy Reporter — веб-интерфейс для визуализации, фильтрации и анализа результатов работы политик. Также Policy Reporter позволяет выгружать данные о работе политик во внешние системы, например в Grafana или ElasticSearch. Подробнее о Policy Reporter в документации Kyverno.

  1. Создайте кластер Managed PostgreSQL подходящей вам конфигурации в той же подсети, где расположен кластер Managed Kubernetes.

  2. Создайте базу данных Managed PostgreSQL. При создании базы создайте нового пользователя и задайте ему пароль.

  3. Сохраните параметры для подключения к базе данных:

    • Внутренний IP-адрес Primary-эндпоинта кластера. Чтобы узнать этот IP-адрес, получите информацию о кластере.
    • Имя базы данных.
    • Имя и пароль пользователя.
  4. Вернитесь в SSH-сессию виртуальной машины.

  5. Политика, блокирующая создание больших приложений, может помешать развертыванию Reports Server. Удалите созданную ранее политику:

    bash
    kubectl delete -f block-large-images.yaml
  6. Скачайте Helm-чарт Reports Server:

    bash
    helm pull oci://registry.mwsapis.ru/mws-mk8s-images/customer/charts/reports-server \
    --version 0.1.6 \
    --untar
  7. Создайте пространство имен для развертывания Reports Server:

    bash
    kubectl create namespace reports-server
  8. Создайте секрет, содержащий параметры подключения к БД Managed PostgreSQL:

    bash
    kubectl create secret generic postgres-auth-reportserver -n reports-server \
    --from-literal=host='<внутренний IP-адрес Primary-эндпоинта кластера Managed PostgreSQL>' \
    --from-literal=port='5432' \
    --from-literal=dbname='<имя БД Managed PostgreSQL>' \
    --from-literal=username='<имя пользователя Managed PostgreSQL>' \
    --from-literal=password='<пароль пользователя Managed PostgreSQL>'
  9. Установите Reports Server:

    bash
    helm install reports-server ./reports-server \
    -n reports-server \
    --set config.db.secretName=postgres-auth-reportserver
  10. Убедитесь, что под приложения перешел в состояние Running:

    bash
    kubectl get pods -n reports-server
  11. Проверьте, что отчеты о срабатывании политик выгружаются в базу данных PostgreSQL:

    1. Создайте новую политику require-labels, которая будет отслеживать, есть ли у подов метка team:

      bash
      kubectl apply -f - <<EOF
      apiVersion: policies.kyverno.io/v1alpha1
      kind: ValidatingPolicy
      metadata:
      name: require-labels
      spec:
      validationActions: ["Audit"]
      matchConstraints:
      resourceRules:
      - apiGroups: [""]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["pods"]
      validations:
      - message: "The label 'team' is required."
      expression: "has(object.metadata.labels) && has(object.metadata.labels.team)"
      EOF
    2. Создайте тестовый под, который не содержит метку team:

      bash
      kubectl run test-report-pod --image=nginx --restart=Never
    3. Подключитесь к базе данных кластера Managed PostgreSQL, используя полученные ранее параметры для подключения.

    4. Выполните запрос, который выведет информацию о срабатывании политики require-labels:

      bash
      SELECT
      report->'scope'->>'namespace' AS namespace,
      report->'scope'->>'name' AS resource_name,
      res->>'policy' AS policy_name,
      res->>'result' AS result,
      res->>'message' AS message
      FROM policyreports,
      jsonb_array_elements(report->'results') AS res
      WHERE res->>'policy' = 'require-labels'
      AND report->'scope'->>'name' = 'test-report-pod';

      Ожидаемый результат выборки:

      bash
      namespace | resource_name | policy_name | result | message
      ----------+-----------------+----------------+--------+-------------------------------
      default | test-report-pod | require-labels | fail | The label 'team' is required.
      (1 row)
  1. Скачайте Helm-чарт Policy Reporter:

    bash
    helm pull oci://registry.mwsapis.ru/mws-mk8s-images/customer/charts/policy-reporter \
    --version 3.7.3 \
    --untar
  2. Установите Policy Reporter:

    bash
    helm install policy-reporter ./policy-reporter \
    -n policy-reporter \
    --create-namespace
  3. Убедитесь, что поды приложения перешли в состояние Running:

    bash
    kubectl get pods -n policy-reporter

    Ожидаемый результат:

    bash
    NAME READY STATUS RESTARTS AGE
    policy-reporter-6b7586b68c-v4vsp 1/1 Running 0 21s
    policy-reporter-ui-774db9cb6b-gdmvg 1/1 Running 0 21s
  4. Узнайте внутренний и внешний IP-адреса ВМ, запросив информацию о ней.

  5. Создайте правило файрвола — оно потребуется для подключения к веб-интерфейсу Policy Reporter. Укажите следующие параметры правила:

    • НаправлениеIngress.
    • ДействиеAllow.
    • Источник трафика0.0.0.0/0 или внешний IP-адрес вашего локального компьютера.
    • Назначение трафика — внутренний IP-адрес виртуальной машины в нотации CIDR, например 192.168.0.12/32.
    • Протокол и портTCP:8081.
  6. Создайте переадресацию порта для сервиса policy-reporter-ui на виртуальной машине:

    bash
    kubectl port-forward service/policy-reporter-ui 8081:8080 -n policy-reporter --address 0.0.0.0
  7. В браузере на локальном компьютере откройте ссылку http://<внешний IP-адрес ВМ>:8081. Откроется веб-интерфейс Policy Reporter.

6. Изучите сценарии работы с политиками безопасности

Заголовок раздела «6. Изучите сценарии работы с политиками безопасности»

Ресурсы, созданные в руководстве, тарифицируются. Если вы больше не планируете использовать их: