Інформація в цьому документі може бути застарілою
Дата оновлення цього документа старіша за оригінал, можливо інформація в ньому застаріла. Радимо ознайомитись з оригіналом англійською для отримання найсвіжіших відомостей: Resource Management for Pods and Containers
Керування ресурсами Podʼів та Контейнерів
Коли ви визначаєте Pod, ви можете додатково вказати, скільки кожного ресурсу потребує контейнер. Найпоширеніші ресурси для вказання — це процесор та памʼять (RAM); є й інші.
Коли ви вказуєте запит ресурсів для контейнерів в Podʼі, kube-scheduler використовує цю інформацію для вибору вузла, на який розмістити Pod. Коли ви вказуєте обмеження ресурсів для контейнера, kubelet забезпечує виконання цих обмежень, щоб запущений контейнер не міг використовувати більше цього ресурсу, ніж обмеження, яке ви встановили. Крім того, kubelet резервує принаймні ту кількість запитуваних ресурсів спеціально для використання цим контейнером.
Запити та обмеження
Якщо вузол, на якому запущений Pod, має достатньо вільного ресурсу, то можливе (і дозволено), щоб контейнер використовував більше ресурсу, ніж його запит
для цього ресурсу вказує. Однак контейнеру не дозволяється використовувати більше, ніж його обмеження
ресурсу.
Наприклад, якщо ви встановите запит memory
256 МіБ для контейнера, і цей контейнер буде в Pod, запланованому на вузол з 8 ГіБ памʼяті та без інших Pod, то контейнер може спробувати використати більше оперативної памʼяті.
Якщо ви встановите обмеження memory
4 ГіБ для цього контейнера, kubelet (і
середовище виконання контейнерів) забезпечують виконання обмеження. Середовище запобігає контейнеру використовувати більше, ніж налаштоване обмеження ресурсів. Наприклад: коли процес в контейнері намагається використати більше дозволеної кількості памʼяті, ядро системи припиняє виконання процесу, що спробував здійснити виділення, з помилкою нестача памʼяті (out of memory, OOM).
Обмеження можуть бути виконані реактивно (система втручається після виявлення порушення) або за допомогою заборони (система завжди запобігає контейнеру перевищувати обмеження). Різні середовища можуть мати різні способи реалізації тих самих обмежень.
Примітка:
Якщо ви вказали обмеження для ресурсу, але не вказали жодного запиту, і жодний механізм часу входу не застосував стандартного значення запиту для цього ресурсу, то Kubernetes скопіює обмеження яке ви вказали та використовує його як запитане значення для ресурсу.Типи ресурсів
ЦП та памʼять кожен є типом ресурсу. Тип ресурсу має базові одиниці вимірювання. ЦП представляє обчислювальні ресурси та вказується в одиницях ЦП Kubernetes. Памʼять вказується в байтах. Для робочих завдань на Linux ви можете вказати huge page ресурсів. Huge page є функцією, специфічною для Linux, де ядро вузла виділяє блоки памʼяті, що значно більше, ніж розмір стандартної сторінки.
Наприклад, у системі, де розмір стандартної сторінки становить 4 КіБ, ви можете вказати обмеження hugepages-2Mi: 80Mi
. Якщо контейнер намагається виділити більше ніж 40 2МіБ великих сторінок (всього 80 МіБ), то це виділення не вдасться.
Примітка:
Ви не можете перевищити ресурсиhugepages-*
. Це відрізняється від ресурсів memory
та cpu
.ЦП та памʼять спільно називаються обчислювальними ресурсами або ресурсами. Обчислювальні ресурси – це вимірювальні величини, які можна запитувати, виділяти та використовувати. Вони відрізняються від ресурсів API. Ресурси API, такі як Pod та Service, є обʼєктами, які можна читати та змінювати за допомогою сервера API Kubernetes.
Запити та обмеження ресурсів для Podʼа та контейнера
Для кожного контейнера ви можете вказати обмеження та запити ресурсів, включаючи наступне:
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.limits.hugepages-<size>
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
spec.containers[].resources.requests.hugepages-<size>
Хоча ви можете вказувати запити та обмеження тільки для окремих контейнерів, також корисно думати про загальні запити та обмеження ресурсів для Podʼа. Для певного ресурсу запит/обмеження ресурсів Podʼа — це сума запитів/обмежень цього типу для кожного контейнера в Podʼі.
Одиниці виміру ресурсів в Kubernetes
Одиниці виміру ресурсів процесора
Обмеження та запити ресурсів процесора вимірюються в одиницях cpu. У Kubernetes 1 одиниця CPU еквівалентна 1 фізичному ядру процесора або 1 віртуальному ядру, залежно від того, чи є вузол фізичним хостом або віртуальною машиною, яка працює всередині фізичної машини.
Допускаються дробові запити. Коли ви визначаєте контейнер з spec.containers[].resources.requests.cpu
встановленою на 0.5
, ви просите вдвічі менше часу CPU порівняно з тим, якщо ви запросили 1.0
CPU. Для одиниць ресурсів процесора вираз кількості 0.1
еквівалентний виразу 100m
, що може бути прочитано як "сто міліпроцесорів". Деякі люди кажуть "сто міліядер", і це розуміється так само.
Ресурс CPU завжди вказується як абсолютна кількість ресурсу, ніколи як відносна кількість. Наприклад, 500m
CPU представляє приблизно ту саму обчислювальну потужність, не важливо чи цей контейнер працює на одноядерній, двоядерній або 48-ядерній машині.
Примітка:
Kubernetes не дозволяє вказувати ресурси CPU з точністю вище 1m
або 0.001
CPU. Щоб уникнути випадкового використання неприпустимої кількості CPU, корисно вказувати одиниці CPU, використовуючи форму міліCPU замість десяткової форми при використанні менше ніж 1 одиниця CPU.
Наприклад, у вас є Pod, який використовує 5m
або 0.005
CPU, і ви хочете зменшити його ресурси CPU. Використовуючи десяткову форму, важко помітити, що 0.0005
CPU є неприпустимим значенням, тоді як використовуючи форму міліCPU, легше помітити, що 0.5m
є неприпустимим значенням.
Одиниці виміру ресурсів памʼяті
Обмеження та запити для memory
вимірюються в байтах. Ви можете вказувати памʼять як звичайне ціле число або як число з плаваючою комою, використовуючи один з наступних суфіксів кількості: E, P, T, G, M, k. Ви також можете використовувати еквіваленти степенів двійки: Ei, Pi, Ti, Gi, Mi, Ki. Наприклад, наступне приблизно представляє те ж саме значення:
128974848, 129e6, 129M, 128974848000m, 123Mi
Звертайте увагу на регістр суфіксів. Якщо ви запитуєте 400m
памʼяті, це запит на 0.4 байта. Той, хто вводить це, ймовірно, мав на увазі запросити 400 мебібайтів (400Mi
)
або 400 мегабайтів (400M
).
Приклад ресурсів контейнера
У наступному Podʼі є два контейнери. Обидва контейнери визначені з запитом на 0,25 CPU і 64 МіБ (226 байт) памʼяті. Кожен контейнер має обмеження в 0,5 CPU та 128 МіБ памʼяті. Можна сказати, що у Podʼі є запит на 0,5 CPU та 128 МіБ памʼяті, та обмеження в 1 CPU та 256 МіБ памʼяті.
---
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ʼи з запитаними ресурсами плануються
Коли ви створюєте Pod, планувальник Kubernetes вибирає вузол, на якому Pod буде запущено. Кожен вузол має максимальну місткість для кожного з типів ресурсів: кількість процесорних ядер (CPU) та обсяг памʼяті, які він може надати для Podʼів. Планувальник забезпечує, що для кожного типу ресурсів сума запитів ресурсів запланованих контейнерів буде менше, ніж місткість вузла. Зверніть увагу, що навіть якщо фактичне використання ресурсів CPU або памʼяті на вузлі дуже низьке, планувальник все одно відмовляється розміщувати Pod на вузлі, якщо перевірка місткості не пройшла успішно. Це захищає від нестачі ресурсів на вузлі, коли пізніше збільшується використання ресурсів, наприклад, під час денного піка запитів.
Як Kubernetes застосовує запити на ресурси та обмеження
Коли kubelet запускає контейнер як частину Podʼа, він передає запити та обмеження для памʼяті та CPU цього контейнера до середовища виконання контейнера.
У Linux середовище виконання контейнера зазвичай налаштовує контрольні групи (cgroups) ядра, які застосовують і виконують обмеження, що ви визначили.
- Обмеження CPU встановлює жорсткий ліміт на те, скільки часу процесора контейнер може використовувати. Протягом кожного інтервалу планування (часового відрізка) ядро Linux перевіряє, чи перевищується це обмеження; якщо так, ядро чекає, перш ніж дозволити цій групі продовжити виконання.
- Запит CPU зазвичай визначає вагу. Якщо кілька різних контейнерів (cgroups) хочуть працювати на конкуруючій системі, робочі навантаження з більшими запитами CPU отримують більше часу CPU, ніж робочі навантаження з малими запитами.
- Запит памʼяті в основному використовується під час планування Podʼа (Kubernetes). На вузлі, що використовує cgroups v2, середовище виконання контейнера може використовувати запит памʼяті як підказку для встановлення
memory.min
таmemory.low
. - Обмеження памʼяті встановлює обмеження памʼяті для цієї контрольної групи. Якщо контейнер намагається виділити більше памʼяті, ніж це обмеження, підсистема управління памʼяттю Linux активується і, зазвичай, втручається, зупиняючи один з процесів у контейнері, який намагався виділити памʼять. Якщо цей процес є PID 1 контейнера, і контейнер позначений як можливий до перезапуску, Kubernetes перезапускає контейнер.
- Обмеження памʼяті для Podʼа або контейнера також може застосовуватися до сторінок в памʼяті, резервованих томами, як от
emptyDir
. Kubelet відстежуєtmpfs
томиemptyDir
як використання памʼяті контейнера, а не як локальне ефемерне сховище. При використанніemptyDir
в памʼяті, обовʼязково ознайомтеся з примітками нижче.
Якщо контейнер перевищує свій запит на памʼять і вузол, на якому він працює, стикається з браком памʼяті взагалі, ймовірно, що Pod, якому належить цей контейнер, буде виселено.
Контейнер може або не може дозволяти перевищувати своє обмеження CPU протягом тривалого часу. Однак середовища виконання контейнерів не припиняють роботу Podʼа або контейнерів через надмірне використання CPU.
Щоб визначити, чи не можна розмістити контейнер або, чи його роботи примусово припиняється через обмеження ресурсів, див. Налагодження.
Моніторинг використання обчислювальних ресурсів та ресурсів памʼяті
kubelet повідомляє про використання ресурсів Podʼа як частину статусу Podʼа.
Якщо в вашому кластері доступні інструменти для моніторингу, то використання ресурсів Podʼа можна отримати або безпосередньо з Metrics API, або з вашого інструменту моніторингу.
Міркування щодо томів emptyDir
, що зберігаються в памʼяті
Увага:
Якщо ви не вказуєте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ʼах, використовуючи механізм політики, такий як ValidationAdmissionPolicy.
Локальне тимчасове сховище
Kubernetes v1.25 [stable]
На вузлах існує локальне тимчасове сховище, яке підтримується локально приєднаними пристроями для запису або іноді ОЗУ. "Тимчасове" означає, що не існує гарантії тривалості.
Podʼи використовують тимчасове локальне сховище для тимчасового простору, кешування та для логів. kubelet може надавати тимчасовий простір Podʼам, використовуючи локальне тимчасове сховище для підключення emptyDir
тому до контейнерів.
Крім того, kubelet використовує цей тип сховища для збереження логів контейнерів на рівні вузла, образів контейнерів та шарів з можливістю запису запущених контейнерів.
Увага:
Якщо вузол виходить з ладу, дані у його тимчасовому сховищі можуть бути втрачені. Ваші програми не можуть розраховувати на будь-які SLA щодо продуктивності (наприклад, IOPS диска) з локального тимчасового сховища.Примітка:
Щоб квота ресурсів працювала на тимчасовому сховищі, потрібно зробити дві речі:
- Адміністратор встановлює обмеження ресурсів для тимчасового сховища в просторі імен.
- Користувач повинен вказати обмеження для ресурсу тимчасового сховища в специфікації Podʼа.
Якщо користувач не вказує обмеження ресурсу тимчасового сховища в специфікації Podʼа, то обмеження ресурсу не накладається на тимчасове сховище.
Kubernetes дозволяє відстежувати, резервувати та обмежувати обсяг тимчасового локального сховища, яке може використовувати Pod.
Налаштування для локального тимчасового сховища
Kubernetes підтримує два способи налаштування локального тимчасового сховища на вузлі:
У цій конфігурації ви розміщуєте всі різновиди тимчасових локальних даних (таких як тимчасові томи emptyDir
, шари з можливістю запису, образи контейнерів, логи) в одній файловій системі. Найефективніший спосіб налаштування kubelet — призначити цю файлову систему для даних Kubernetes (kubelet).
Kubelet також записує логи контейнерів на рівні вузла та обробляє їх аналогічно до тимчасового локального сховища.
Kubelet записує логи в файли всередині свого налаштованого каталогу журналів (/var/log
типово); та має базовий каталог для інших локально збережених даних (/var/lib/kubelet
типово).
Зазвичай як /var/lib/kubelet
, так і /var/log
знаходяться на кореневій файловій системі системи, і kubelet розроблений з урахуванням цієї структури.
Ваш вузол може мати стільки інших файлових систем, не використовуваних для Kubernetes, скільки вам потрібно.
Ви маєте файлову систему на вузлі, яку використовуєте для тимчасових даних, які надходять від запущених Podʼів: логи та томи emptyDir
. Ви можете використовувати цю файлову систему для інших даних (наприклад: системні логи, не повʼязані з Kubernetes); це може навіть бути кореневою файловою системою.
Kubelet також записує логи контейнерів на рівні вузла у першу файлову систему та обробляє їх аналогічно до тимчасового локального сховища.
Ви також використовуєте окрему файлову систему, яка базується на іншому логічному пристрої зберігання. У цій конфігурації каталог, де ви вказуєте kubelet розміщувати шари образів контейнерів та шари з можливістю запису, знаходиться на цій другій файловій системі.
Перша файлова система не містить жодних шарів образів або шарів з можливістью запису.
Ваш вузол може мати стільки інших файлових систем, не використовуваних для Kubernetes, скільки вам потрібно.
Kubelet може вимірювати, скільки локального сховища він використовує. Він робить це, якщо ви налаштували вузол за однією з підтримуваних конфігурацій для локального тимчасового сховища.
Якщо у вас інша конфігурація, то kubelet не застосовує обмеження ресурсів для тимчасового локального сховища.
Примітка:
Kubelet відстежує тимчасові томиtmpfs
як використання памʼяті контейнера, а не як локальне тимчасове сховище.Примітка:
Kubelet відстежує тільки кореневу файлову систему для тимчасового сховища. Розкладки ОС, які монтували окремий диск у/var/lib/kubelet
або /var/lib/containers
, не будуть правильно відображати тимчасове сховище.Налаштування запитів та обмежень для локального тимчасового сховища
Ви можете вказати ephemeral-storage
для керування локальним тимчасовим сховищем. Кожен контейнер Podʼа може вказати одне або обидва з наступного:
spec.containers[].resources.limits.ephemeral-storage
spec.containers[].resources.requests.ephemeral-storage
Обмеження та запити для ephemeral-storage
вимірюються в кількості байтів. Ви можете виражати сховище як звичайне ціле число або як число з плаваючою точкою, використовуючи один з наступних суфіксів: E, P, T, G, M, k. Ви також можете використовувати еквіваленти степенів двійки: Ei, Pi, Ti, Gi, Mi, Ki. Наприклад, наступні кількості приблизно представляють одне й те ж значення:
128974848
129e6
129M
123Mi
Звертайте увагу на регістр суфіксів. Якщо ви запитуєте 400m
тимчасового сховища, це запит на 0,4 байти. Хтось, хто вводить це, мабуть, мав на меті запросити 400 мебібайтів (400Mi
) або 400 мегабайтів (400M
).
У наступному прикладі Pod має два контейнери. Кожен контейнер має запит на 2 гігабайти локального тимчасового сховища. Кожен контейнер має обмеження на 4 гігабайти локального тимчасового сховища. Отже, у Podʼа запит на 4 гігабайти локального тимчасового сховища, і обмеження на 8 ГіБ локального тимчасового сховища. З цього обмеження 500 Мі може бути витрачено на тимчасовий том emptyDir
.
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: app
image: images.my-company.example/app:v4
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "4Gi"
volumeMounts:
- name: ephemeral
mountPath: "/tmp"
- name: log-aggregator
image: images.my-company.example/log-aggregator:v6
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "4Gi"
volumeMounts:
- name: ephemeral
mountPath: "/tmp"
volumes:
- name: ephemeral
emptyDir:
sizeLimit: 500Mi
Як розміщуються Podʼи з запитами на локальне тимчасове сховище
При створенні Podʼа планувальник Kubernetes вибирає вузол, на якому буде виконуватися Под. Кожен вузол має максимальну кількість локального тимчасового сховища, яке він може надати для Podʼів. Для отримання додаткової інформації дивіться розділ Виділення ресурсів вузла.
Планувальник забезпечує те, щоб сума запитів ресурсів запланованих контейнерів була меншою за потужність вузла.
Керування використанням локального тимчасового сховища
Якщо kubelet керує локальним тимчасовим сховищем як ресурсом, тоді kubelet вимірює використання сховища у таких областях:
emptyDir
томи, за винятком tmpfsemptyDir
томів- каталоги, де зберігаються логи на рівні вузла
- шари контейнера з можливістю запису
Якщо Pod використовує більше тимчасового сховища, ніж дозволяється, kubelet встановлює сигнал виселення, який викликає виселення Podʼа.
Для ізоляції на рівні контейнера, якщо записуваний шар контейнера та використання логу перевищують обмеження щодо сховища, то kubelet позначає Pod для виселення.
Для ізоляції на рівні Podʼа kubelet визначає загальне обмеження сховища для Podʼа, підсумовуючи обмеження для контейнерів у цьому Podʼі. У цьому випадку, якщо сума використання локального тимчасового сховища з усіх контейнерів та emptyDir
томів Podʼа перевищує загальне обмеження сховища для Podʼа, то kubelet також позначає Pod для виселення.
Увага:
Якщо kubelet не вимірює локальне тимчасове сховище, тоді Pod, який перевищує своє обмеження локального сховища, не буде виселено за порушення обмежень ресурсів локального сховища.
Проте, якщо простір файлової системи для записуваних шарів контейнерів, журналів на рівні вузла або emptyDir
томів стає малим, вузол встановлює для себе позначку недостатності місця у локальному сховищі, і ця позначка викликає виселення будь-яких Podʼів, які не толерують цю позначку. Дивіться підтримані конфігурації для локального тимчасового сховища.
kubelet підтримує різні способи вимірювання використання сховища Podʼа:
kubelet виконує регулярні заплановані перевірки, які сканують кожний emptyDir
том, каталог логів контейнера та записуваний шар контейнера.
Під час сканування вимірюється обсяг використаного простору.
Примітка:
У цьому режимі kubelet не відстежує відкриті дескриптори файлів для видалених файлів.
Якщо ви (або контейнер) створюєте файл всередині emptyDir
тому, потім щось відкриває цей файл, і ви видаляєте файл, поки він ще відкритий, то inode для видаленого файлу залишається до тих пір, поки ви не закриєте цей файл, але kubelet не класифікує цей простір як використаний.
Kubernetes v1.31 [beta]
(стандартно увімкнено: false)Квоти проєктів — це функціональність на рівні операційної системи для управління використанням сховища у файлових системах. У Kubernetes ви можете ввімкнути квоти проєктів для моніторингу використання сховища. Переконайтеся, що файлова система, яка підтримує emptyDir
томи, на вузлі надає підтримку квот проєктів. Наприклад, XFS та ext4fs пропонують квоти проєктів.
Примітка:
Квоти проєктів дозволяють вам відслідковувати використання сховища, вони не встановлюють обмеження.Kubernetes використовує ідентифікатори проєктів, що починаються з 1048576
. Використані ідентифікатори зареєстровані в /etc/projects
та /etc/projid
. Якщо ідентифікатори проєктів у цьому діапазоні використовуються для інших цілей у системі, ці ідентифікатори проєктів повинні бути зареєстровані в /etc/projects
та /etc/projid
, щоб Kubernetes не використовував їх.
Квоти є швидкими та точними, ніж сканування каталогів. Коли каталог призначений для проєкту, всі файли, створені в каталозі, створюються в цьому проєкті, і ядро просто відстежує, скільки блоків використовується файлами в цьому проєкті. Якщо файл створений і видалений, але має відкритий файловий дескриптор, він продовжує споживати місце. Відстеження квот точно відображає цей простір, тоді як сканування каталогів не враховує місце, використане видаленими файлами.
Щоб використовувати квоти для відстеження використання ресурсів Podʼів, Pod повинен знаходитися в просторі імен користувача. У просторах імен користувачів ядро обмежує зміни ідентифікаторів проєктів у файловій системі, забезпечуючи надійність зберігання метрик, розрахованих за квотами.
Якщо ви хочете використовувати квоти проєктів, вам потрібно:
Увімкнути функціональну можливість
LocalStorageCapacityIsolationFSQuotaMonitoring=true
використовуючи полеfeatureGates
в конфігурації kubelet.Переконайтеся, що функціональну можливість
UserNamespacesSupport
увімкнено, і що ядро, реалізація CRI та середовище виконання OCI підтримують простори імен користувачів.Переконайтеся, що коренева файлова система (або додаткова файлова система запуску) має увімкнену підтримку квот проєктів. Всі файлові системи XFS підтримують квоти проєктів. Для файлових систем ext4fs вам потрібно увімкнути функцію відстеження квот проєктів допоки файлова система не змонтована.
# Для ext4, з /dev/block-device, не змонтовано sudo tune2fs -O project -Q prjquota /dev/block-device
Переконайтеся, що коренева файлова система (або додаткова файлова система запуску) змонтована з увімкненими квотами проєктів. Для XFS та ext4fs параметр монтування має назву
prjquota
.
Якщо ви не хочете використовувати квоти проєкту, вам слід зробити так:
- Вимкнути функціональну можливість
LocalStorageCapacityIsolationFSQuotaMonitoring
використовуючи полеfeatureGates
в kubelet configuration.
Розширені ресурси
Розширені ресурси — це повністю кваліфіковані імена ресурсів поза доменом kubernetes.io
. Вони дозволяють операторам кластера оголошувати, а користувачам використовувати ресурси, які не вбудовані в Kubernetes.
Щоб скористатися Розширеними ресурсами, потрібно виконати два кроки. По-перше, оператор кластера повинен оголошувати Розширений Ресурс. По-друге, користувачі повинні запитувати Розширений Ресурс в Podʼах.
Керування розширеними ресурсами
Ресурси на рівні вузла
Ресурси на рівні вузла повʼязані з вузлами.
Керовані ресурси втулків пристроїв
Дивіться Втулок пристроїв щодо того, як оголошувати ресурси, що керуються втулком пристроїв на кожному вузлі.
Інші ресурси
Щоб оголошувати новий розширений ресурс на рівні вузла, оператор кластера може надіслати HTTP-запит типу PATCH
до API-сервера, щоб вказати доступну кількість в полі status.capacity
для вузла у кластері. Після цієї операції поле status.capacity
вузла буде містити новий ресурс. Поле status.allocatable
оновлюється автоматично з новим ресурсом асинхронно за допомогою kubelet.
Оскільки планувальник використовує значення status.allocatable
вузла при оцінці придатності Podʼа, планувальник враховує нове значення лише після цього асинхронного оновлення. Між моментом зміни потужності вузла новим ресурсом і часом, коли перший Pod, який запитує ресурс, може бути запланований на цьому вузлі, може відбуватися коротка затримка.
Приклад:
Нижче наведено приклад використання curl
для формування HTTP-запиту, який оголошує пʼять ресурсів "example.com/foo" на вузлі k8s-node-1
, майстер якого 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-вказівник. Для отримання докладнішої інформації дивіться 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
}
]
}
]
}
Використання розширених ресурсів
Користувачі можуть використовувати розширені ресурси у специфікаціях Podʼа, подібно до CPU та памʼяті. Планувальник відповідає за облік ресурсів, щоб одночасно не виділялося більше доступної кількості ресурсів для Podʼів.
Сервер API обмежує кількість розширених ресурсів цілими числами. Приклади дійсних значень: 3
, 3000m
та 3Ki
. Приклади недійсних значень: 0.5
та 1500m
(томущо 1500m
буде давати в результаті 1.5
).
Примітка:
Розширені ресурси замінюють Opaque Integer Resources. Користувачі можуть використовувати будь-який префікс доменного імені, крімkubernetes.io
, який зарезервований.Щоб використовувати розширений ресурс у Podʼі, включіть імʼя ресурсу як ключ у масив spec.containers[].resources.limits
у специфікації контейнера.
Примітка:
Розширені ресурси не можуть бути перевищені, тому запити та обмеження мають бути рівними, якщо обидва присутні у специфікації контейнера.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
ніколи не буде запланованим. - Перевірте наявність "taint" вузла. Якщо більшість ваших вузлів мають "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 kube-dns-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,23 ГБ памʼяті, то цей Pod не поміститься на вузлі.
Дивлячись на розділ "Podʼи", ви можете побачити, які Podʼи займають місце на вузлі.
Обсяг ресурсів, доступних для Podʼів, менший за місткість вузла, оскільки системні служби використовують частину доступних ресурсів. У Kubernetes API, кожен вузол має поле .status.allocatable
(див. NodeStatus для деталей).
Поле .status.allocatable
описує обсяг ресурсів, доступних для Podʼів на цьому вузлі (наприклад: 15 віртуальних ЦП та 7538 МіБ памʼяті). Для отримання додаткової інформації про виділені ресурси вузла в 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
показує, що контейнер намагався використовувати більше памʼяті, ніж встановлений йому ліміт.
Наступним кроком може бути перевірка коду програми на витік памʼяті. Якщо ви встановите, що програма працює так, як очікувалося, розгляньте встановлення вищого ліміту памʼяті (і, можливо, запит) для цього контейнера.
Що далі
- Отримайте практичний досвід призначення ресурсів памʼяті контейнерам та Podʼам.
- Отримайте практичний досвід призначення ресурсів ЦП контейнерам та Podʼам.
- Прочитайте, як API-довідка визначає контейнер та його вимоги до ресурсів
- Прочитайте про квоти ресурсів проєкту в XFS
- Дізнайтеся більше про конфігурацію планувальника kube-scheduler (v1)
- Дізнайтеся більше про класи якості обслуговування для Podʼів