Вивчаємо Validating та Mutating Admission Policies

Використовуйте декларативні політики допуску для перевірки або зміни ресурсів під час допуску за допомогою Common Expression Language (CEL).

Ця сторінка дозволяє вам спробувати декларативні політики допуску, які дають змогу використовувати Common Expression Language (CEL) для перевірки або зміни ресурсів.

Kubernetes 1.36 підтримує два види політик допуску:

Цей посібник охоплює обидва види політик допуску.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Для визначення політик допуску ви повинні бути адміністратором кластеру. Переконайтеся, що ви маєте доступ адміністратора до кластеру, у якому ви навчаєтеся.

Для ValidatingAdmissionPolicy вам потрібно:

  • Кластер, що працює версією 1.30 або пізніше.

Для MutatingAdmissionPolicy вам потрібно:

  • Кластер, що працює версією 1.36 або пізніше. Якщо ви використовуєте стару версію Kubernetes, перевірте документацію для цієї версії.

Що таке декларативні політики допуску?

Декларативні політики допуску пропонують декларативну, вбудовану альтернативу вебхукам допуску.

Використовуючи Common Expression Language (CEL) для оголошення правил політики, ці політики оцінюються безпосередньо в API-сервері.

Ці політики мають широкі можливості налаштування, що дозволяє авторам політик визначати логіку, яку адміністратори кластерів можуть параметризувати та застосовувати до ресурсів залежно від потреб.

Типи API для політик допуску

Обидва види політик мають різні цілі.

ValidatingAdmissionPolicy призначена для забезпечення обмежень.

MutatingAdmissionPolicy призначена для зміни ресурсів під час допуску.

Елементи політики

Кожна застосована політика завжди має об’єкт політики (ValidatingAdmissionPolicy або MutatingAdmissionPolicy) та окремий обʼєкт звʼязку (ValidatingAdmissionPolicyBinding або MutatingAdmissionPolicyBinding).

Ви також можете використовувати параметри, які є необов’язковими. Щоб дізнатися більше, дивіться ресурси параметрів (ValidatingAdmissionPolicy) або ресурси параметрів (MutatingAdmissionPolicy).

Об’єкти політики описують абстрактну логіку політики за допомогою Common Expression Language (CEL). Наприклад, ValidatingAdmissionPolicy може забезпечувати обмеження кількості реплік або гарантувати наявність певних міток, тоді як MutatingAdmissionPolicy може змінювати ресурси, такі як додавання стандартної мітки до простору імен.

Об’єкти зв’язку пов’язують політику з вашим кластером та забезпечують обмеження. ValidatingAdmissionPolicyBinding або MutatingAdmissionPolicyBinding з’єднує політику з конкретними ресурсами. Якщо ви хочете застосувати політику лише до певної підгрупи ресурсів, привʼязки — це місце, де ви звужуєте область застосування політики (за допомогою matchResources).

Параметри дозволяють відокремити конфігурацію поведінки політики від її визначення. Ресурси параметрів посилаються на ресурси Kubernetes, доступні в API. Вони можуть бути вбудованими типами API (такими як ConfigMap) або можуть бути власними ресурсами. Привʼязка політики потім використовує spec.paramRef для посилання на фактичний ресурс параметра.

Якщо політика не потребує параметрів, ви залишаєте spec.paramKind не вказаним.

Вирази CEL

Обидва види політик спираються на мову виразів, відому як Common Expression Language (CEL). Прочитайте CEL у Kubernetes, щоб дізнатися більше.

Якщо ви новачок у CEL, потренуйтеся писати дуже простий вираз, такий як false || true. Ви можете тестувати вирази CEL у CEL Playground.

Дії політики

Кожна привʼязка політики допуску повинна вказувати одну або кілька дій, щоб оголосити, як політика застосовується.

ValidatingAdmissionPolicyBinding

Для ValidatingAdmissionPolicyBinding підтримуваними validationActions є:

Audit
Помилка перевірки включається до події аудиту для API-запиту.
Warn
Помилка перевірки повідомляється клієнту запиту як попередження.
Deny
Помилка перевірки призводить до відхилення запиту.

Перевірка політики, яка завершується невдачею або виникає помилка, застосовується відповідно до цих дій. Помилки, визначені failurePolicy, застосовуються відповідно до цих дій лише якщо failurePolicy встановлено як Fail (або не вказано).

Дивіться Анотації аудиту: помилки перевірки для отримання додаткової інформації про аудит політик.

Вам не дозволяється використовувати Deny і Warn разом, оскільки така комбінація дублювала б помилку перевірки в обох тілі відповіді API та HTTP-заголовку Warning:.

MutatingAdmissionPolicyBinding

Для MutatingAdmissionPolicyBinding дія завжди полягає у зміні об’єкта.

Ви можете використовувати JSON Patch або конфігурацію Kubernetes apply configuration.

Забезпечення дотримання шляхом перевірки

Тепер спробуйте визначити ValidatingAdmissionPolicy.

Нижче наведено приклад ValidatingAdmissionPolicy, яка вимагає, щоб будь-який Deployment мав кілька реплік.

---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "enforce-multiple-replicas-deployments"
  annotations:
    kubernetes.io/description: "Require that matching Deployments have multiple replicas"
spec:
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      resources:   ["deployments"]      # Deployment API
      operations:  ["CREATE", "UPDATE"] # дієслово API, перетворене на верхній регістр
  validations:
    - expression: "object.spec.replicas >= 2"

spec.validations містить вирази CEL, які використовують Common Expression Language (CEL) для перевірки запиту. Якщо вираз оцінюється як false, перевірка застосовується відповідно до поля spec.failurePolicy.

Напишіть політику подібним чином та застосуйте її.

Або, якщо ви хочете застосувати готовий маніфест:

kubectl apply --server-side -f https://k8s.io/examples/access/manifest-admission-control/vap-min-replicas.yaml

Сама по собі вона нічого не робить.

Ви можете спробувати створити Deployment з 0 або 1 реплікою; це працюватиме (хіба що інша політика завадить цьому).


Щоб зробити це, ви визначаєте ValidatingAdmissionPolicyBinding.

Виберіть простір імен, де ви будете застосовувати нову політику.

Нижче наведено приклад ValidatingAdmissionPolicyBinding для політики, яку ви створили:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: enforce-multiple-replicas-deployments-binding
spec:
  policyName: "enforce-multiple-replicas-deployments"
  validationActions: [Deny]
  matchResources:
    namespaceSelector:
      matchLabels:
        kubernetes.io/metadata.name: default # змініть це, щоб відповідати простору імен, який ви використовуєте

Увага:

Будь-хто з повним/адміністративним доступом до простору імен може записувати його мітки. Це включає видалення мітки з простору імен.

Мітка kubernetes.io/metadata.name захищена, але якщо ви використовуєте іншу мітку, будьте обережні, щоб переконатися, що лише довірені користувачі мають спосіб видалити або редагувати цю мітку, яку ви обираєте.

Створіть маніфест на основі цього прикладу YAML (якщо ви використовуєте простір імен default, ви можете використовувати його без змін). Застосуйте маніфест за допомогою kubectl apply.

Тестування політики

Тепер перевірте політику. Спробуйте створити Deployment та потім зменшити його до 0 реплік за допомогою kubectl scale. Що відбувається?

Ви можете змінити ValidatingAdmissionPolicyBinding, щоб мати іншу дію перевірки, замість Deny. Якщо ви обираєте дію перевірки Warning і спробуєте зменшити Deployment до 0 реплік, що відбувається?

Примітка:

Якщо ви дійсно змінили налаштування ValidatingAdmissionPolicyBinding так, щоб воно лише попереджало користувачів, то тут є проблема…

Назва неправильна! Якщо ви змінюєте ValidatingAdmissionPolicyBinding або повʼязану ValidatingAdmissionPolicy так, що вона лише попереджає людей, ви повинні перевірити, чи також потрібно змінити назву політики. Ви б змінили назву, щоб переконатися, що назва не вводить людей в оману.

Це не впливає на наявні ресурси

Якщо у вас є Deployment з 0 або 1 реплікою, і ви змінюєте ValidatingAdmissionPolicyBinding назад до Deny-режиму, це не впливає на жодні наявні ресурси.

(Якщо ви захочете спробувати збільшити Deployments до принаймні 2 реплік, ви можете досягти цього іншим способом — наприклад, використовуючи controller).

На цьому все для ValidatingAdmissionPolicy. Тепер ви дізнаєтеся про MutatingAdmissionPolicies.

Зміна ресурсів під час їх створення або зміни

Для цього прикладу уявіть, що ви хочете використовувати Pod security admission для забезпечення того, щоб простори імен, окрім системних просторів імен, застосовували стандарт безпеки Podʼів.

Подібно до перевірки, ви можете створити MutatingAdmissionPolicy, яка може змінювати ресурси під час допуску. Тип API, який вам потрібно змінити, — це Namespace.

Ось MutatingAdmissionPolicy, яка робить частину цього:

---
# Увага: перед тим, як застосувати цю політику default-pod-security-baseline,
# ознайомтеся з примітками до неї, щоб зрозуміти наслідки для інформаційної безпеки.
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionPolicy
metadata:
  name: "default-pod-security-baseline"
  annotations:
    kubernetes.io/description: "Default new namespaces to enforce the Baseline pod security standard"
spec:
  reinvocationPolicy: IfNeeded
  matchConstraints:
    resourceRules:
    - apiGroups:   [""]
      apiVersions: ["v1"]
      operations:  ["CREATE"]
      resources:   ["namespaces"]
  matchConditions:
    - name: "exclude-system-namespaces"
      # Якщо ім'я починається з "kube-", це системний простір імен.
      # Припускаємо, що API-сервер або інструменти управління кластером застосовують відповідні стандартні значення.
      expression: "!object.metadata.name.startsWith('kube-')"
    - name: "no-existing-pod-security-label"
      expression: "!('pod-security.kubernetes.io/enforce' in object.metadata.labels)"
  mutations:
    - patchType: "ApplyConfiguration"
      applyConfiguration:
        expression: "Object{metadata: Object.metadata{labels: {'pod-security.kubernetes.io/enforce': 'baseline'}}}"

Увага:

Ця політика встановлює стандартне значення. Той, хто має можливість оновлювати Namespace, може видалити мітку pod-security.kubernetes.io/enforce з простору імен.

Якщо ви не впевнені, що це означає, прочитайте документацію з Безпеки або отримайте іншу пораду з питань безпеки.

Щоб застосувати цю політику:

kubectl apply --server-side -f https://k8s.io/examples/access/manifest-admission-control/default-pod-security-baseline.yaml

MutatingAdmissionPolicyBinding потрібна для активації цієї політики; наприклад:

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionPolicyBinding
metadata:
  name: default-pod-security-baseline
spec:
  # назва MutatingAdmissionPolicy, яку застосовувати
  policyName: default-pod-security-baseline

Тестування політики

Спробуйте створити новий простір імен з назвою example:

kubectl create ns example

Перевірте його мітки:

kubectl describe ns example

Навіть якщо ви не вказали рівень забезпечення безпеки Podʼів, мітка була встановлена.

Далі перевірте, чи можете знайти спосіб обійти налаштування безпеки. Створіть YAML-маніфест для іншого Namespace:

apiVersion: v1
kind: Namespace
metadata:
  name: another-example
  labels:
    pod-security.kubernetes.io/enforce: privileged

Ви можете створити цей простір імен з локального маніфесту за допомогою kubectl apply --server-side. Чи спрацювало?

Так, і новий простір імен дозволяє запускати привілейовані Podʼи.

Ця політика допуску не була налаштована для перевірки або обмеження. Вона забезпечує стандартне значення, але ви можете встановити свій власний. Однак ви можете поєднати мутаційний допуск з валідаційним допуском як спосіб забезпечення чогось, але також зробити легким дотримання. (Посібник не пояснює це, але ви можете це зробити).

Забезпечення корисного стандартного значення означає, що коли люди нічого не встановлюють, вони отримують кращий результат, ніж просто побачити повідомлення про помилку. Уявіть, що у вас було б правило перевірки, щоб усі простори імен мали забезпечувати принаймні базовий стандарт. Той, хто не знав про це правило, міг би спробувати розгорнути щось і одразу побачити повідомлення про помилку, коли він спробує створити простір імен.

Використання ресурсу параметра

Ресурси параметрів дозволяють відокремити конфігурацію політики від її визначення. Політика може визначити paramKind, який описує групу, версію та тип (також відомий як GVK, від group, version, kind) ресурсу параметра. Потім прив’язка політики пов’язує цю політику з областю дії, до якої вона прив’язана, відповідно до налаштувань конкретного ресурсу параметра.

---
# Увага: перед тим, як застосувати цю політику default-pod-security-configurable,
# ознайомтеся з примітками до неї, щоб зрозуміти наслідки для інформаційної безпеки.
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionPolicy
metadata:
  name: "default-pod-security-configurable"
  annotations:
    kubernetes.io/description: "Default new namespaces to enforce the chosen pod security standard"
spec:
  reinvocationPolicy: IfNeeded
  paramKind:
    apiVersion: v1
    kind: ConfigMap
  matchConstraints:
    resourceRules:
    - apiGroups:   [""]
      apiVersions: ["v1"]
      operations:  ["CREATE"]
      resources:   ["namespaces"]
  matchConditions:
    - name: "exclude-system-namespaces"
      # Якщо ім'я починається з "kube-", це системний простір імен.
      # Припускаємо, що API-сервер або інструменти управління кластером застосовують відповідні стандартні значення.
      expression: "!object.metadata.name.startsWith('kube-')"
    - name: "no-existing-pod-security-label"
      expression: "!('pod-security.kubernetes.io/enforce' in object.metadata.labels)"
  mutations:
    - patchType: "ApplyConfiguration"
      applyConfiguration:
        expression: "Object{metadata: Object.metadata{labels: {'pod-security.kubernetes.io/enforce': params.data.default}}}"

Ось зразок MutatingAdmissionPolicyBinding:

---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionPolicyBinding
metadata:
  name: default-pod-security-configurable
spec:
  # назва MutatingAdmissionPolicy, яку застосовувати
  policyName: default-pod-security-configurable

  # параметри для використання
  paramRef:
    # якщо ConfigMap відсутній або порожній, не встановлювати стандартне значення
    # (але дозволити створення простору імен)
    parameterNotFoundAction: Allow

    # де знайти параметр
    namespace: kube-system
    name: default-pod-security-standard

і ось зразок ConfigMap, який потрібно помістити до простору імен kube-system:

---
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: kube-system
  name: default-pod-security-standard
data:
  default: baseline # також може бути "restricted"

Визначте обидва. Ви повинні створити ConfigMap першим; привʼязка очікує, що ресурс параметра вже існує (навіть якщо ви плануєте змінити його пізніше).

Тепер видаліть попередній MutatingAdmissionPolicyBinding:

kubectl delete mutatingadmissionpolicybindings/default-pod-security-baseline

і створіть новий простір імен:

kubectl create ns yet-another-example
kubectl describe ns yet-another-example

Чи були мітки встановлені за замовчуванням?

Зміна параметра

# Ця команда запускає редактор, який дозволяє змінити .data.default для параметра
kubectl --namespace kube-system edit configmap default-pod-security-standard

Після зміни спробуйте створити ще один простір імен. Що відбувається?

Очищення

Щоб видалити створені ресурси, виконайте такі команди:

kubectl delete validatingadmissionpolices/enforce-multiple-replicas-deployments \
               validatingadmissionpolicybindings/enforce-multiple-replicas-deployments

kubectl delete mutatingadmissionpolicies/default-pod-security-baseline \
               mutatingadmissionpolicybindings/default-pod-security-baseline

kubectl delete mutatingadmissionpolicies/default-pod-security-configurable \
               mutatingadmissionpolicybindings/default-pod-security-configurable

kubectl --namespace kube-system delete configmaps/default-pod-security-standard

kubectl delete namespaces/example namespaces/another-example namespaces/yet-another-example

Якщо ви створили будь-які тестові Podʼи або тестові простори імен, очистьте їх також.

Востаннє змінено July 15, 2026 at 12:45 AM PST: [uk] Ukrainian translation (all-in-one) (193b0d4ea4)