Описание

Проекты (ресурс Project) в Deckhouse Virtualization Platform (DVP) обеспечивают изолированные окружения для создания ресурсов пользователя.

Настройки проекта позволяют задать квоты для ресурсов, ограничить сетевое взаимодействие, как внутри платформы, так и вне её.

Для создания проектов используются шаблоны (ресурс ProjectTemplate).

При изменении шаблона проекта, все созданные проекты будут обновлены в соответствии с новым шаблоном.

Шаблоны для проектов доступные по умолчанию

В DVP есть набор шаблонов для создания проектов:

  • default — шаблон для базовых сценариев использования проектов:
    • ограничение ресурсов;
    • сетевая изоляция;
    • автоматические алерты и сбор логов;
    • выбор профиля безопасности;
    • настройка администраторов проекта.

      Описание шаблона в GitHub.

  • secure — включает все возможности шаблона default, а также дополнительные функции:
    • настройка допустимых для проекта UID/GID;
    • правила аудита обращения Linux-пользователей проекта к ядру;
    • сканирование запускаемых образов контейнеров на наличие известных уязвимостей (CVE).

    Описание шаблона в GitHub.

  • secure-with-dedicated-nodes — включает все возможности шаблона secure, а также дополнительные функции:
    • определение селектора узла для всех ВМ в проекте: если ВМ создана, селектор узла ВМ будет автоматически заменён на селектор узла проекта;
    • определение стандартных tolerations для всех ВМ в проекте: если ВМ создана, стандартные значения tolerations добавляются к нему автоматически.

    Описание шаблона в GitHub.

Чтобы перечислить все доступные параметры для шаблона проекта, выполните команду:

d8 k get projecttemplates <ИМЯ_ШАБЛОНА_ПРОЕКТА> -o jsonpath='{.spec.parametersSchema.openAPIV3Schema}' | jq

Создание проекта

  1. Для создания проекта создайте ресурс Project с указанием имени шаблона проекта в поле .spec.projectTemplateName.
  2. В параметре .spec.parameters ресурса Project укажите значения параметров для секции .spec.parametersSchema.openAPIV3Schema ресурса ProjectTemplate.

    Пример создания проекта с помощью ресурса Project из default ProjectTemplate представлен ниже:

    apiVersion: deckhouse.io/v1alpha2
    kind: Project
    metadata:
      name: my-project
    spec:
      description: This is an example from the Deckhouse documentation.
      projectTemplateName: default
      parameters:
        resourceQuota:
          requests:
            cpu: 5
            memory: 5Gi
            storage: 1Gi
          limits:
            cpu: 5
            memory: 5Gi
        networkPolicy: Isolated
        podSecurityProfile: Restricted
        extendedMonitoringEnabled: true
        administrators:
        - subject: Group
          name: k8s-admins
    
  3. Для проверки статуса проекта выполните команду:

    d8 k get projects my-project
    

    Успешно созданный проект должен отображаться в статусе Deployed (синхронизирован). Если отображается статус Error (ошибка), добавьте аргумент -o yaml к команде (например, d8 k get projects my-project -o yaml) для получения более подробной информации о причине ошибки.

Автоматическое создание проекта для пространства имён

Для пространства имён возможно создать новый проект. Для этого пометьте пространство имён аннотацией projects.deckhouse.io/adopt. Например:

  1. Создайте новое пространство имён:

    d8 k create ns test
    
  2. Пометьте его аннотацией:

    d8 k annotate ns test projects.deckhouse.io/adopt=""
    
  3. Убедитесь, что проект создался:

    d8 k get projects
    

    В списке проектов появится новый проект, соответствующий пространству имён:

    NAME        STATE      PROJECT TEMPLATE   DESCRIPTION                                            AGE
    deckhouse   Deployed   virtual            This is a virtual project                              181d
    default     Deployed   virtual            This is a virtual project                              181d
    test        Deployed   empty                                                                     1m
    

Шаблон созданного проекта можно изменить на существующий.

Обратите внимание, что при смене шаблона может возникнуть конфликт ресурсов: если в чарте шаблона прописаны ресурсы, которые уже присутствуют в пространстве имён, то применить шаблон не получится.

Создание собственного шаблона для проекта

Шаблоны проектов по умолчанию включают базовые сценарии использования и служат примером возможностей шаблонов.

Для создания своего шаблона:

  1. Возьмите за основу один из шаблонов по умолчанию, например, default.
  2. Скопируйте его в отдельный файл, например, my-project-template.yaml при помощи команды:

    d8 k get projecttemplates default -o yaml > my-project-template.yaml
    
  3. Отредактируйте файл my-project-template.yaml, внесите в него необходимые изменения.

    Необходимо изменить не только шаблон, но и схему входных параметров под него.

    Шаблоны для проектов поддерживают все функции шаблонизации Helm.

  4. Измените имя шаблона в поле .metadata.name.
  5. Примените полученный шаблон командой:

    d8 k apply -f my-project-template.yaml
    
  6. Проверьте доступность нового шаблона с помощью команды:

    d8 k get projecttemplates <ИМЯ_НОВОГО_ШАБЛОНА>
    

Использование лейблов для управления ресурсами

При создании ресурсов в ProjectTemplate можно использовать специальные лейблы для управления поведением multitenancy-manager при обработке этих ресурсов:

Пропуск создания лейбла heritage: multitenancy-manager

По умолчанию все ресурсы, созданные из ProjectTemplate, получают лейбл heritage: multitenancy-manager.
Он запрещают изменение ресурсов пользователями или любым контроллером, кроме multitenancy-manager.
Если необходимо разрешить изменение ресурса (например, для совместимости с другими системами, или в случае реализации собственного контроля изменения создаваемых объектов), добавьте к ресурсу лейбл projects.deckhouse.io/skip-heritage-label.

Пример:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
  namespace: {{ .projectName }}
  labels:
    projects.deckhouse.io/skip-heritage-label: "true"
    app: my-app
data:
  key: value

В этом случае ресурс получит лейблы projects.deckhouse.io/project и projects.deckhouse.io/project-template, но не получит лейбл heritage: multitenancy-manager.

Исключение ресурсов из управления multitenancy-manager

Если необходимо исключить ресурс из управления multitenancy-manager (например, если он должен управляться вручную или другим контроллером), добавьте к ресурсу лейбл projects.deckhouse.io/unmanaged.

Пример:

apiVersion: v1
kind: Secret
metadata:
  name: external-secret
  namespace: {{ .projectName }}
  labels:
    projects.deckhouse.io/unmanaged: "true"
type: Opaque
data:
  token: <base64-encoded-value>

Ресурсы с лейблом projects.deckhouse.io/unmanaged:

  • Будут созданы только один раз при создании проекта.
  • Не будут обновляться при последующих изменениях шаблона или обновлениях.
  • Не будут отслеживаться в статусе проекта.
  • Получат лейблы projects.deckhouse.io/project и projects.deckhouse.io/project-template, но не получат лейбл heritage: multitenancy-manager.

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

Реализация валидации изменений объектов с помощью пользовательского лейбла

Модуль multitenancy-manager использует ValidatingAdmissionPolicy для защиты ресурсов с лейблом heritage: multitenancy-manager от ручных изменений.
Вы можете реализовать аналогичную валидацию для ресурсов с любым лейблом.

Принцип работы валидации в multitenancy-manager

multitenancy-manager валидирует объекты с лейблом heritage: multitenancy-manager.
Для этого используются следующие ресурсы:

  1. ValidatingAdmissionPolicy — определяет правила валидации:
    • Операции: UPDATE и DELETE;
    • Проверка: разрешены только операции от имени service account контроллера;
    • Применяется ко всем ресурсам и API группам.
  2. ValidatingAdmissionPolicyBinding — определяет на какие объекты распространяется валидация:
    • Использует namespaceSelector и objectSelector для выбора ресурсов по лейблу heritage: multitenancy-manager.

Создание собственной валидации

Для реализации валидации для ресурсов с другим лейблом (например, heritage: my-custom-label):

  1. Создайте файл с манифестами ресурсов ValidatingAdmissionPolicy и ValidatingAdmissionPolicyBinding:

    apiVersion: admissionregistration.k8s.io/v1
    kind: ValidatingAdmissionPolicy
    metadata:
      name: my-custom-label-validation
    spec:
      failurePolicy: Fail
      matchConstraints:
        resourceRules:
          - apiGroups:   ["*"]
            apiVersions: ["*"]
            operations:  ["UPDATE", "DELETE"]
            resources:   ["*"]
            scope: "*"
      validations:
        - expression: 'request.userInfo.username == "system:serviceaccount:my-namespace:my-service-account"' # Замените на ваш сервисный аккаунт.
          reason: Forbidden
          messageExpression: 'object.kind == ''Namespace'' ? ''This resource is managed by '' + object.metadata.name + '' system. Manual modification is forbidden.''
            : ''This resource is managed by '' + object.metadata.namespace + '' system. Manual modification is forbidden.'''
    ---
    apiVersion: admissionregistration.k8s.io/v1
    kind: ValidatingAdmissionPolicyBinding
    metadata:
      name: my-custom-label-validation
    spec:
      policyName: my-custom-label-validation
      validationActions: [Deny, Audit]
      matchResources:
        namespaceSelector:
          matchLabels:
            heritage: my-custom-label
        objectSelector:
          matchLabels:
            heritage: my-custom-label
    
  2. Настройте параметры валидации:

    • policyName — уникальное имя политики (должно совпадать с Policy и Binding);
    • request.userInfo.username — имя сервисного аккаунта, которому разрешено изменять ресурсы (замените на ваш сервисный аккаунт);
    • heritage: my-custom-label — значение лейбла heritage для ваших ресурсов (замените на ваше значение). Запрещено использование значение multitenancy-manager, deckhouse;
    • failurePolicy: Fail — политика при ошибке валидации:
      • Fail — отклонять запрос при ошибке проверки,
      • Ignore — игнорировать ошибки валидации.
    • validationActions — действия валидации:
      • Deny — отклонять неразрешенные операции,
      • Audit — записывать операции в аудит лог.
  3. Примените политику:

    d8 k apply -f my-validation-policy.yaml
    
  4. Убедитесь, что ваши ресурсы имеют соответствующий лейбл heritage:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: my-resource
      labels:
        heritage: my-custom-label
    

Выдача кластерных ресурсов проектам

multitenancy-manager позволяет администраторам кластера управлять тем, какие кластерные ресурсы (например, StorageClass) можно использовать из неймспейсов проектов.

Для этого используются кастомные ресурсы:

  • GrantableClusterResourceDefinition (cluster-scoped) — регистрирует кластерный ресурс, который можно выдавать проектам. Определяет тип ресурса (grantedResource), где проверяются ссылки на него (usageReferences), базовую доступность (defaultAvailability) и способ определения значения по умолчанию для проекта (defaultFrom). Каждая ссылка отдельно включает подстановку значения по умолчанию через default: true. Указывайте этот параметр только для полей, значение которых всегда должно быть задано (например, storageClassName у PersistentVolumeClaim). Если отсутствие ссылки имеет смысл (например, для аннотации-переключателя), не указывайте default: true. В этом случае такая ссылка по-прежнему будет проверяться и учитываться в квоте, но её значение не будет подставляться автоматически.
  • ClusterResourceGrantPolicy (cluster-scoped) — выбирает проекты (по меткам неймспейса через projectSelector) и для каждого ресурса (resourceName) задаёт разрешённые имена (allowed, allowedSelector) и значение по умолчанию (default). Если задан allow-лист, использовать можно только ресурсы из этого списка.
  • AvailableClusterResource (namespaced, read-only, короткое имя available) — формируемый контроллером каталог доступных для проекта кластерных ресурсов. Пользователи проекта могут использовать его, чтобы узнать, какие ресурсы им доступны
  • ClusterResourceGrant (namespaced) — определяет квоты проекта на кластерные ресурсы (лимиты на количество объектов и на измеряемые величины, например запрошенный объём хранилища). В статусе объекта отображается текущее потребление.
apiVersion: multitenancy.deckhouse.io/v1alpha1
kind: GrantableClusterResourceDefinition
metadata:
  name: storageclasses
spec:
  grantedResource:
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
  enforcement: Managed
  defaultAvailability: All
  defaultFrom:
    annotationKey: storageclass.kubernetes.io/is-default-class
  usageReferences:
    - rule:
        apiGroups:
          - ""
        apiVersions:
          - v1
        resources:
          - persistentvolumeclaims
      fieldPath: $.spec.storageClassName
      default: true
---
apiVersion: multitenancy.deckhouse.io/v1alpha1
kind: ClusterResourceGrantPolicy
metadata:
  name: production-storage
spec:
  projectSelector:
    matchLabels:
      environment: production
  resources:
    - resourceName: storageclasses
      default: fast-ssd          # Перекрывает дефолт по аннотации.
      allowed:
        - fast-ssd
        - standard
      allowedSelector:           # Дополнительно разрешает любой StorageClass с меткой shared=true.
        matchLabels:
          shared: "true"

Особенности применения:

  • Проверяющий (validating) вебхук запрещает создание/обновление объектов в подходящих проектах, если используемое значение не разрешено. Уже присутствующие в объекте значения при обновлении не блокируются — существующие объекты продолжают работать.
  • Мутирующий (mutating) вебхук подставляет значение по умолчанию только при создании и только в ссылки, помеченные default: true. Ссылки без неё (например, аннотации-переключатели) никогда не заполняются.
  • Grant без совпавших проектов (или проект без совпавших grant’ов) ничего не ограничивает.

Дополнительные ресурсы