Керування ресурсами Podʼів та контейнерів

Керування ресурсами Podʼів та контейнерів

Коли ви визначаєте Pod, ви можете додатково вказати, скільки кожного ресурсу потребує контейнер. Найпоширеніші ресурси, які вказують, — це CPU та памʼять (RAM); є й інші.

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

Запити та обмеження

Якщо вузол, на якому запущений Pod, має достатньо вільного ресурсу, то контейнер може (і має право) використовувати більше ресурсу, ніж зазначено в його request для цього ресурсу.

Наприклад, якщо ви встановите запит memory 256 MiB для контейнера, і цей контейнер буде в Podʼі, запланованому на вузол із 8GiB памʼяті та без інших Podʼів, то контейнер може спробувати використати більше оперативної памʼяті.

Обмеження — то вже інша справа. Обидва обмеження cpu та memory застосовуються kubeletʼом (та середовищем виконання контейнерів), і, зрештою, забезпечуються ядром. На вузлах Linux ядро Linux застосовує обмеження за допомогою cgroups. Поведінка застосування обмежень cpu та memory дещо відрізняється.

Обмеження cpu застосовуються через тротлінг CPU (CPU throttling). Коли контейнер наближається до свого обмеження cpu, ядро обмежує доступ до CPU відповідно до обмеження контейнера. Тож обмеження cpu є жорстким обмеженням, що застосовує ядро. Контейнери не можуть використовувати більше CPU, ніж зазначено в їх обмеженні cpu.

Обмеження memory застосовуються ядром через завершення процесів за нестачі памʼяті (OOM kills). Якщо контейнер використовує більше памʼяті, ніж його обмеження memory, ядро може його завершити. Однак завершення відбувається тільки тоді, коли ядро виявляє тиск на памʼять. Тому контейнер, який виділяє забагато памʼяті, може бути завершений не одразу. Це означає, що обмеження memory застосовуються реактивно. Контейнер може використовувати більше памʼяті, ніж його обмеження memory, але в такому разі його може бути завершено.

Примітка:

Існує функція MemoryQoS, яка додає тротлінг памʼяті та необовʼязкове багаторівневе резервування памʼяті на вузлах Linux за допомогою cgroup v2. Докладніше дивіться Memory QoS з cgroup v2.

Примітка:

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

Типи ресурсів

Тип ресурсу має базову одиницю вимірювання, і його можна запитувати, обмежувати або і те, й інше. Kubernetes має такі вбудовані типи ресурсів:

Тип ресурсуОписБазова одиниця
cpuОбчислювальні ресурсиcpu (ядро)
memoryОперативна памʼятьБайти
ephemeral-storageЛокальне тимчасове сховищеБайти
hugepages-<size>Великі сторінки (тільки Linux)Байти

Кластери також можуть надавати розширені ресурси (ресурси з власною назвою, які зазвичай надають втулки пристроїв).

Великі сторінки

Для робочих навантажень на Linux ви можете вказати ресурси великих сторінок (huge pages). Великі сторінки є функцією, специфічною для Linux, де ядро вузла виділяє блоки памʼяті, значно більші за стандартний розмір сторінки.

Наприклад, у системі, де розмір стандартної сторінки становить 4KiB, ви можете вказати обмеження hugepages-2Mi: 80Mi. Якщо контейнер намагається виділити понад 40 великих сторінок по 2MiB (загалом 80 MiB), це виділення завершиться невдачею.

Примітка:

Ресурси hugepages-* не можна виділяти понад наявні (overcommit). Це відрізняється від ресурсів memory та cpu.

CPU та памʼять спільно називаються обчислювальними ресурсами або ресурсами. Обчислювальні ресурси — це вимірювані величини, які можна запитувати, виділяти та використовувати. Вони відрізняються від ресурсів API. Ресурси API, такі як Podʼи та Services, є обʼєктами, які можна читати та змінювати через API-сервер Kubernetes.

Запити та обмеження ресурсів для Podʼа та контейнера

Для кожного контейнера ви можете вказати обмеження та запити ресурсів, зокрема такі:

  • spec.containers[].resources.limits.cpu
  • spec.containers[].resources.limits.memory
  • spec.containers[].resources.limits.ephemeral-storage
  • spec.containers[].resources.limits.hugepages-<size>
  • spec.containers[].resources.requests.cpu
  • spec.containers[].resources.requests.memory
  • spec.containers[].resources.requests.ephemeral-storage
  • spec.containers[].resources.requests.hugepages-<size>

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

Специфікація ресурсів на рівні Podʼів

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.34; (стандартно увімкнено)

За умови, що у вашому кластері увімкнено функціональну можливість PodLevelResources, ви можете вказувати запити та обмеження ресурсів на рівні Podʼа. На рівні Podʼа Kubernetes 1.37 підтримує запити або обмеження ресурсів лише для певних типів ресурсів: cpu та/або memory, та/або hugepages. Завдяки цій функції Kubernetes дозволяє вам декларувати загальний бюджет ресурсів для Podʼа, що є особливо корисним під час роботи з великою кількістю контейнерів, де може бути важко точно визначити індивідуальні потреби у ресурсах. Крім того, це дає змогу контейнерам у межах Podʼа ділитися один з одним ресурсами, що простоюють, покращуючи використання ресурсів.

Для Podʼа ви можете вказати обмеження та запити ресурсів для CPU і памʼяті, включивши таке:

  • spec.resources.limits.cpu
  • spec.resources.limits.memory
  • spec.resources.limits.hugepages-<size>
  • spec.resources.requests.cpu
  • spec.resources.requests.memory
  • spec.resources.requests.hugepages-<size>

Одиниці виміру ресурсів в Kubernetes

Одиниці виміру ресурсів CPU

Обмеження та запити ресурсів CPU вимірюються в одиницях cpu. У Kubernetes 1 одиниця CPU еквівалентна 1 фізичному ядру CPU або 1 віртуальному ядру, залежно від того, чи є вузол фізичним хостом або віртуальною машиною, яка працює всередині фізичної машини.

Допускаються дробові запити. Коли ви визначаєте контейнер зі значенням 0.5 у spec.containers[].resources.requests.cpu, ви запитуєте вдвічі менше часу CPU, ніж якби запросили 1.0 CPU. Для одиниць ресурсів CPU вираз кількості 0.1 еквівалентний виразу 100m, що можна прочитати як "сто millicpu". Деякі люди кажуть "сто міліядер", і це розуміється так само.

Ресурс CPU завжди вказується як абсолютна кількість ресурсу, ніколи як відносна кількість. Наприклад, 500m CPU представляє приблизно ту саму обчислювальну потужність незалежно від того, чи працює цей контейнер на одноядерній, двоядерній або 48-ядерній машині.

Примітка:

Kubernetes не дозволяє вказувати ресурси CPU з точністю вище 1m або 0.001 CPU. Щоб уникнути випадкового використання неприпустимої кількості CPU, корисно вказувати одиниці CPU, використовуючи форму milliCPU замість десяткової форми, коли використовується менше ніж 1 одиниця CPU.

Наприклад, у вас є Pod, який використовує 5m або 0.005 CPU, і ви хочете зменшити його ресурси CPU. Використовуючи десяткову форму, важко помітити, що 0.0005 CPU є неприпустимим значенням, тоді як використовуючи форму milliCPU, легше помітити, що 0.5m є неприпустимим значенням.

Одиниці виміру ресурсів памʼяті

Обмеження та запити для memory вимірюються в байтах. Ви можете вказувати памʼять як звичайне ціле число або як число з фіксованою комою, використовуючи один із таких суфіксів кількості: E, P, T, G, M, k. Ви також можете використовувати еквіваленти степенів двійки: Ei, Pi, Ti, Gi, Mi, Ki. API Kubernetes також дозволяє використовувати суфікс m (для мілібайтів: 1/1000 байта), але вказувати його немає сенсу: завжди потрібно призначати цілі числа байтів або іноді більші блоки, такі як кратні 1 гібібайту.

Ось кілька прикладів визначення обсягу памʼяті, які приблизно представляють те саме значення:

128974848, 129e6, 129M,  128974848000m, 123Mi

Звертайте увагу на регістр суфіксів. "M" означає мегабайти, тоді як "m" означає мілібайти. Якщо ви запитуєте 400m памʼяті, це запит на 0,4 байта. Той, хто вводить це, ймовірно, мав на увазі запросити 400 мебібайтів (400Mi) або 400 мегабайтів (400M).

Приклад ресурсів контейнера

У цьому Podʼі є два контейнери. Обидва контейнери визначені із запитом на 0,25 CPU і 64MiB (226 байт) памʼяті. Кожен контейнер має обмеження в 0,5 CPU та 128MiB памʼяті. Можна сказати, що Pod має запит на 0,5 CPU та 128 MiB памʼяті й обмеження в 1 CPU та 256MiB памʼяті.

---
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

Приклад ресурсів Podʼа

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.34; (стандартно увімкнено)

Цю можливість можна увімкнути за допомогою функціональної можливості PodLevelResources. Цей Pod має явний запит на 1 CPU та 100 MiB памʼяті, а також явне обмеження в 1 CPU та 200 MiB памʼяті. Контейнер pod-resources-demo-ctr-1 має явні запити та обмеження. Однак контейнер pod-resources-demo-ctr-2 просто спільно використовуватиме ресурси, доступні в межах ресурсів Podʼа, оскільки він не має явних запитів і обмежень.

apiVersion: v1
kind: Pod
metadata:
  name: pod-resources-demo
  namespace: pod-resources-example
spec:
  resources:
    limits:
      cpu: "1"
      memory: "200Mi"
    requests:
      cpu: "1"
      memory: "100Mi"
  containers:
  - name: pod-resources-demo-ctr-1
    image: nginx
    resources:
      limits:
        cpu: "0.5"
        memory: "100Mi"
      requests:
        cpu: "0.5"
        memory: "50Mi"
  - name: pod-resources-demo-ctr-2
    image: fedora
    command:
    - sleep
    - inf 

Як плануються Podʼи із запитами ресурсів

Коли ви створюєте Pod, планувальник Kubernetes вибирає вузол, на якому Pod буде запущено. Кожен вузол має максимальну місткість для кожного з типів ресурсів: кількість CPU та обсяг памʼяті, які він може надати для Podʼів. Планувальник гарантує, що для кожного типу ресурсів сума запитів ресурсів запланованих контейнерів буде менше, ніж місткість вузла. Зверніть увагу, що навіть якщо фактичне використання ресурсів CPU або памʼяті на вузлі дуже низьке, планувальник все одно відмовляється розміщувати Pod на вузлі, якщо перевірка місткості не пройшла успішно. Це захищає від нестачі ресурсів на вузлі, коли пізніше збільшується використання ресурсів, наприклад, під час щоденного піку кількості запитів.

Як Kubernetes застосовує запити на ресурси та обмеження

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

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

  • Обмеження CPU встановлює жорстку верхню межу часу CPU, який може використовувати контейнер. Протягом кожного інтервалу планування (часового відрізка) ядро Linux перевіряє, чи перевищується це обмеження; якщо так, ядро чекає, перш ніж дозволити цій cgroup продовжити виконання.
  • Запит CPU зазвичай визначає вагу. Якщо кілька різних контейнерів (cgroups) хочуть працювати на системі з конкуренцією за ресурси, робочі навантаження з більшими запитами CPU отримують більше часу CPU, ніж робочі навантаження з малими запитами.
  • Запит памʼяті в основному використовується під час планування Podʼа (Kubernetes). На вузлі, що використовує cgroups v2, середовище виконання контейнерів може використовувати запит памʼяті як підказку для встановлення memory.min та memory.low.
  • Обмеження памʼяті встановлює обмеження памʼяті для цієї контрольної групи. Якщо контейнер намагається виділити більше памʼяті, ніж це обмеження, підсистема обробки нестачі памʼяті (out-of-memory) ядра Linux активується і, зазвичай, втручається, зупиняючи один з процесів у контейнері, який намагався виділити памʼять. Якщо цей процес є PID 1 контейнера, і контейнер позначений як такий, що може перезапускатися, Kubernetes перезапускає контейнер.
  • Обмеження памʼяті для Podʼа або контейнера також може застосовуватися до сторінок у томах, що зберігаються в памʼяті, таких як emptyDir. Kubelet відстежує томи emptyDir типу tmpfs як використання памʼяті контейнера, а не як локальне тимчасове сховище. Під час використання emptyDir у памʼяті обовʼязково ознайомтеся з примітками нижче.

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

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

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

Зміна розміру ресурсів контейнера

Після створення Podʼа може знадобитися налаштувати його ресурси CPU або памʼяті відповідно до фактичних моделей використання. Kubernetes пропонує два підходи до зміни розміру ресурсів Podʼа:

Зміна розміру на місці

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

This is a stable feature in Kubernetes, and has been since version v1.35. It was first available in the v1.27 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 InPlacePodVerticalScaling, Kubernetes ignores it but does not report any error.

Ви можете змінити requests та limits CPU та памʼяті контейнерів у запущеному Podʼі без його повторного створення. Це називається вертикальним масштабуванням Podʼа на місці або зміною розміру Podʼа на місці. Щоб виконати зміну розміру на місці, оновіть специфікації ресурсів контейнера за допомогою субресурсу Podʼа /resize. Ви можете контролювати, чи потрібно перезапускати контейнер, встановивши поле resizePolicy у специфікації контейнера.

Примітка:

Зміна розміру на місці наразі застосовується до ресурсів на рівні контейнера. Щоб змінити розмір ресурсів на рівні Podʼа, див. Зміна розміру ресурсів CPU та памʼяті Podʼа.

Примітка:

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the InPlacePodVerticalScalingSchedulerPreemption feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Коли увімкнено функціональну можливість InPlacePodVerticalScalingSchedulerPreemption, відкладені запити на зміну розміру на місці можуть спонукати kube-scheduler витіснити Podʼи з нижчим пріоритетом на призначеному вузлі, щоб звільнити місце для зміни розміру. Для отримання додаткових відомостей див. Витіснення для зміни розміру Podʼа на місці.

Зміна розміру шляхом запуску Podʼів-замінників

Підхід cloud native до зміни ресурсів Podʼа полягає в оновленні шаблону Podʼа в обʼєкті робочого навантаження (такому як Deployment або StatefulSet) і дозволі контролеру робочого навантаження замінити Podʼи новими, що мають оновлені ресурси. Цей підхід працює з будь-якою версією Kubernetes і дозволяє змінювати будь-які специфікації Podʼів.

Детальніше про зміну розміру Podʼів див. Зміна розміру Podʼа. Детальні інструкції щодо зміни розміру на місці див. у розділі Зміна розміру ресурсів CPU та памʼяті, призначених контейнерам. Ви також можете використовувати Vertical Pod Autoscaler для автоматичного управління рекомендаціями щодо ресурсів Podʼа.

Моніторинг використання обчислювальних ресурсів та ресурсів памʼяті

Kubelet повідомляє про використання ресурсів Podʼа як частину status Podʼа.

Якщо у вашому кластері доступні інструменти для моніторингу, то використання ресурсів Podʼа можна отримати або безпосередньо з Metrics API, або з ваших інструментів моніторингу.

Міркування щодо томів emptyDir, що зберігаються в памʼяті

Примітка:

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the InPlacePodVerticalScalingMemoryBackedVolumes feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Коли увімкнено функціональну можливість InPlacePodVerticalScalingMemoryBackedVolumes, ви можете динамічно змінювати sizeLimit тому emptyDir, що зберігається в памʼяті (medium: Memory), на запущеному Podʼі без повторного створення Podʼа або перезапуску контейнерів. Покрокові інструкції див. у розділі Зміна розміру ресурсів CPU та памʼяті, призначених контейнерам.

Увага:

Якщо ви не вказуєте sizeLimit для тому emptyDir, цей том може використовувати памʼять до обмеження памʼяті цього Podʼа (Pod.spec.containers[].resources.limits.memory). Якщо ви не встановлюєте обмеження памʼяті, Pod не має верхньої межі на споживання памʼяті і може використовувати всю доступну памʼять на вузлі. Kubernetes планує Podʼи на основі запитів на ресурси (Pod.spec.containers[].resources.requests) і не враховує використання памʼяті понад запит під час вирішення, чи може інший Pod розміститися на даному вузлі. Це може призвести до відмови в обслуговуванні та змусити ОС виконати обробку нестачі памʼяті (OOM). Можна створити будь-яку кількість emptyDir, які потенційно можуть використовувати всю доступну памʼять на вузлі, що робить OOM більш ймовірним.

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

  • Файли, збережені в томі, що зберігається в памʼяті, майже повністю управляються застосунком користувача. На відміну від використання памʼяті як робочої області процесу, ви не можете покладатися на такі речі, як збір сміття на рівні мови програмування.
  • Мета запису файлів в том полягає в збереженні даних або їх передачі між застосунками. Ні Kubernetes, ні ОС не можуть автоматично видаляти файли з тому, тому памʼять, яку займають ці файли, не може бути звільнена, коли система або Pod відчувають тиск на памʼять.
  • Томи emptyDir, що зберігаються в памʼяті, корисні через свою продуктивність, але памʼять зазвичай набагато менша за розміром і набагато дорожча за інші носії, такі як диски або SSD. Використання великої кількості памʼяті для томів emptyDir може вплинути на нормальну роботу вашого Podʼа або всього вузла, тому їх слід використовувати обережно.

Якщо ви адмініструєте кластер або простір імен, ви також можете встановити ResourceQuota, що обмежує використання памʼяті; також може бути корисно визначити LimitRange для додаткового забезпечення обмежень. Якщо ви вказуєте spec.containers[].resources.limits.memory для кожного Podʼа, то максимальний розмір тому emptyDir буде дорівнювати обмеженню памʼяті Podʼа.

Як альтернатива, адміністратор кластера може забезпечити дотримання обмежень на розмір томів emptyDir в нових Podʼах, використовуючи механізм політики, такий як ValidatingAdmissionPolicy.

Локальне тимчасове сховище

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

Моніторинг ресурсів для локального тимчасового сховища

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

Kubernetes відстежує обсяг тимчасового сховища, яке використовує Pod, із таких джерел:

  • Запис у шар контейнера, доступний для запису (rootfs), в образи контейнерів або і туди, й туди.
  • Запис у локальні томи emptyDir.
  • Власні логи Podʼа (зазвичай зберігаються в /var/log/pods).
  • Системні файли, керовані Kubernetes, які відображаються в Pod, наприклад /etc/hosts.

Розширені ресурси

Розширені ресурси — це повністю кваліфіковані назви ресурсів поза доменом kubernetes.io. Вони дозволяють операторам кластера оголошувати, а користувачам використовувати ресурси, які не вбудовані в Kubernetes.

Щоб скористатися розширеними ресурсами, потрібно виконати два кроки. По-перше, оператор кластера повинен оголосити розширений ресурс. По-друге, користувачі повинні запитати розширений ресурс у Podʼах.

Керування розширеними ресурсами

Розширені ресурси на рівні вузла

Розширені ресурси на рівні вузла повʼязані з вузлами.

Ресурси, керовані втулками пристроїв

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

Інші ресурси

Щоб оголосити новий розширений ресурс на рівні вузла, оператор кластера може надіслати HTTP-запит типу PATCH до API-сервера, щоб вказати доступну кількість в полі status.capacity для вузла у кластері. Після цієї операції поле status.capacity вузла буде містити новий ресурс. Kubelet автоматично й асинхронно оновлює поле status.allocatable, додаючи новий ресурс.

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

Приклад:

Нижче наведено приклад використання curl для формування HTTP-запиту, який оголошує пʼять ресурсів "example.com/foo" на вузлі k8s-node-1, master якого — k8s-master.

curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \
http://k8s-master:8080/api/v1/nodes/k8s-node-1/status

Примітка:

У наведеному вище запиті ~1 — це кодування символу / у шляху патча. Значення шляху операції у JSON-Patch інтерпретується як JSON-Pointer. Докладніше дивіться IETF RFC 6901, розділ 3.

Розширені ресурси на рівні кластера

Розширені ресурси на рівні кластера не повʼязані з вузлами. Зазвичай ними керують розширювачі планувальника, які відповідають за споживання ресурсів і квоту ресурсів.

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

Приклад:

Ця конфігурація для політики планувальника вказує на те, що розширений ресурс на рівні кластера "example.com/foo" обробляється розширювачем планувальника.

  • Планувальник відправляє Pod до розширювача планувальника тільки у випадку, якщо Pod запитує "example.com/foo".
  • Поле ignoredByScheduler вказує, що планувальник не перевіряє ресурс "example.com/foo" в своєму предикаті PodFitsResources.
{
  "kind": "Policy",
  "apiVersion": "v1",
  "extenders": [
    {
      "urlPrefix":"<extender-endpoint>",
      "bindVerb": "bind",
      "managedResources": [
        {
          "name": "example.com/foo",
          "ignoredByScheduler": true
        }
      ]
    }
  ]
}

Розподілення розширених ресурсів за допомогою DRA

Розподілення розширених ресурсів за допомогою DRA дозволяє адміністраторам кластерів вказувати extendedResourceName у DeviceClass, після чого пристрої, що відповідають DeviceClass, можуть бути запитані з розширених запитів ресурсів Podʼа. Читайте більше про Розподілення розширених ресурсів за допомогою DRA.

Використання розширених ресурсів

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

API-сервер обмежує кількість розширених ресурсів цілими числами. Приклади дійсних значень: 3, 3000m та 3Ki. Приклади недійсних значень: 0.5 та 1500m (тому що 1500m буде давати в результаті 1.5).

Примітка:

Розширені ресурси замінюють Opaque Integer Resources. Користувачі можуть використовувати будь-який префікс доменного імені, крім kubernetes.io, який зарезервований.

Щоб використовувати розширений ресурс у Podʼі, включіть назву ресурсу як ключ у мапу spec.containers[].resources.limits у специфікації контейнера.

Примітка:

Розширені ресурси не можна виділяти понад наявні (overcommit), тому запит і обмеження мають бути рівними, якщо обидва присутні у специфікації контейнера.

Pod планується лише тоді, коли задоволено всі запити ресурсів, включаючи CPU, памʼять та будь-які розширені ресурси. Pod залишається у стані PENDING, доки запит ресурсу неможливо задовольнити.

Приклад:

Нижче наведено Pod, який запитує 2 CPU та 1 "example.com/foo" (розширений ресурс).

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: myimage
    resources:
      requests:
        cpu: 2
        example.com/foo: 1
      limits:
        example.com/foo: 1

Обмеження PID

Обмеження ідентифікаторів процесів (PID) дозволяють налаштувати kubelet для обмеження кількості PID, яку може використовувати певний Pod. Див. Обмеження PID для отримання інформації.

Усунення несправностей

Мої Podʼи знаходяться в стані очікування з повідомленням події FailedScheduling

Якщо планувальник не може знайти жодного вузла, де може розміститися Pod, Pod залишається незапланованим, поки не буде знайдено місце. Кожного разу, коли планувальник не може знайти місце для Podʼа, створюється подія. Ви можете використовувати kubectl для перегляду подій Podʼа; наприклад:

kubectl describe pod frontend | grep -A 9999999999 Events
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  23s   default-scheduler  0/42 nodes available: insufficient cpu

У наведеному вище прикладі Pod із назвою "frontend" не вдалося запланувати через нестачу ресурсу CPU на будь-якому вузлі. Схожі повідомлення про помилку також можуть вказувати на невдачу через недостатню памʼять (PodExceedsFreeMemory). Загалом, якщо Pod знаходиться в стані очікування з таким типом повідомлення, є кілька речей, які варто спробувати:

  • Додайте більше вузлів у кластер.
  • Завершіть непотрібні Podʼи, щоб звільнити місце для очікуваних Podʼів.
  • Перевірте, що Pod не є більшим, ніж усі вузли. Наприклад, якщо всі вузли мають місткість cpu: 1, то Pod з запитом cpu: 1.1 ніколи не буде запланованим.
  • Перевірте наявність taints на вузлах. Якщо більшість ваших вузлів мають taint, і новий Pod не толерує цей taint, планувальник розглядає розміщення лише на решті вузлів, які не мають цього taint.

Ви можете перевірити місткості вузлів та виділені обсяги ресурсів за допомогою команди kubectl describe nodes. Наприклад:

kubectl describe nodes e2e-test-node-pool-4lw4
Name:            e2e-test-node-pool-4lw4
[ ... lines removed for clarity ...]
Capacity:
 cpu:                               2
 memory:                            7679792Ki
 pods:                              110
Allocatable:
 cpu:                               1800m
 memory:                            7474992Ki
 pods:                              110
[ ... lines removed for clarity ...]
Non-terminated Pods:        (5 in total)
  Namespace    Name                                  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------    ----                                  ------------  ----------  ---------------  -------------
  kube-system  fluentd-gcp-v1.38-28bv1               100m (5%)     0 (0%)      200Mi (2%)       200Mi (2%)
  kube-system  coredns-3297075139-61lj3              260m (13%)    0 (0%)      100Mi (1%)       170Mi (2%)
  kube-system  kube-proxy-e2e-test-...               100m (5%)     0 (0%)      0 (0%)           0 (0%)
  kube-system  monitoring-influxdb-grafana-v4-z1m12  200m (10%)    200m (10%)  600Mi (8%)       600Mi (8%)
  kube-system  node-problem-detector-v0.1-fj7m3      20m (1%)      200m (10%)  20Mi (0%)        100Mi (1%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests    CPU Limits    Memory Requests    Memory Limits
  ------------    ----------    ---------------    -------------
  680m (34%)      400m (20%)    920Mi (11%)        1070Mi (13%)

У наведеному вище виводі ви можете побачити, що якщо Pod запитує більше 1,120 CPU або більше 6,23Gi памʼяті, то цей Pod не поміститься на вузлі.

Подивившись на розділ "Pods", ви можете побачити, які Podʼи займають місце на вузлі.

Обсяг ресурсів, доступних для Podʼів, менший за місткість вузла, оскільки системні демони використовують частину доступних ресурсів. В API Kubernetes кожен вузол має поле .status.allocatable (див. NodeStatus для деталей).

Поле .status.allocatable описує обсяг ресурсів, доступних для Podʼів на цьому вузлі (наприклад: 15 віртуальних CPU та 7538 MiB памʼяті). Для отримання додаткової інформації про доступні для розподілу (allocatable) ресурси вузла в Kubernetes дивіться Резервування обчислювальних ресурсів для системних демонів.

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

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

Робота мого контейнера завершується примусово

Робота вашого контейнера може бути завершена через нестачу ресурсів. Щоб перевірити, чи контейнер був завершений через досягнення обмеження ресурсів, викличте kubectl describe pod для потрібного Podʼа:

kubectl describe pod simmemleak-hra99

Вивід буде схожий на:

Name:                           simmemleak-hra99
Namespace:                      default
Image(s):                       saadali/simmemleak
Node:                           kubernetes-node-tf0f/10.240.216.66
Labels:                         name=simmemleak
Status:                         Running
Reason:
Message:
IP:                             10.244.2.75
Containers:
  simmemleak:
    Image:  saadali/simmemleak:latest
    Limits:
      cpu:          100m
      memory:       50Mi
    State:          Running
      Started:      Tue, 07 Jul 2019 12:54:41 -0700
    Last State:     Terminated
      Reason:       OOMKilled
      Exit Code:    137
      Started:      Fri, 07 Jul 2019 12:54:30 -0700
      Finished:     Fri, 07 Jul 2019 12:54:33 -0700
    Ready:          False
    Restart Count:  5
Conditions:
  Type      Status
  Ready     False
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  42s   default-scheduler  Successfully assigned simmemleak-hra99 to kubernetes-node-tf0f
  Normal  Pulled     41s   kubelet            Container image "saadali/simmemleak:latest" already present on machine
  Normal  Created    41s   kubelet            Created container simmemleak
  Normal  Started    40s   kubelet            Started container simmemleak
  Normal  Killing    32s   kubelet            Killing container with id ead3fb35-5cf5-44ed-9ae1-488115be66c6: Need to kill Pod

У наведеному вище прикладі Restart Count: 5 вказує на те, що контейнер simmemleak у Podʼі був завершений та перезапущений пʼять разів (до цього моменту). Причина OOMKilled показує, що контейнер намагався використовувати більше памʼяті, ніж встановлене йому обмеження.

Наступним кроком може бути перевірка коду застосунку на витік памʼяті. Якщо ви виявите, що застосунок працює так, як очікувалося, розгляньте встановлення вищого обмеження памʼяті (і, можливо, запиту) для цього контейнера.

Що далі