Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.

Повернутися до звичайного перегляду сторінки.

Політики

Керування безпекою та найкращими практиками за допомогою політик.

Політики Kubernetes — це конфігурації, які керують іншими конфігураціями або поведінкою під час виконання. Kubernetes пропонує різні форми політик, описані нижче:

Застосування політик за допомогою обʼєктів API

Деякі обʼєкти API діють як політики. Ось кілька прикладів:

  • NetworkPolicies можна використовувати для обмеження вхідного та вихідного трафіку робочого навантаження.
  • LimitRanges керують обмеженнями розподілу ресурсів для різних типів обʼєктів.
  • ResourceQuotas обмежують споживання ресурсів для простору імен.

Застосування політик за допомогою контролерів допуску

Контролер допуску працює в API-сервері та може перевіряти або змінювати запити до API. Деякі контролери допуску застосовують політики. Наприклад, контролер допуску AlwaysPullImages змінює новий Pod, встановлюючи для нього політику завантаження образу Always.

У Kubernetes є кілька вбудованих контролерів допуску, які можна налаштувати за допомогою прапорця --enable-admission-plugins API-сервера.

Детальні відомості про контролери допуску, з повним списком доступних контролерів допуску, ви знайдете в окремому розділі:

Застосування політик за допомогою ValidatingAdmissionPolicy

Політики перевірки допуску дають змогу виконувати налаштовувані перевірки в API-сервері за допомогою мови виразів Common Expression Language (CEL). Наприклад, ValidatingAdmissionPolicy можна використати, щоб заборонити використання теґу образу latest.

ValidatingAdmissionPolicy працює із запитом до API і може використовуватися для блокування, аудиту та попередження користувачів про невідповідні конфігурації.

Детальні відомості про API ValidatingAdmissionPolicy з прикладами ви знайдете в окремому розділі:

Застосування політик за допомогою динамічного контролю допуску

Динамічні контролери допуску (або вебхуки допуску) працюють поза API-сервером як окремі застосунки, які реєструються для отримання запитів вебхуків, щоб виконувати перевірку або зміну запитів до API.

Динамічні контролери допуску можна використовувати для застосування політик до запитів до API та запуску інших робочих процесів на основі політик. Динамічний контролер допуску може виконувати складні перевірки, зокрема ті, що потребують отримання інших ресурсів кластера та зовнішніх даних. Наприклад, перевірка образу може шукати дані в реєстрах OCI, щоб перевірити підписи та атестації образів контейнерів.

Детальні відомості про динамічний контроль допуску ви знайдете в окремому розділі:

Реалізації

Примітка: Цей розділ містить посилання на проєкти сторонніх розробників, які надають функціонал, необхідний для Kubernetes. Автори проєкту Kubernetes не несуть відповідальності за ці проєкти. Проєкти вказано в алфавітному порядку. Щоб додати проєкт до цього списку, ознайомтеся з посібником з контенту перед надсиланням змін. Докладніше.

Динамічні контролери допуску, які діють як гнучкі рушії політик, розробляються в екосистемі Kubernetes, серед них:

Застосування політик за допомогою конфігурацій Kubelet

Kubernetes дозволяє налаштовувати Kubelet на кожному робочому вузлі. Деякі конфігурації Kubelet діють як політики:

  • Обмеження та резервування ID процесів використовуються для обмеження та резервування доступних для розподілу PID.
  • Менеджери ресурсів вузлів можуть керувати обчислювальними ресурсами, памʼяттю та ресурсами пристроїв для робочих навантажень, критичних до затримок, і робочих навантажень із високою пропускною здатністю.

1 - Діапазони обмежень

Стандартно контейнери запускаються з необмеженими обчислювальними ресурсами у кластері Kubernetes. Використовуючи квоти ресурсів Kubernetes, адміністратори (також відомі як оператори кластера) можуть обмежувати споживання та створення ресурсів кластера (таких як час CPU, памʼять та постійне сховище) у визначеному просторі імен. У межах простору імен Pod може використовувати стільки CPU та памʼяті, скільки дозволяють ResourceQuotas, що застосовуються до цього простору імен. Як оператору кластера або адміністратору на рівні простору імен вам також може бути важливо переконатися, що один обʼєкт не може монополізувати всі доступні ресурси у просторі імен.

LimitRange — це політика для обмеження виділення ресурсів (обмежень і запитів), які можна вказати для кожного відповідного типу обʼєктів (такого як Pod або PersistentVolumeClaim) у просторі імен.

LimitRange надає обмеження, які можуть:

  • Застосовувати мінімальне та максимальне використання обчислювальних ресурсів на Pod або контейнер у просторі імен.
  • Застосовувати мінімальний та максимальний запит на сховище для PersistentVolumeClaim у просторі імен.
  • Застосовувати співвідношення між запитом та обмеженням для ресурсу у просторі імен.
  • Встановлювати стандартний запит/обмеження для обчислювальних ресурсів у просторі імен та автоматично додавати їх до контейнерів під час виконання.

Kubernetes обмежує виділення ресурсів для Podʼів у певному просторі імен, якщо у цьому просторі імен є хоча б один обʼєкт LimitRange.

Назва обʼєкта LimitRange має бути дійсною назвою DNS-піддомену.

Вимоги до обмежень і запитів ресурсів

  • Адміністратор створює LimitRange у просторі імен.
  • Користувачі створюють (або намагаються створити) обʼєкти у цьому просторі імен, такі як Podʼи або PersistentVolumeClaims.
  • По-перше, контролер допуску LimitRange застосовує стандартні значення запиту та обмеження для всіх Podʼів (та їхніх контейнерів), які не задають вимог до обчислювальних ресурсів.
  • По-друге, LimitRange відстежує використання, щоб воно не перевищувало мінімум, максимум і співвідношення ресурсів, визначені в будь-якому LimitRange у цьому просторі імен.
  • Якщо ви намагаєтеся створити або оновити обʼєкт (Pod або PersistentVolumeClaim), який порушує обмеження LimitRange, ваш запит до API-сервера буде відхилено з HTTP-кодом стану 403 Forbidden та повідомленням, що пояснює порушене обмеження.
  • Якщо ви додаєте в простір імен LimitRange, який застосовується до обчислювальних ресурсів, таких як cpu та memory, ви повинні вказати запити або обмеження для цих значень. Інакше система може відхилити створення Podʼа.
  • Перевірка LimitRange відбувається лише на етапі допуску Podʼа, а не для запущених Podʼів. Якщо ви додаєте або змінюєте LimitRange, Podʼи, які вже існують у цьому просторі імен, залишаються без змін.
  • Якщо у просторі імен існує два або більше обʼєктів LimitRange, то не визначено, яке стандартне значення буде застосовано.

LimitRange та перевірки допуску для Podʼів

LimitRange не перевіряє узгодженість стандартних значень, які він застосовує. Це означає, що стандартне значення для limit, встановлене LimitRange, може бути меншим за значення request, вказане для контейнера в специфікації, яку клієнт надсилає до API-сервера. Якщо це станеться, фінальний Pod не буде придатним для планування.

Наприклад, ви визначаєте LimitRange таким маніфестом:

Примітка:

Наведені далі приклади працюють у просторі імен default вашого кластера, оскільки параметр namespace не визначено, а область дії LimitRange обмежена рівнем простору імен. Це означає, що будь-які посилання або операції в цих прикладах взаємодіятимуть з елементами в просторі імен default вашого кластера. Ви можете перевизначити робочий простір імен, налаштувавши namespace у полі metadata.namespace.
apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-resource-constraint
spec:
  limits:
  - default: # this section defines default limits
      cpu: 500m
    defaultRequest: # this section defines default requests
      cpu: 500m
    max: # max and min define the limit range
      cpu: "1"
    min:
      cpu: 100m
    type: Container

разом із Podʼом, який оголошує запит ресурсу CPU 700m, але не обмеження:

apiVersion: v1
kind: Pod
metadata:
  name: example-conflict-with-limitrange-cpu
spec:
  containers:
  - name: demo
    image: registry.k8s.io/pause:3.8
    resources:
      requests:
        cpu: 700m

тоді цей Pod не буде заплановано, і він завершиться помилкою, схожою на таку:

Pod "example-conflict-with-limitrange-cpu" is invalid: spec.containers[0].resources.requests: Invalid value: "700m": must be less than or equal to cpu limit

Якщо ви встановите і request, і limit, то цей новий Pod буде успішно заплановано, навіть за наявності того самого LimitRange:

apiVersion: v1
kind: Pod
metadata:
  name: example-no-conflict-with-limitrange-cpu
spec:
  containers:
  - name: demo
    image: registry.k8s.io/pause:3.8
    resources:
      requests:
        cpu: 700m
      limits:
        cpu: 700m

Приклади обмежень ресурсів

Приклади політик, які можна створити за допомогою LimitRange:

  • У кластері з 2 вузлів місткістю 8 GiB RAM та 16 ядер обмежте Podʼи в просторі імен запитом 100m CPU з максимальним обмеженням 500m для CPU та запитом 200Mi для памʼяті з максимальним обмеженням 600Mi для памʼяті.
  • Визначте стандартне обмеження та запит CPU на рівні 150m та стандартний запит памʼяті на рівні 300Mi для контейнерів, що запускаються без запитів CPU та памʼяті у своїх специфікаціях.

У випадку, коли загальні обмеження простору імен менші за суму обмежень Podʼів/контейнерів, може виникнути конкуренція за ресурси. У цьому випадку контейнери або Podʼи не будуть створені.

Ні конкуренція, ні зміни LimitRange не впливають на вже створені ресурси.

Що далі

Приклади використання обмежень дивіться тут:

Контекст та історичну інформацію дивіться в проєктному документі LimitRanger.

2 - Квоти ресурсів

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

Квоти ресурсів — це інструмент, за допомогою якого адміністратори розвʼязують цю проблему.

Квота ресурсів, визначена обʼєктом ResourceQuota, задає обмеження загального споживання ресурсів у кожному просторі імен. ResourceQuota також може обмежувати кількість обʼєктів, які можна створити в просторі імен, за типом API, а також загальний обсяг інфраструктурних ресурсів, які можуть споживати обʼєкти API в цьому просторі імен.

Увага:

Ані конкуренція, ані зміни до квоти не вплинуть на вже створені ресурси.

Як працюють ResourceQuotas у Kubernetes

ResourceQuotas працюють так:

  • Різні команди працюють у різних просторах імен. Цей поділ можна забезпечити за допомогою RBAC або будь-якого іншого механізму авторизації.

  • Адміністратор кластера створює принаймні одну ResourceQuota для кожного простору імен.

    • Щоб ці вимоги залишалися чинними, адміністратор кластера також повинен обмежити доступ до видалення або оновлення цієї ResourceQuota, наприклад, визначивши ValidatingAdmissionPolicy.
  • Користувачі створюють ресурси (Podʼи, Services тощо) у просторі імен, а система квот відстежує використання, щоб воно не перевищувало жорстких обмежень ресурсів, визначених у ResourceQuota.

    Ви можете застосувати до ResourceQuota область дії, щоб обмежити, де вона застосовується.

  • Якщо створення або оновлення ресурсу порушує обмеження квоти, панель управління відхиляє цей запит із кодом стану HTTP 403 Forbidden. Помилка містить повідомлення з поясненням обмеження, яке було б порушено.

  • Якщо квоти увімкнено в просторі імен для таких ресурсів, як cpu та memory, користувачі повинні вказувати запити або обмеження для цих значень під час визначення Podʼа; інакше система квот може відхилити створення Podʼа.

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

Примітка:

  • Ви можете визначити LimitRange, щоб примусово встановлювати стандартні значення для Podʼів, які не задають вимог до обчислювальних ресурсів (щоб користувачам не доводилося памʼятати про це).

Часто ви не створюєте Podʼи безпосередньо; наприклад, ви зазвичай створюєте обʼєкт керування робочим навантаженням, такий як Deployment. Якщо ви створюєте Deployment, який намагається використати більше ресурсів, ніж доступно, створення Deployment (або іншого обʼєкта керування робочим навантаженням) буде успішним, але Deployment може бути не в змозі забезпечити існування всіх керованих ним Podʼів. У цьому випадку ви можете перевірити стан Deployment, наприклад, за допомогою kubectl describe, щоб дізнатися, що сталося.

  • Для ресурсів cpu та memory ResourceQuotas вимагають, щоб кожен (новий) Pod у цьому просторі імен встановлював обмеження для цього ресурсу. Якщо ви застосовуєте квоту ресурсів у просторі імен для cpu або memory, ви та інші клієнти повинні вказувати requests або limits для цього ресурсу для кожного нового Podʼа, який ви надсилаєте. Якщо ви цього не зробите, панель управління може відхилити допуск цього Podʼа.
  • Для інших ресурсів: ResourceQuota працює та ігнорує Podʼи в просторі імен, які не встановлюють обмеження або запит для цього ресурсу. Це означає, що ви можете створити новий Pod без обмеження/запиту тимчасового сховища, якщо квота ресурсів обмежує тимчасове сховище цього простору імен.

Ви можете використовувати LimitRange для автоматичного встановлення стандартного запиту для цих ресурсів.

Назва обʼєкта ResourceQuota має бути дійсною назвою DNS-піддомену.

Приклади політик, які можна створити за допомогою просторів імен та квот:

  • У кластері місткістю 32 GiB RAM і 16 ядер дозвольте команді A використовувати 20 GiB і 10 ядер, дозвольте команді B використовувати 10 GiB і 4 ядра, а 2 GiB і 2 ядра залиште в резерві для майбутнього розподілу.
  • Обмежте простір імен "testing" використанням 1 ядра та 1 GiB RAM. Дозвольте простору імен "production" використовувати будь-який обсяг.

У випадку, коли загальна місткість кластера менша за суму квот просторів імен, може виникнути конкуренція за ресурси. Це обробляється за принципом «перший прийшов — перший обслужений».

Увімкнення квоти ресурсів

Підтримка ResourceQuota стандартно увімкнена в багатьох дистрибутивах Kubernetes. Вона увімкнена, коли прапорець --enable-admission-plugins= API-сервера має ResourceQuota серед своїх аргументів.

Квота ресурсів застосовується в певному просторі імен, коли у цьому просторі імен є ResourceQuota.

Типи квот ресурсів

Механізм ResourceQuota дозволяє застосовувати різні види обмежень. У цьому розділі описано типи обмежень, які можна застосовувати.

Квота на інфраструктурні ресурси

Ви можете обмежити загальну суму обчислювальних ресурсів, які можна запитати в певному просторі імен.

Підтримуються такі типи ресурсів:

Назва ресурсуОпис
limits.cpuДля всіх Podʼів у нетермінальному стані сума обмежень CPU не може перевищувати це значення.
limits.memoryДля всіх Podʼів у нетермінальному стані сума обмежень памʼяті не може перевищувати це значення.
requests.cpuДля всіх Podʼів у нетермінальному стані сума запитів CPU не може перевищувати це значення.
requests.memoryДля всіх Podʼів у нетермінальному стані сума запитів памʼяті не може перевищувати це значення.
hugepages-<size>Для всіх Podʼів у нетермінальному стані кількість запитів великих сторінок зазначеного розміру не може перевищувати це значення.
cpuТе саме, що і requests.cpu
memoryТе саме, що і requests.memory

Квота для розширених ресурсів

Крім згаданих вище ресурсів, у випуску 1.10 було додано підтримку квот для розширених ресурсів.

Оскільки overcommit для розширених ресурсів не дозволяється, немає сенсу вказувати і requests, і limits для одного й того самого розширеного ресурсу у квоті. Тому для розширених ресурсів дозволені лише елементи квоти з префіксом requests..

Візьмімо як приклад ресурс GPU: якщо назва ресурсу — nvidia.com/gpu і ви хочете обмежити загальну кількість запитаних GPU в просторі імен до 4, ви можете визначити квоту так:

  • requests.nvidia.com/gpu: 4

Докладніше дивіться в розділі Перегляд та встановлення квот.

Квота для запитів на ресурси DRA

Запити на ресурси DRA (Dynamic Resource Allocation) можуть запитувати ресурси DRA за класом пристроїв. Наприклад, для класу пристроїв із назвою examplegpu, якщо ви хочете обмежити загальну кількість GPU, запитаних у просторі імен, до 4, ви можете визначити квоту так:

  • examplegpu.deviceclass.resource.k8s.io/devices: 4

Коли увімкнено виділення розширених ресурсів за допомогою DRA, той самий клас пристроїв із назвою examplegpu можна запитувати через розширений ресурс або явно, коли в полі ExtendedResourceName класу пристроїв задано, скажімо, example.com/gpu, тоді ви можете визначити квоту так:

  • requests.example.com/gpu: 4

або неявно, використовуючи похідну назву розширеного ресурсу від назви класу пристроїв examplegpu, тоді ви можете визначити квоту так:

  • requests.deviceclass.resource.kubernetes.io/examplegpu: 4

Усі пристрої, запитані через запити на ресурси або розширені ресурси, враховуються у всіх трьох наведених вище квотах. Квота розширеного ресурсу, наприклад requests.example.com/gpu: 4, також враховує пристрої, надані втулком пристроїв.

Докладніше дивіться в розділі Перегляд та встановлення квот.

Квота для сховища

Ви можете обмежити загальний обсяг сховища для томів, який можна запитати в певному просторі імен.

Крім того, ви можете обмежити споживання ресурсів сховища на основі повʼязаного StorageClass.

Назва ресурсуОпис
requests.storageДля всіх PersistentVolumeClaims сума запитів на сховище не може перевищувати це значення.
persistentvolumeclaimsЗагальна кількість PersistentVolumeClaims, які можуть існувати у просторі імен.
<storage-class-name>.storageclass.storage.k8s.io/requests.storageДля всіх PersistentVolumeClaims, повʼязаних із <storage-class-name>, сума запитів на сховище не може перевищувати це значення.
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaimsДля всіх PersistentVolumeClaims, повʼязаних із <storage-class-name>, загальна кількість PersistentVolumeClaims, які можуть існувати у просторі імен.

Наприклад, якщо ви хочете встановити квоту для сховища зі StorageClass gold окремо від StorageClass bronze, ви можете визначити квоту так:

  • gold.storageclass.storage.k8s.io/requests.storage: 500Gi
  • bronze.storageclass.storage.k8s.io/requests.storage: 100Gi

Квота для локального тимчасового сховища

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.8
Назва ресурсуОпис
requests.ephemeral-storageДля всіх Podʼів у просторі імен сума запитів на локальне тимчасове сховище не може перевищувати це значення.
limits.ephemeral-storageДля всіх Podʼів у просторі імен сума обмежень на локальне тимчасове сховище не може перевищувати це значення.
ephemeral-storageТе саме, що і requests.ephemeral-storage.

Примітка:

Під час використання середовища виконання контейнерів CRI логи контейнерів зараховуються до квоти тимчасового сховища. Це може призвести до неочікуваного виселення Podʼів, які вичерпали свої квоти сховища.

Докладніше дивіться в розділі Архітектура логів.

Квота на кількість обʼєктів

Ви можете встановити квоту на загальну кількість одного конкретного типу ресурсу в API Kubernetes, використовуючи такий синтаксис:

  • count/<resource>.<group> для ресурсів із груп API, що не належать до основної (non-core)
  • count/<resource> для ресурсів з основної групи API (core)

Наприклад, API PodTemplate входить до основної групи API, тому, якщо ви хочете обмежити кількість обʼєктів PodTemplate у просторі імен, використовуйте count/podtemplates.

Такі типи квот корисні для захисту від вичерпання сховища панелі управління. Наприклад, ви можете обмежити кількість Secrets на сервері, враховуючи їхній великий розмір. Занадто велика кількість Secrets у кластері може фактично завадити запуску серверів і контролерів. Ви можете встановити квоту для Jobs, щоб захиститися від неправильно налаштованого CronJob. CronJobs, які створюють занадто багато Jobs у просторі імен, можуть призвести до відмови в обслуговуванні.

Якщо ви визначаєте квоту таким чином, вона застосовується до API Kubernetes, які є частиною API-сервера, та до будь-яких власних ресурсів, що підтримуються CustomResourceDefinition. Наприклад, щоб створити квоту на власний ресурс widgets у групі API example.com, використовуйте count/widgets.example.com. Якщо ви використовуєте агрегацію API для додавання власних API, які не визначені як CustomResourceDefinitions, основна панель управління Kubernetes не застосовує квоту до агрегованого API. Очікується, що сервер розширення API забезпечуватиме застосування квоти, якщо це доречно для цього власного API.

Загальний синтаксис

Нижче наведено список поширених прикладів типів обʼєктів, які ви можете захотіти підпорядкувати квоті на кількість обʼєктів, перелічених за рядками конфігурації, які ви будете використовувати.

  • count/pods
  • count/persistentvolumeclaims
  • count/services
  • count/secrets
  • count/configmaps
  • count/deployments.apps
  • count/replicasets.apps
  • count/statefulsets.apps
  • count/jobs.batch
  • count/cronjobs.batch
Спеціалізований синтаксис

Існує інший синтаксис для встановлення такого самого типу квоти, який працює лише для певних типів API. Підтримуються такі типи:

Назва ресурсуОпис
configmapsЗагальна кількість ConfigMaps, які можуть існувати в просторі імен.
persistentvolumeclaimsЗагальна кількість PersistentVolumeClaims, які можуть існувати в просторі імен.
podsЗагальна кількість Podʼів у нетермінальному стані, які можуть існувати в просторі імен. Pod перебуває в термінальному стані, якщо .status.phase in (Failed, Succeeded) є true.
replicationcontrollersЗагальна кількість ReplicationControllers, які можуть існувати в просторі імен.
resourcequotasЗагальна кількість ResourceQuotas, які можуть існувати в просторі імен.
servicesЗагальна кількість Services, які можуть існувати в просторі імен.
services.loadbalancersЗагальна кількість Services типу LoadBalancer, які можуть існувати в просторі імен.
services.nodeportsЗагальна кількість NodePorts, виділених Services типу NodePort чи LoadBalancer, які можуть існувати в просторі імен.
secretsЗагальна кількість Secrets, які можуть існувати в просторі імен.

Наприклад, квота pods рахує та обмежує максимальну кількість pods, створених в одному просторі імен, які не є термінальними. Ви можете встановити квоту pods у просторі імен, щоб уникнути випадку, коли користувач створює багато невеликих Podʼів і вичерпує запас IP-адрес Podʼів у кластері.

Більше прикладів можна знайти в розділі Перегляд та встановлення квот.

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

kubectl підтримує створення, оновлення та перегляд квот:

kubectl create namespace myspace
cat <<EOF > compute-resources.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-resources
spec:
  hard:
    requests.cpu: "1"
    requests.memory: "1Gi"
    limits.cpu: "2"
    limits.memory: "2Gi"
    requests.nvidia.com/gpu: 4
EOF
kubectl create -f ./compute-resources.yaml --namespace=myspace
cat <<EOF > object-counts.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-counts
spec:
  hard:
    configmaps: "10"
    persistentvolumeclaims: "4"
    pods: "4"
    replicationcontrollers: "20"
    secrets: "10"
    services: "10"
    services.loadbalancers: "2"
EOF
kubectl create -f ./object-counts.yaml --namespace=myspace
kubectl get quota --namespace=myspace
NAME                    AGE
compute-resources       30s
object-counts           32s
kubectl describe quota compute-resources --namespace=myspace
Name:                    compute-resources
Namespace:               myspace
Resource                 Used  Hard
--------                 ----  ----
limits.cpu               0     2
limits.memory            0     2Gi
requests.cpu             0     1
requests.memory          0     1Gi
requests.nvidia.com/gpu  0     4
kubectl describe quota object-counts --namespace=myspace
Name:                   object-counts
Namespace:              myspace
Resource                Used    Hard
--------                ----    ----
configmaps              0       10
persistentvolumeclaims  0       4
pods                    0       4
replicationcontrollers  0       20
secrets                 1       10
services                0       10
services.loadbalancers  0       2

kubectl також підтримує квоту на кількість обʼєктів для всіх стандартних ресурсів простору імен, використовуючи синтаксис count/<resource>.<group>:

kubectl create namespace myspace
kubectl create quota test --hard=count/deployments.apps=2,count/replicasets.apps=4,count/pods=3,count/secrets=4 --namespace=myspace
kubectl create deployment nginx --image=nginx --namespace=myspace --replicas=2
kubectl describe quota --namespace=myspace
Name:                         test
Namespace:                    myspace
Resource                      Used  Hard
--------                      ----  ----
count/deployments.apps        1     2
count/pods                    2     3
count/replicasets.apps        1     4
count/secrets                 1     4

Квота та місткість кластера

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

Іноді можуть знадобитися більш складні політики, такі як:

  • Пропорційно розподіляти загальні ресурси кластера між кількома командами.
  • Дозволяти кожному орендарю збільшувати використання ресурсів за потреби, але мати щедре обмеження, щоб запобігти випадковому вичерпанню ресурсів.
  • Виявляти попит з боку одного простору імен, додавати вузли та збільшувати квоту.

Такі політики можна реалізувати, використовуючи ResourceQuotas як будівельні блоки, написавши «контролер», який стежить за використанням квот і коригує жорсткі обмеження квот кожного простору імен відповідно до інших сигналів.

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

Області дії квоти

Кожна квота може мати повʼязаний набір scopes. Квота вимірюватиме використання ресурсу лише тоді, коли він відповідає перетину перелічених областей дії.

Коли до квоти додається область дії, вона обмежує кількість підтримуваних ресурсів тими, що стосуються цієї області дії. Ресурси, вказані у квоті поза дозволеним набором, призводять до помилки перевірки.

Kubernetes 1.37 підтримує такі області дії:

ОбластьОпис
BestEffortВідповідає Podʼам із якістю обслуговування best-effort.
CrossNamespacePodAffinityВідповідає Podʼам, які мають правила (анти)спорідненості Podʼів між просторами імен.
NotBestEffortВідповідає Podʼам, які не мають якості обслуговування best-effort.
NotTerminatingВідповідає Podʼам, де .spec.activeDeadlineSeconds є nil.
PriorityClassВідповідає Podʼам, які посилаються на вказаний клас пріоритету.
TerminatingВідповідає Podʼам, де .spec.activeDeadlineSeconds >= 0.
VolumeAttributesClassВідповідає PersistentVolumeClaims, які посилаються на вказаний клас атрибутів тому.

ResourceQuotas із заданою областю дії також можуть мати необовʼязкове поле scopeSelector. Ви визначаєте один або кілька виразів відповідності, які вказують operators і, якщо це доречно, набір values для відповідності. Наприклад:

  scopeSelector:
    matchExpressions:
      - scopeName: BestEffort # Відповідає Podʼам із якістю обслуговування best-effort
        operator: Exists # необовʼязково; для області дії BestEffort "Exists" мається на увазі

scopeSelector підтримує такі значення в полі operator:

  • In
  • NotIn
  • Exists
  • DoesNotExist

Якщо оператором є In або NotIn, поле values повинно мати щонайменше одне значення. Наприклад:

  scopeSelector:
    matchExpressions:
      - scopeName: PriorityClass
        operator: In
        values:
          - middle

Якщо оператором є Exists або DoesNotExist, поле values НЕ повинно бути вказане.

Область дії для Podʼів Best effort

Ця область дії відстежує лише квоту, спожиту Podʼами. Вона відповідає лише Podʼам, які мають клас QoS best-effort.

operator для scopeSelector повинен бути Exists.

Область дії для Podʼів Not-best-effort

Ця область дії відстежує лише квоту, спожиту Podʼами. Вона відповідає лише Podʼам, які мають клас QoS Guaranteed або Burstable.

operator для scopeSelector повинен бути Exists.

Область дії для Podʼів Non-terminating

Ця область дії відстежує лише квоту, спожиту Podʼами, які не завершуються. operator для scopeSelector повинен бути Exists.

Pod вважається таким, що не завершується, якщо поле .spec.activeDeadlineSeconds не встановлено.

Ви можете використовувати ResourceQuota з цією областю дії для керування такими ресурсами:

  • count.pods
  • pods
  • cpu
  • memory
  • requests.cpu
  • requests.memory
  • limits.cpu
  • limits.memory

Область дії Podʼів Terminating

Ця область дії відстежує лише квоту, спожиту Podʼами, які завершуються. operator для scopeSelector повинен бути Exists.

Pod вважається таким, що завершується, якщо поле .spec.activeDeadlineSeconds встановлено на будь-яке число.

Ви можете використовувати ResourceQuota з цією областю дії для керування такими ресурсами:

  • count.pods
  • pods
  • cpu
  • memory
  • requests.cpu
  • requests.memory
  • limits.cpu
  • limits.memory

Область дії спорідненості Podʼів між просторами імен

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.24

Ви можете використовувати область дії квоти CrossNamespacePodAffinity, щоб обмежити, які простори імен можуть мати Podʼи з правилами спорідненості, що охоплюють кілька просторів імен. Зокрема, вона контролює, яким Podʼам дозволено встановлювати поля namespaces або namespaceSelector у правилах (анти)спорідненості Podʼів.

Може бути бажаним не дозволяти користувачам використовувати правила спорідненості між просторами імен, оскільки Pod з обмеженнями антиспорідненості може не дати Podʼам з усіх інших просторів імен бути запланованими в домені відмов.

За допомогою цієї області дії ви (як адміністратор кластера) можете заборонити певним просторам імен (наприклад, foo-ns у наведеному нижче прикладі) мати Podʼи, які використовують спорідненість Podʼів між просторами імен. Для цього створіть у цьому просторі імен обʼєкт ResourceQuota з областю дії CrossNamespacePodAffinity та жорстким обмеженням 0:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: disable-cross-namespace-affinity
  namespace: foo-ns
spec:
  hard:
    pods: "0"
  scopeSelector:
    matchExpressions:
    - scopeName: CrossNamespacePodAffinity
      operator: Exists

Якщо ви хочете стандартно заборонити використання namespaces та namespaceSelector і дозволити його лише для певних просторів імен, ви можете налаштувати CrossNamespacePodAffinity як обмежений ресурс, встановивши для прапорця kube-apiserver --admission-control-config-file шлях до такого конфігураційного файлу:

apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
  configuration:
    apiVersion: apiserver.config.k8s.io/v1
    kind: ResourceQuotaConfiguration
    limitedResources:
    - resource: pods
      matchScopes:
      - scopeName: CrossNamespacePodAffinity
        operator: Exists

За такої конфігурації Podʼи можуть використовувати namespaces та namespaceSelector у спорідненості Podʼів лише тоді, коли простір імен, у якому вони створені, має обʼєкт квоти ресурсів з областю дії CrossNamespacePodAffinity та жорстким обмеженням, більшим або рівним кількості Podʼів, що використовують ці поля.

Область дії PriorityClass

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.17

ResourceQuota з областю дії PriorityClass відповідає лише тим Podʼам, які мають певний клас пріоритету, і лише якщо будь-який scopeSelector у специфікації квоти вибирає певний Pod.

Podʼи можна створювати з певним пріоритетом. Ви можете контролювати споживання системних ресурсів Podʼом на основі його пріоритету, використовуючи поле scopeSelector у специфікації квоти.

Коли область дії квоти задано для PriorityClass за допомогою поля scopeSelector, ResourceQuota може відстежувати (і обмежувати) лише такі ресурси:

  • pods
  • cpu
  • memory
  • ephemeral-storage
  • limits.cpu
  • limits.memory
  • limits.ephemeral-storage
  • requests.cpu
  • requests.memory
  • requests.ephemeral-storage

Приклад

Цей приклад створює ResourceQuota, яка відповідає Podʼам з певними пріоритетами. Приклад працює так:

  • Podʼи в кластері мають один із трьох PriorityClasses: "low", "medium", "high".
    • Якщо ви хочете спробувати це, використовуйте тестовий кластер і налаштуйте ці три PriorityClasses, перш ніж продовжувати.
  • Для кожного пріоритету створюється один обʼєкт квоти.

Перегляньте цей набір ResourceQuotas:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: pods-high
spec:
  hard:
    cpu: "1000"
    memory: "200Gi"
    pods: "10"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values: ["high"]
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pods-medium
spec:
  hard:
    cpu: "10"
    memory: "20Gi"
    pods: "10"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values: ["medium"]
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pods-low
spec:
  hard:
    cpu: "5"
    memory: "10Gi"
    pods: "10"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values: ["low"]

Застосуйте YAML за допомогою kubectl create.

kubectl create -f https://k8s.io/examples/policy/quota.yaml
resourcequota/pods-high created
resourcequota/pods-medium created
resourcequota/pods-low created

Перевірте, що квота Used дорівнює 0, за допомогою команди kubectl describe quota.

kubectl describe quota
Name:       pods-high
Namespace:  default
Resource    Used  Hard
--------    ----  ----
cpu         0     1k
memory      0     200Gi
pods        0     10


Name:       pods-low
Namespace:  default
Resource    Used  Hard
--------    ----  ----
cpu         0     5
memory      0     10Gi
pods        0     10


Name:       pods-medium
Namespace:  default
Resource    Used  Hard
--------    ----  ----
cpu         0     10
memory      0     20Gi
pods        0     10

Створіть Pod з пріоритетом "high".

apiVersion: v1
kind: Pod
metadata:
  name: high-priority
spec:
  containers:
  - name: high-priority
    image: ubuntu
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello; sleep 10;done"]
    resources:
      requests:
        memory: "10Gi"
        cpu: "500m"
      limits:
        memory: "10Gi"
        cpu: "500m"
  priorityClassName: high

Створіть Pod:

kubectl create -f https://k8s.io/examples/policy/high-priority-pod.yaml

Перевірте, що статистика "Used" для квоти пріоритету "high", pods-high, змінилася, а інші дві квоти залишилися без змін.

kubectl describe quota
Name:       pods-high
Namespace:  default
Resource    Used  Hard
--------    ----  ----
cpu         500m  1k
memory      10Gi  200Gi
pods        1     10


Name:       pods-low
Namespace:  default
Resource    Used  Hard
--------    ----  ----
cpu         0     5
memory      0     10Gi
pods        0     10


Name:       pods-medium
Namespace:  default
Resource    Used  Hard
--------    ----  ----
cpu         0     10
memory      0     20Gi
pods        0     10

Стандартне обмеження споживання PriorityClass

Може бути бажаним, щоб Podʼи з певним пріоритетом, наприклад "cluster-services", дозволялися в просторі імен тоді й лише тоді, коли існує відповідний обʼєкт квоти.

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

Для цього потрібно використати прапорець kube-apiserver --admission-control-config-file, щоб передати шлях до такого конфігураційного файлу:

apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
  configuration:
    apiVersion: apiserver.config.k8s.io/v1
    kind: ResourceQuotaConfiguration
    limitedResources:
    - resource: pods
      matchScopes:
      - scopeName: PriorityClass
        operator: In
        values: ["cluster-services"]

Потім створіть обʼєкт квоти ресурсів у просторі імен kube-system:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: pods-cluster-services
spec:
  scopeSelector:
    matchExpressions:
      - operator : In
        scopeName: PriorityClass
        values: ["cluster-services"]
kubectl apply -f https://k8s.io/examples/policy/priority-class-resourcequota.yaml -n kube-system
resourcequota/pods-cluster-services created

У цьому випадку створення Podʼа буде дозволено, якщо:

  1. priorityClassName Podʼа не вказано.
  2. priorityClassName Podʼа має значення, відмінне від cluster-services.
  3. priorityClassName Podʼа встановлено на cluster-services, Pod створюється у просторі імен kube-system і пройшов перевірку квоти ресурсів.

Запит на створення Podʼа буде відхилено, якщо його priorityClassName встановлено на cluster-services і Pod створюється в просторі імен, відмінному від kube-system.

Область дії VolumeAttributesClass

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.36
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.36. It was first available in the v1.29 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate VolumeAttributesClass, Kubernetes ignores it but does not report any error.

Ця область дії відстежує лише квоту, спожиту PersistentVolumeClaims.

PersistentVolumeClaims можна створювати з певним VolumeAttributesClass і змінювати після створення. Ви можете контролювати споживання ресурсів сховища PVC на основі повʼязаних VolumeAttributesClasses, використовуючи поле scopeSelector у специфікації квоти.

PVC посилається на повʼязаний VolumeAttributesClass через такі поля:

  • spec.volumeAttributesClassName
  • status.currentVolumeAttributesClassName
  • status.modifyVolumeStatus.targetVolumeAttributesClassName

Відповідна ResourceQuota зіставляється й споживається лише тоді, коли ResourceQuota має scopeSelector, який вибирає PVC.

Коли область дії квоти задано для класу атрибутів тому за допомогою поля scopeSelector, обʼєкт квоти може відстежувати лише такі ресурси:

  • persistentvolumeclaims
  • requests.storage

Детальніше про це читайте в розділі Обмеження використання сховища.

Що далі

3 - Обмеження та резервування ID процесів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.20

Kubernetes дозволяє обмежувати кількість ідентифікаторів процесів (PID), які може використовувати Pod. Також можна зарезервувати певну кількість доступних для розподілу PID для кожного вузла для використання операційною системою та демонами (а не Podʼами).

Ідентифікатори процесів (PID) є фундаментальним ресурсом на вузлах. Досягти обмеження на кількість завдань, не досягнувши жодних інших обмежень ресурсів, дуже просто, і це може призвести до нестабільної роботи хост-машини.

Адміністраторам кластерів потрібні механізми, щоб гарантувати, що Podʼи, які працюють у кластері, не зможуть спричинити вичерпання PID, яке перешкоджає роботі демонів хоста (таких як kubelet або kube-proxy, а потенційно й середовище виконання контейнерів). Крім того, важливо обмежувати PID між Podʼами, щоб вони мали обмежений вплив на інші робочі навантаження на тому самому вузлі.

Примітка:

На деяких інсталяціях Linux операційна система стандартно встановлює низьке обмеження PID, наприклад 32768. Розгляньте можливість збільшення значення /proc/sys/kernel/pid_max.

Ви можете налаштувати kubelet для обмеження кількості PID, які може споживати конкретний Pod. Наприклад, якщо ОС хоста вашого вузла налаштовано на використання максимум 262144 PID і очікується, що на ньому розміщуватиметься менше ніж 250 Podʼів, можна надати кожному Podʼу бюджет у 1000 PID, щоб запобігти вичерпанню загальної кількості доступних PID на вузлі. Якщо адміністратор хоче застосувати overcommit для PID, як для CPU чи памʼяті, це теж можливо, але з певними додатковими ризиками. У будь-якому випадку один Pod не зможе вивести з ладу всю машину. Цей вид обмеження ресурсів допомагає запобігти впливу простих форк-бомб на роботу всього кластера.

Обмеження PID на рівні Podʼа дозволяє адміністраторам захистити один Pod від іншого, але не гарантує, що всі Podʼи, заплановані на цей хост, не зможуть вплинути на вузол загалом. Обмеження на рівні Podʼа також не захищає самі агенти вузла від вичерпання PID.

Ви також можете зарезервувати певну кількість PID для накладних витрат вузла, окремо від виділених для Podʼів. Це подібно до того, як ви можете резервувати CPU, памʼять чи інші ресурси для використання операційною системою та іншими засобами поза Podʼами та їхніми контейнерами.

Обмеження PID є важливим доповненням до запитів і обмежень обчислювальних ресурсів. Однак ви вказуєте його інакше: замість того, щоб визначати обмеження ресурсу Podʼа в .spec Podʼа, ви налаштовуєте обмеження як параметр kubelet. Обмеження PID, визначені в Podʼі, наразі не підтримуються.

Увага:

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

Обмеження PID вузла

Kubernetes дозволяє зарезервувати певну кількість ідентифікаторів процесів для системного використання. Щоб налаштувати резервування, використовуйте параметр pid=<кількість> у параметрах командного рядка kubelet --system-reserved та --kube-reserved. Вказане вами значення оголошує, що вказану кількість ідентифікаторів процесів буде зарезервовано відповідно для системи в цілому та для системних демонів Kubernetes.

Обмеження PID на рівні Podʼа

Kubernetes дозволяє обмежити кількість процесів, запущених у Podʼі. Ви вказуєте це обмеження на рівні вузла, а не налаштовуєте його як обмеження ресурсів для певного Podʼа. Кожен вузол може мати власне обмеження PID. Щоб налаштувати обмеження, ви можете вказати параметр командного рядка kubelet --pod-max-pids або встановити PodPidsLimit у конфігураційному файлі kubelet.

Виселення на основі PID

Ви можете налаштувати kubelet так, щоб він починав завершувати Pod, коли той поводиться некоректно та споживає аномальну кількість ресурсів. Ця можливість називається виселенням (eviction). Ви можете налаштувати обробку випадків нестачі ресурсів для різних сигналів виселення. Використовуйте сигнал виселення pid.available, щоб налаштувати поріг кількості PID, які використовує Pod. Ви можете встановити мʼякі та жорсткі політики виселення. Однак навіть із жорсткою політикою виселення, якщо кількість PID зростає дуже швидко, вузол усе ще може перейти в нестабільний стан, досягнувши обмеження PID вузла. Значення сигналу виселення обчислюється періодично і НЕ забезпечує дотримання обмеження.

Обмеження PID — на рівні Podʼа та на рівні вузла — встановлює жорстку межу. Щойно її буде досягнуто, робоче навантаження почне отримувати помилки під час спроб отримати новий PID. Це може призвести або не призвести до повторного планування Podʼа, залежно від того, як робоче навантаження реагує на ці помилки та як для Podʼа налаштовано проби життєздатності та готовності. Однак, якщо обмеження встановлено правильно, ви можете гарантувати, що робочі навантаження інших Podʼів та системні процеси не вичерпають PID, коли один Pod поводиться некоректно.

Що далі