Модуль 4.3: Вимоги до ресурсів та обмеження
Складність:
[MEDIUM]— критично для продакшену, впливає на плануванняЧас на проходження: 35–45 хвилин
Передумови: Модуль 1.1 (Поди), розуміння концепцій CPU та пам’яті
Результати навчання
Розділ «Результати навчання»Ці результати зосереджені на рішеннях, які ви зможете обґрунтувати під тиском іспиту CKAD і в реальному кластері. Наприкінці ви повинні вміти прочитати специфікацію ресурсів, передбачити поведінку планувальника та kubelet, яку вона породжує, і вибрати наступну діагностичну команду, не вгадуючи лише за симптомами.
- Впроваджувати запити та обмеження CPU й пам’яті у специфікаціях Pod, Deployment, LimitRange та ResourceQuota.
- Діагностувати поди у стані Pending, перезапуски OOMKilled та дроселювання CPU, співвідносячи налаштування ресурсів зі статусом і подіями Kubernetes.
- Проєктувати розподіл ресурсів, що збалансовує продуктивність застосунку, ємність ноди, клас QoS та політику простору імен.
- Порівнювати запити, обмеження, LimitRange та ResourceQuota, щоб передбачити, чи буде робоче навантаження відхилене, заплановане, сповільнене, вбите чи витіснене.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: реліз розгортається у завантажений день, і одночасно з’являються два різні збої. Один новий под залишається у стані Pending з подією Insufficient cpu, тоді як інший под успішно запускається, а потім перезапускається з Reason: OOMKilled. Обидва збої згадують ресурси, але вони відбуваються на різних фазах циклу управління Kubernetes, тож сприймати їх як одну й ту саму проблему — це марнувати час і ще більше виводити кластер з рівноваги.
Запити та обмеження ресурсів — це контракт між вашим робочим навантаженням, планувальником і середовищем виконання на ноді. Запит повідомляє планувальнику, скільки ємності потрібно зарезервувати, перш ніж под зможе потрапити на ноду. Обмеження повідомляє kubelet та середовищу виконання контейнера, скільки CPU чи пам’яті може спожити запущений контейнер. Ці два поля стоять поруч у YAML, але відповідають на різні операційні запитання: «Чи вміститься цей под тут?» і «Що станеться після його запуску?»
Аналогія з орендою квартири все ще працює, якщо застосовувати її обережно. Запит — це як гарантоване паркомісце, яке управитель будинку резервує до того, як ви заселитеся, тоді як обмеження — це як правило максимальної заповненості, що діє вже після того, як ви опинилися всередині. Для пам’яті порушення правила заповненості може витіснити процес, бо пам’ять не можна безпечно стиснути. Для CPU порушення правила зазвичай сповільнює контейнер, бо процесорний час можна поділити на менші частки.
Іспит CKAD часто перевіряє цю тему через невеликі маніфести та короткі описи збоїв, а не через довгі теоретичні запитання. Вам може знадобитися швидко додати ресурси до пода, пояснити, чому політика простору імен підставила значення за замовчуванням, або знайти причину, чому под не може заплануватися, хоча нода все ще показує вільний CPU на рівні операційної системи. Усе в цьому модулі передбачає Kubernetes 1.35 або новіший, і описана тут механіка стабільна для всіх об’єктів API ресурсів, з якими ви працюєте щодня у кластері.
Запити, обмеження та обіцянка планувальника
Розділ «Запити, обмеження та обіцянка планувальника»Запити й обмеження найлегше вивчати, коли ви відокремлюєте рішення площини управління від рішення ноди. Планувальник оцінює запити до того, як под запуститься, використовуючи доступну для виділення ємність ноди та суму запитів уже допущених подів. Kubelet та середовище виконання застосовують обмеження після того, як под уже запущений, використовуючи засоби контролю операційної системи для CPU й пам’яті. Саме через це под може не заплануватися ще до того, як використає бодай якийсь ресурс, і саме через це запланований под може пізніше бути вбитий за перевищення пам’яті.
| Термін | Значення | Коли застосовується |
|---|---|---|
| Запит (Request) | Гарантований мінімум ресурсів | Під час планування |
| Обмеження (Limit) | Максимально дозволені ресурси | Під час виконання |
Уявіть запит як резервування у книзі обліку планувальника. Якщо под запитує 500m CPU та 256Mi пам’яті, планувальник шукає ноду щонайменше з такою кількістю незарезервованої доступної для виділення ємності. Він не запускає ваш процес, не вимірює фактичне використання й не прогнозує майбутні сплески. Він лише вирішує, чи може заявлене резервування вміститися поруч із резервуваннями, які вже присутні на ноді.
Уявіть обмеження як межу під час виконання. Обмеження пам’яті — це жорстка межа, бо контейнер не може й далі виділяти пам’ять понад неї, не будучи завершеним. Обмеження CPU — це зазвичай межа темпу, бо середовище виконання може дроселювати контейнер і дати йому продовжити пізніше. Ця різниця важлива під час реагування на інциденти: тиск на пам’ять породжує перезапуски та втрату стану, тоді як дроселювання CPU зазвичай породжує затримки, повільнішу пакетну роботу та збентежено низьку пропускну здатність.
┌─────────────────────────────────────────────────────────────┐│ Resource Request vs Limit │├─────────────────────────────────────────────────────────────┤│ ││ Memory: ││ ├── Request: 256Mi (guaranteed, used for scheduling) ││ ├── Actual usage can vary between 0 and Limit ││ └── Limit: 512Mi (hard cap, exceeding = OOMKill) ││ ││ CPU: ││ ├── Request: 100m (guaranteed, used for scheduling) ││ ├── Can burst above request if node has spare capacity ││ └── Limit: 500m (throttled if exceeded, NOT killed) ││ ││ ┌────────────────────────────────────────────────────┐ ││ │ │ ││ │ 0 Request Actual Limit │ ││ │ | | | | │ ││ │ ├───────────┼───────────┼────────────┤ │ ││ │ │ guaranteed│ burstable │ max │ │ ││ │ └───────────┴───────────┴────────────┘ │ ││ │ │ ││ └────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────┘Планувальник використовує запити, а не обмеження, бо плануванню потрібна стабільна модель резервування. Якби планувальник використовував обмеження, кластери з консервативними запасами безпеки виглядали б заповненими навіть тоді, коли більшість застосунків зазвичай споживає набагато менше. Якби планувальник використовував живе використання, розміщення стало б нестабільним, бо тихий застосунок міг би раптово сплеснути після прибуття нового пода. Запити — це золота середина: вони відображають обсяг, який ви готові зарезервувати навіть тоді, коли контейнер його наразі не використовує.
Ця модель також пояснює, чому надмірне запитування дороге навіть тоді, коли ваші застосунки тихі. Кластер може мати вільний CPU на рівні ноди, тоді як планувальник відмовляє новим подам, бо книга обліку запитів заповнена. Нода може виглядати недовикористаною на графіку моніторингу, але планувальник дотримується обіцянок, уже даних запущеним подам. У завданнях CKAD найшвидший спосіб це підтвердити — оглянути події пода, а потім розділ виділених ресурсів ноди.
Зробіть паузу й передбачте: под запитує 100m CPU й має обмеження CPU 500m. Якщо на ноді є вільний CPU, под може використати до свого обмеження; якщо сусіднім подам також потрібен CPU, середовище виконання розподіляє час відповідно до налаштувань cgroup кожного контейнера й дроселює ті, що досягли квоти. Запит забезпечив подові планування, але не обмежив назавжди споживання під час виконання.
Пам’ять поводиться менш поблажливо, бо ядро не може безпечно сповільнити виділення пам’яті так само, як воно може сповільнити виконання CPU. Щойно контейнер перевищує своє обмеження пам’яті, процес стає кандидатом на завершення, і Kubernetes повідомляє останній стан як OOMKilled. Якщо кілька подів на ноді одночасно використовують більше пам’яті, ніж їхні запити, витіснення kubelet може також статися ще до того, як буде перетнуто індивідуальні обмеження контейнерів. Точний симптом залежить від того, чи тиск локальний для обмеження контейнера, чи спільний для всієї ноди.
Написання специфікацій ресурсів, які Kubernetes може допустити
Розділ «Написання специфікацій ресурсів, які Kubernetes може допустити»Блок ресурсів належить до кожного контейнера, а не безпосередньо до спеки пода. Ця деталь часто стає причиною помилок на іспиті, бо под має один результат планування, але ресурси оголошуються для кожного контейнера й лише потім сумуються для планування. Под із двома контейнерами, кожен з яких запитує 100m CPU, має запит на планування на рівні пода 200m CPU. Контейнери ініціалізації (init) обробляються для планування інакше, але для основ роботи з ресурсами в CKAD ключова звичка — щоразу розміщувати блок на рівні контейнера.
apiVersion: v1kind: Podmetadata: name: resource-demospec: containers: - name: app image: nginx resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m"Цей маніфест говорить, що контейнеру потрібна зарезервована десята частина ядра CPU та 256Mi пам’яті, щоб бути запланованим. Він може сплеснути до половини ядра CPU, коли це дозволяє ємність під час виконання, і може виділити пам’ять до 512Mi, перш ніж обмеження стане фатальним. Значення тут наведені як рядки, бо взяття величин ресурсів у лапки дозволяє уникнути сюрпризів YAML і зберігає чітку візуальну відмінність. Kubernetes приймає величини ресурсів і без лапок, але значення в лапках — надійна звичка для прикладів і згенерованих маніфестів.
CPU вимірюється в ядрах, а суфікс m означає міліядра (millicores). Одне повне ядро — це 1 або 1000m, тож 250m означає чверть ядра. Запити та обмеження CPU можуть бути дробовими, бо процесорний час можна планувати частками. Для перегляду людиною міліядра зазвичай зручніші для невеликих сервісів, бо 100m читається легше, ніж 0.1.
| Значення | Зміст |
|---|---|
1 | 1 ядро CPU |
1000m | 1000 міліядер = 1 ядро |
500m | 0.5 ядра |
100m | 0.1 ядра (10%) |
Величини пам’яті можуть використовувати двійкові суфікси, як-от Mi та Gi, або десяткові суфікси, як-от M та G. Kubernetes приймає обидва, але вони не ідентичні, бо двійкові одиниці базуються на степенях 1024, а десяткові — на степенях 1000. Більшість прикладів Kubernetes використовують Mi та Gi, і це безпечніша угода, коли ви хочете, щоб значення відповідало тому, як оператори обговорюють пам’ять на нодах. У невеликому обмеженні різниця між 128M та 128Mi не велика, але узгоджені одиниці зменшують кількість помилок під час перегляду.
| Значення | Зміст |
|---|---|
128Mi | 128 мебібайтів (на основі 1024) |
1Gi | 1 гібібайт = 1024 Mi |
128M | 128 мегабайтів (на основі 1000) |
1G | 1 гігабайт = 1000 M |
Перед запуском — який вивід ви очікуєте від запиту JSONPath: мапу запитів, мапу обмежень, обидві мапи чи нічого? Цей маленький крок передбачення важливий, бо Kubernetes може мутувати под під час допуску, якщо LimitRange постачає значення за замовчуванням. Коли об’єкт, який ви оглядаєте, відрізняється від YAML, який ви написали, політика допуску — одне з перших місць, куди варто заглянути.
Коли ви генеруєте маніфести на іспиті чи в локальній лабораторії, тримайте блок ресурсів близько до контейнера, яким він керує. Для Deployment блок ресурсів розташований під spec.template.spec.containers[], а не під верхньорівневим spec самого Deployment. Це розміщення може здаватися вкладеним, але воно віддзеркалює модель об’єктів: Deployment створює ReplicaSet, ReplicaSet створюють Поди, а шаблон пода несе налаштування контейнера, що використовуються кожною реплікою.
Значення ресурсів мають походити з доказів, коли вони у вас є, і з консервативних значень за замовчуванням, коли їх немає. Для відомого сервісу використовуйте спостережуване стале та пікове використання, а потім встановлюйте запити близько до ємності, яку ви хочете зарезервувати під час нормальної роботи. Для нового сервісу в навчальному кластері виберіть помірні запити й обмеження, що дозволяють подові працювати, не приховуючи очевидних витоків пам’яті. Важлива звичка — робити значення усвідомленим, а не залишати продакшен-поди в BestEffort через недогляд.
Математика ресурсів для багатоконтейнерних подів
Розділ «Математика ресурсів для багатоконтейнерних подів»Більшість прикладів для початківців показують один контейнер на под, але Kubernetes сумує вимоги до ресурсів усіх контейнерів, що працюють разом. Сайдкар для логування, проксі чи локальний допоміжний процес споживає реальну ємність ноди навіть тоді, коли користувачі помічають лише основний застосунок. Планувальник розміщує под як єдине ціле, тож йому потрібно достатньо доступної для виділення ємності для сукупного запиту. Якщо ви забудете про допоміжний контейнер, под може коректно працювати в тихій лабораторії, але провалити розміщення або спричинити тиск, коли кількість реплік зросте.
Арифметика проста для звичайних контейнерів застосунку. Якщо под має контейнер app, що запитує 200m CPU, та sidecar, що запитує 50m, то под просить планувальник зарезервувати 250m CPU. Запити пам’яті додаються так само, а обмеження описують стелю під час виконання для кожного контейнера окремо. Саме тому навіть невеликий сайдкар повинен мати ресурси: він може бути маленьким, але множення його на багато реплік перетворює забутий запит на помилку планування ємності.
apiVersion: v1kind: Podmetadata: name: multi-container-demospec: containers: - name: app image: nginx resources: requests: cpu: "200m" memory: "256Mi" limits: cpu: "500m" memory: "512Mi" - name: sidecar image: busybox command: ["sh", "-c", "sleep 3600"] resources: requests: cpu: "50m" memory: "64Mi" limits: cpu: "100m" memory: "128Mi"Для цього пода стале резервування для планування — це 250m CPU та 320Mi пам’яті. Контейнер app і сайдкар можна обмежувати незалежно, тож app може бути OOMKilled без того, щоб сайдкар перевищив власне обмеження пам’яті, а сайдкар може бути задроселений без зміни обмеження CPU контейнера app. Статус пода може підсумувати результат, але статус контейнера дає точну причину для кожного контейнера. Під час усунення несправностей завжди оглядайте назву контейнера, прикріплену до перезапуску чи останнього стану.
Контейнери ініціалізації (init) додають ще одну тонкість, бо вони виконуються перед звичайними контейнерами застосунку, а не поряд із ними. Для кожного типу ресурсу Kubernetes для планування враховує більше з двох значень: вимогу init-контейнера або суму вимог звичайних контейнерів застосунку. Це означає, що важкий міграційний init-контейнер може змусити под потребувати більше пам’яті для планування, навіть якщо довготривалий застосунок невеликий. Под може виглядати завеликим за стале використання, але планувальник мусить зарезервувати достатньо ємності для найбільшої фази запуску.
Ця відмінність важлива, коли робоче навантаження має міграцію бази даних, крок генерації сертифіката чи прогрів кешу перед запуском основного процесу. Якщо init-контейнер запитує 1Gi пам’яті, а контейнери застосунку разом запитують 320Mi, подові потрібне більше резервування для запуску, щоб розмістити пам’ять. Зниження запиту контейнера застосунку не допоможе подові заплануватися, якщо init-контейнер залишається найбільшим запитом. Ви мусите оглянути всю спеку пода, а не лише контейнер, що залишається запущеним.
Яке число ви б використали для оцінки ємності: запит основного контейнера, суму звичайних контейнерів чи максимум init-контейнера? Обґрунтована відповідь залежить від ресурсу та фази, але джерело істини — модель розміщення планувальника. Просумуйте звичайні контейнери, порівняйте цю суму з найбільшим запитом init-контейнера для кожного ресурсу, а потім використайте більше значення для планування. Ця звичка не дає сайдкарам і роботі під час запуску зникнути з вашої уявної арифметики.
Розширені ресурси (extended resources) та величезні сторінки (huge pages) дотримуються тієї самої загальної теми: оголосіть те, що має бути зарезервоване перед запуском пода, і очікуйте, що Kubernetes плануватиме за цим оголошенням, а не за живим використанням. Питання з ресурсів у CKAD зазвичай тримаються CPU та пам’яті, але базовий урок переноситься. Kubernetes не може захистити спільну ємність здогадами, прихованими всередині застосунку. Спека пода мусить заявити резервування достатньо чітко, щоб допуск, планування та застосування на ноді могли виконати свою роботу.
Застосування під час виконання: OOMKill, дроселювання та QoS
Розділ «Застосування під час виконання: OOMKill, дроселювання та QoS»Симптоми під час виконання стають набагато зрозумілішими, коли ви пам’ятаєте, що CPU й пам’ять мають різні режими відмови. CPU стискуваний, бо середовище виконання може дати контейнеру менше часових часток і дати йому продовжити. Пам’ять не стискувана в тому самому практичному сенсі, бо виділення або вдається, або ні. Kubernetes відображає цю різницю в статусі пода, останньому стані контейнера та подіях ноди.
Container uses > limit → OOMKilled → Container restartsКонтейнер OOMKilled перевищив свою межу пам’яті або був вибраний під час тиску на пам’ять у спосіб, що завершив процес. Поле Last State особливо корисне, бо перезапущений контейнер наразі може виглядати справним, тоді як причина його попереднього завершення розповідає справжню історію. Під час усунення несправностей у CKAD вам зазвичай не потрібен повний стек спостережуваності, щоб ідентифікувати цей симптом. Статусу пода, кількості перезапусків та історії подій достатньо, щоб довести, що задіяне застосування пам’яті.
# Check if a pod was OOMKilledkubectl describe pod my-pod | grep -A5 "Last State"kubectl get pod my-pod -o jsonpath='{.status.containerStatuses[0].lastState}'Якщо обмеження занадто низьке, його підвищення може бути правильним, але це не повинно бути єдиною думкою. Обмеження пам’яті захищає ноду від процесу, що вийшов з-під контролю, тож збільшення його без доказів може перемістити збій з одного контейнера на всю ноду. Спочатку порівняйте обмеження з реальним використанням, накладними витратами часу виконання застосунку, сплесками під час запуску та поведінкою кешу. Потім вирішіть, чи потрібно застосунку більше пам’яті, нижча стеля кешу, менше одночасних воркерів чи інше співвідношення запиту до обмеження.
Container uses > limit → Throttled (slowed down, NOT killed)Дроселювання CPU тихіше за OOMKill, бо контейнер зазвичай залишається у стані Running. Застосунок може повідомляти про повільні відповіді, затримку готовності, пропущені тайм-аути чи низьку пропускну здатність, тоді як Kubernetes усе ще показує под справним. kubectl top може показати поточне використання, коли встановлено Metrics Server, але саме дроселювання часто краще підтверджується через метрики часу виконання чи застосунку. На іспиті головна відмінність у тому, що обмеження CPU сповільнюють роботу, тоді як обмеження пам’яті можуть її завершити.
Зробіть паузу й передбачте: под має requests.cpu: 100m та limits.cpu: 500m, а на ноді доступне одне повне ядро CPU. Под може споживати до 500m, поки доступна ємність, але йому не гарантовано цей обсяг під час суперництва. Якщо кілька подів сплескують одночасно, їхні запити та засоби контролю часу виконання впливають на те, як розподіляється процесорний час. Саме тому сервіс може бути успішно запланований і все одно працювати погано, якщо його обмеження CPU занадто тісне.
Kubernetes призначає кожному поду клас якості обслуговування (QoS) на основі його налаштувань ресурсів. QoS не замінює запити, обмеження чи квоти; він впливає на порядок витіснення, коли нода під тиском. Поди Guaranteed отримують найсильніший захист від витіснення, бо кожен контейнер має рівні запити й обмеження CPU та пам’яті. Поди BestEffort отримують найслабший захист, бо вони не мають оголошеного резервування, тож будь-яке використання перевищує їхній запит, що дорівнює нулю.
| Клас QoS | Умова | Імовірність витіснення |
|---|---|---|
| Guaranteed | Запити = Обмеження для всіх контейнерів | Найнижча (захищено) |
| Burstable | Запити < Обмеження (або встановлено лише одне) | Середня |
| BestEffort | Не встановлено запитів чи обмежень | Найвища |
Под Guaranteed корисний, коли передбачуваність важливіша за гнучкість сплесків. Запит дорівнює обмеженню для кожного ресурсу на кожному контейнері, тож Kubernetes знає, що зарезервований обсяг пода й максимальний обсяг однакові. Це може бути доречно для щільно розмірених інфраструктурних компонентів чи робочих навантажень, які мають бути захищені під час тиску на пам’ять. Компроміс у тому, що планувальник резервує повний обсяг наперед, що може знизити ефективність ущільнення.
resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "256Mi" # Same as request cpu: "100m" # Same as requestПоди Burstable поширені для робочих навантажень застосунків, бо вони резервують реалістичний базовий рівень, водночас дозволяючи контрольований запас. Вебсервіс може запитувати достатньо CPU та пам’яті для звичайного трафіку, а потім дозволяти додаткові CPU чи пам’ять для коротких сплесків. Це ефективно, коли в кластері багато сервісів, чиї піки не збігаються в часі. Це стає ризикованим, коли обмеження встановлені настільки високо, що одночасні сплески можуть створити тиск на ноду.
resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" # Higher than request cpu: "500m" # Higher than requestПоди BestEffort прийнятні для одноразових експериментів, але вони — поганий вибір за замовчуванням для продакшену. Вони можуть працювати, коли є вільна ємність, проте не мають резервування і першими стоять у черзі, коли kubelet потрібно повернути ресурси. Под BestEffort також може зробити планування ємності оманливим, бо він споживає реальні CPU та пам’ять, не з’являючись у книзі обліку запитів планувальника. Для роботи з CKAD припускайте, що важливі поди повинні мати принаймні запити.
resources: {} # No resources definedЗупиніться й подумайте: под має обмеження, але не має запитів. Kubernetes у деяких випадках може скопіювати обмеження в запити, а значення за замовчуванням простору імен також можуть мутувати відсутні поля. Це означає, що клас QoS, який ви очікуєте з маніфесту, може відрізнятися від об’єкта, збереженого після допуску. Оглядайте створений под, коли поведінка має значення, бо значення за замовчуванням під час допуску — частина контракту кластера.
Планування, політика простору імен та сигнали ємності
Розділ «Планування, політика простору імен та сигнали ємності»Збої планування часто легше розв’язати, ніж збої під час виконання, бо планувальник залишає прямі докази в подіях. Под у стані Pending з Insufficient cpu чи Insufficient memory не зазнав збою всередині контейнера; він провалив тест на розміщення. Тест порівнює запити пода з доступною для виділення ємністю ноди, яка ще не зарезервована іншими подами. Саме тому саме лише зниження обмеження не змусить под у стані Pending заплануватися, якщо запит усе ще завеликий.
# Check why a pod is Pendingkubectl describe pod my-pod
# Events may show:# 0/3 nodes are available: 3 Insufficient cpu.# or# 0/3 nodes are available: 3 Insufficient memory.Ємність ноди має кілька рівнів, і ця відмінність важлива під час усунення несправностей. Capacity — це сира величина, яку повідомляє нода, тоді як allocatable — це те, що Kubernetes вважає доступним для подів після резервування ресурсів для системи та kubelet. Allocated resources — це сума запитів та обмежень подів, уже допущених на ноду. Планувальника передусім цікавить allocatable мінус запитані ресурси, а не поточна простоюваність на рівні операційної системи.
# Node capacity and allocatablekubectl describe node NODE_NAME | grep -A5 Capacitykubectl describe node NODE_NAME | grep -A5 Allocatable
# Already allocatedkubectl describe node NODE_NAME | grep -A10 "Allocated resources"Сценарій-вправа: под запитує два ядра CPU, кожна нода має чотири ядра, і кожна нода все ще показує вільний CPU на дашборді. Под усе одно може залишатися у стані Pending, якщо наявні поди вже зарезервували планований CPU через запити. У цій ситуації збільшення обмеження пода нічого не дає, а зниження запиту пода допомагає лише тоді, коли нижче значення залишається чесним для робочого навантаження. Тривкі виправлення — це коректне розмірення запитів, переміщення чи масштабування інших робочих навантажень або додавання ємності.
LimitRange — це об’єкт політики допуску для простору імен. Він може встановлювати запити й обмеження за замовчуванням для контейнерів, які їх опускають, і може відхиляти контейнери, що виходять за налаштовані мінімальні чи максимальні значення. Це корисно, коли простір імен містить багато невеликих робочих навантажень і ви хочете, щоб кожен под входив до планувальника з базовим контрактом ресурсів. Це не заміна специфічного для застосунку розмірення, бо значення за замовчуванням — лише безпечні здогади.
apiVersion: v1kind: LimitRangemetadata: name: cpu-memory-limitsspec: limits: - default: # Default limits if not specified cpu: "500m" memory: "512Mi" defaultRequest: # Default requests if not specified cpu: "100m" memory: "256Mi" max: # Maximum allowed cpu: "2" memory: "2Gi" min: # Minimum allowed cpu: "50m" memory: "64Mi" type: Container# View LimitRange objects in the current namespacekubectl get limitrangekubectl describe limitrange cpu-memory-limitsLimitRange змінює поведінку допуску до початку планування. Якщо под опускає ресурси, а простір імен має значення за замовчуванням, сервер API може зберегти спеку пода, що містить значення, яких автор не писав. Якщо под просить менше за мінімум чи більше за максимум, допуск відхиляє його ще до того, як планувальник його побачить. Ця відмінність дає вам чіткий порядок усунення несправностей: помилки допуску з’являються під час створення об’єкта, помилки планування з’являються після того, як об’єкт існує й залишається у стані Pending.
ResourceQuota також обмежена простором імен, але вона контролює загальний бюджет, спожитий об’єктами в цьому просторі імен. Квота може обмежити загальний запитаний CPU, запитану пам’ять, обмеження CPU, обмеження пам’яті, кількість подів та багато інших ресурсів. Коли квота відстежує обчислювальні ресурси, подам зазвичай потрібні поля ресурсів, щоб сервер API міг обчислити, чи перевищить новий об’єкт бюджет простору імен. Значення за замовчуванням LimitRange та ResourceQuota часто працюють разом, бо значення за замовчуванням дають квоті, що рахувати.
apiVersion: v1kind: ResourceQuotametadata: name: compute-quotaspec: hard: requests.cpu: "4" requests.memory: "8Gi" limits.cpu: "8" limits.memory: "16Gi" pods: "10"# View quota usage in the current namespacekubectl get resourcequotakubectl describe resourcequota compute-quotaЗбої квоти — це збої допуску, а не збої планувальника. Якщо простір імен уже використав більшу частину бюджету requests.memory, новий под може бути відхилений навіть тоді, коли на нодах вдосталь вільної пам’яті. Це захищає межу простору імен і не дає одній команді чи вправі спожити більше за призначену частку. Виправлення — зменшити запит нового пода, видалити чи змінити розмір інших робочих навантажень простору імен або підвищити квоту звичайним адміністративним шляхом.
Наведена нижче коротка довідка тримає поширені команди огляду в одному місці. Використовуйте їх після того, як ви знаєте, яку фазу налагоджуєте: допуск об’єкта, розміщення планувальником чи застосування під час виконання. Команда, що показує виділення на ноді, не пояснить відхиленої ResourceQuota, а команда квоти не пояснить контейнера OOMKilled. Відповідність команди фазі — це навичка, яку цей модуль намагається сформувати.
# Check pod resourceskubectl get pod POD -o jsonpath='{.spec.containers[*].resources}'
# Check node capacity and allocationkubectl describe node NODE | grep -A10 "Allocated"
# Check QoS classkubectl get pod POD -o jsonpath='{.status.qosClass}'
# Check current usage when Metrics Server is availablekubectl top pod PODРозбір прикладу: налаштування невеликого вебпода
Розділ «Розбір прикладу: налаштування невеликого вебпода»Почніть з невеликого вебдеплойменту, що має реалістичний базовий рівень та помірний запас на сплеск. Деплоймент використовує дві репліки, тож планувальник мусить розмістити два резервування подів, а не лише одне. Кожна репліка запитує 50m CPU та 64Mi пам’яті, тож сукупний запитаний слід — це 100m CPU та 128Mi пам’яті на весь Деплоймент. Кожна репліка може сплеснути до 100m CPU та 128Mi пам’яті, перш ніж застосується обмеження.
apiVersion: apps/v1kind: Deploymentmetadata: name: resource-webspec: replicas: 2 selector: matchLabels: app: resource-web template: metadata: labels: app: resource-web spec: containers: - name: nginx image: nginx resources: requests: cpu: "50m" memory: "64Mi" limits: cpu: "100m" memory: "128Mi"Цей приклад навмисно невеликий, бо він навчає арифметики без потреби у великому кластері. Якщо ви застосуєте його в однонодному навчальному середовищі, запитаний слід має легко вміститися. Якщо под залишається у стані Pending, запит ресурсів — лише одна з можливих причин; селектори нод, taint’и, проблеми зі стягуванням образу та політика простору імен також можуть заблокувати поступ. Першою діагностичною командою все одно має бути kubectl describe pod, бо вона повідомляє події планувальника та підказки, пов’язані з допуском, поруч з об’єктом.
kubectl apply -f resource-web.yamlkubectl get deploy resource-webkubectl get pods -l app=resource-webkubectl get pod -l app=resource-web -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.qosClass}{"\n"}{end}'Припустімо, обидва поди працюють і повідомляють QoS Burstable. Цей результат випливає безпосередньо з маніфесту, бо запити нижчі за обмеження як для CPU, так і для пам’яті. Якщо ви зміните кожне обмеження так, щоб воно дорівнювало відповідному запиту, поди стануть Guaranteed, але вони також втратять запас на сплеск. Якщо ви повністю приберете блок ресурсів, вони стануть BestEffort, якщо тільки LimitRange не підставить значення за замовчуванням.
Тепер припустімо, що Деплоймент має обслуговувати короткі сплески трафіку без частого дроселювання CPU. Підвищення обмеження CPU зі 100m до 250m може допомогти затримці, якщо нода має вільну ємність, але воно не змінює планування, бо запит CPU залишається 50m на репліку. Підвищення запиту CPU змінює планування та резервування, що може покращити справедливість під час суперництва, але може зменшити, скільки подів вміщується. Правильне редагування залежить від того, чи проблема — це ємність для сплесків під час виконання, чи резервування планувальником.
Налаштування пам’яті має інший профіль ризику. Підвищення обмеження пам’яті може зменшити перезапуски OOMKilled, коли застосунку справді потрібно більше пам’яті, але воно також збільшує максимальну пам’ять, яку нода може потребувати поглинути під час сплесків. Підвищення запиту пам’яті резервує більше планованої ємності й покращує позицію щодо витіснення, бо kubelet порівнює використання із запитами під час тиску. Для процесів зі станом чи з інтенсивним кешуванням запит зазвичай має відображати реальний робочий базовий рівень, а не найменше значення, що дозволяє подові запуститися.
Який підхід ви б вибрали тут і чому: підвищити лише обмеження, підвищити лише запит, підвищити обидва чи спершу дослідити застосунок? Обґрунтована відповідь називає симптом. Поди у стані Pending вказують на запити та ємність, перезапуски OOMKilled вказують на обмеження пам’яті чи поведінку застосунку, а повільні-але-запущені поди вказують на дроселювання CPU, недостатній запит CPU під час суперництва або вузькі місця на рівні застосунку.
Остання перевірка — оглянути збережений об’єкт, а не лише файл, який ви редагували. Допуск може додати значення за замовчуванням, контролери можуть шаблонувати поди з Деплойменту, а люди можуть застосувати інший файл, ніж той, що на перегляді. kubectl get з JSONPath лаконічний, тоді як kubectl describe кращий, коли вам потрібен контекст подій та виділення на ноді. В умовах іспиту використовуйте найкоротшу команду, що доводить конкретне твердження, яке вам потрібно зробити.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Керування ресурсами має кілька повторюваних патернів, що масштабуються за межі одного маніфесту. Це не моральні правила; це способи зробити розміщення планувальником, поведінку під час виконання та керування простором імен передбачуваними. Хороший патерн називає, коли він застосовний і який компроміс приймає. Поганий патерн зазвичай починається з розумного скорочення й стає шкідливим, коли змінюються трафік, репліки чи сусідні робочі навантаження.
| Патерн | Коли використовувати | Чому це працює | Аспект масштабування |
|---|---|---|---|
| Базовий запит з виміряним обмеженням на сплеск | Бездержавні сервіси зі змінним трафіком | Планувальник резервує звичайний попит, тоді як середовище виконання дозволяє короткі сплески | Перегляньте після навантажувальних тестів та продакшен-вимірювань |
| Ресурси Guaranteed для критичних подів фіксованого розміру | Інфраструктурні чи чутливі до затримки компоненти зі сталим використанням | Захист QoS найсильніший, а конверт часу виконання явний | Ефективність ущільнення падає, бо спільне використання для сплесків зменшено |
| Значення за замовчуванням простору імен плюс квота | Спільні навчальні, командні чи орендарські простори імен | Кожен под має обчислювані ресурси, а простір імен має бюджет | Значення за замовчуванням треба переглядати, щоб крихітні лабораторії не успадковували завеликі резервування |
| Окрема діагностика за фазою | Будь-який под у стані Pending, відхилений, повільний чи з перезапусками | Збої допуску, планування та виконання залишають різні докази | Запустіть специфічну для фази команду, перш ніж змінювати YAML |
Найсильніший патерн для CKAD — це усунення несправностей за фазами. Якщо створення провалюється, оглядайте політику допуску, як-от LimitRange та ResourceQuota. Якщо об’єкт існує, але залишається у стані Pending, оглядайте події планувальника та виділені ресурси ноди. Якщо под працює, а потім перезапускається чи сповільнюється, оглядайте стан контейнера, обмеження та живе використання, де воно доступне. Цей порядок не дає вам змінювати обмеження, коли справжній блокувальник — це запит.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
| Немає ресурсів на продакшен-подах | Поди стають BestEffort, якщо тільки не застосуються значення за замовчуванням, а планування ємності стає оманливим | Встановіть принаймні запити CPU та пам’яті для важливих робочих навантажень |
| Запити скопійовані з обмежень без роздумів | Планувальник резервує пікову ємність, і кластер виглядає заповненим рано | Встановлюйте запити за звичайним попитом, а обмеження — за безпечною межею сплеску чи захисту |
| Крихітні обмеження пам’яті для застосунків з важким часом виконання | Контейнери перезапускаються під час запуску, збирання сміття чи прогріву кешу | Виміряйте пам’ять процесу, врахуйте накладні витрати часу виконання й додайте свідомий запас |
| Гігантські обмеження CPU як виправлення продуктивності | Дроселювання може переміщатися, а шумні робочі навантаження можуть впливати на сусідів | Виміряйте дроселювання, налаштуйте запити та масштабуйте репліки чи шляхи коду за потреби |
Команди потрапляють у ці антипатерни, бо YAML ресурсів виглядає простим. Складна частина — не синтаксис; це рішення, яке число відображає резервування, яке число відображає межу безпеки і який симптом доводить, що поточне число неправильне. Для CKAD вам потрібно бути швидкими із синтаксисом, але іспит усе одно винагороджує ту саму уявну модель, що використовується в продакшені. Опишіть под, ідентифікуйте фазу, а потім відредагуйте поле, що впливає на цю фазу.
Ще один практичний патерн — робити зміни ресурсів спостережуваними. Pull request, що змінює запити чи обмеження, має пояснити симптом, який він усуває, очікуваний вплив на планування та очікуваний вплив на час виконання. У лабораторії ви можете записати це обґрунтування в нотатці поруч із командою. У реальному репозиторії воно належить до контексту перегляду, щоб майбутні супровідники знали, чи значення було виміряне, успадковане чи вибране як безпечна стартова точка.
Фреймворк прийняття рішень
Розділ «Фреймворк прийняття рішень»Використовуйте цей фреймворк, коли з’являється проблема з ресурсами і вам потрібно швидко вибрати наступний крок. Мета — не запам’ятати кожну можливу подію Kubernetes. Мета — класифікувати фазу збою, а потім вибрати об’єкт і поле, що справді можуть вплинути на цю фазу. Под у стані Pending не виправляється більшим обмеженням пам’яті, якщо запит також не змінюється, а под OOMKilled не виправляється меншим запитом CPU, якщо справжня проблема не в іншому місці.
Resource symptom appears | vWas the object rejected by the API server? |-- yes --> Check LimitRange and ResourceQuota admission rules | no vDoes the pod exist but stay Pending? |-- yes --> Check requests, node allocatable capacity, and scheduler events | no vDoes the container restart with OOMKilled? |-- yes --> Check memory limit, memory usage, runtime overhead, and leaks | no vIs the pod Running but slow under load? |-- yes --> Check CPU limits, CPU requests under contention, and app metrics | no vInspect QoS, eviction events, and neighboring workload pressureФреймворк також допомагає вирішити, що змінювати — запит чи обмеження. Зміна запиту впливає на планування та резервування. Зміна обмеження впливає на застосування під час виконання та на максимальну межу сплеску чи пам’яті. Зміна обох доречна, коли і справжній базовий рівень робочого навантаження, і безпечний максимум змінилися. Не змінювати нічого доречно, коли симптом вказує на селектор, образ, пробу чи помилку застосунку.
| Симптом | Перший доказ для перевірки | Найімовірніше задіяне поле чи об’єкт | Чому |
|---|---|---|---|
| Под відхилено під час створення | Помилка API від kubectl apply | LimitRange чи ResourceQuota | Політика допуску виконується перед плануванням |
| Под залишається у стані Pending | Події kubectl describe pod | Запити CPU чи пам’яті | Планувальник вміщує запити в доступну для виділення ємність |
| Контейнер перезапускається як OOMKilled | Останній стан контейнера | Обмеження пам’яті чи поведінка пам’яті застосунку | Час виконання застосовує пам’ять як жорстку межу |
| Под у стані Running, але повільний | Метрики використання, затримки, дроселювання | Обмеження CPU, запит CPU чи кількість реплік | Тиск на CPU сповільнює роботу, а не вбиває її |
| Под витіснено під час тиску | Статус пода та події ноди | Клас QoS та використання понад запити | Витіснення kubelet враховує запити та сигнали пріоритету пода |
Коли ви розмірюєте новий застосунок, почніть із запитання, який збій ви намагаєтеся запобігти. Обмеження пам’яті запобігає тому, щоб один контейнер споживав необмежену пам’ять, але воно може створити перезапуски, якщо встановлене нижче за реальні піки. Обмеження CPU захищає сусідів від необмеженого використання CPU, але воно може створити затримку, якщо встановлене нижче за попит. Запит запобігає переобтяженню планувальника оголошеною базовою ємністю, але він може залишити придатні ресурси ноди невикористаними, якщо встановлений вище за реалістичну потребу.
Для невеликого бездержавного вебсервісу поширений перший підхід — це помірний запит CPU, вище обмеження CPU, запит пам’яті близько до звичайного використання та обмеження пам’яті, що включає запас на запуск і пік. Для пакетного завдання ви можете вибрати більший запит, щоб завдання отримало достатньо CPU під час суперництва й завершилося передбачувано. Для критичного компонента управління ви можете встановити запити рівними обмеженням, щоб отримати QoS Guaranteed. Вибір дизайну випливає з толерантності робочого навантаження до затримки, перезапуску, витіснення та неефективного ущільнення.
Для політики простору імен вирішіть, чи потрібні вам значення за замовчуванням, стелі чи бюджети. LimitRange постачає значення за замовчуванням та мінімальні чи максимальні значення для кожного контейнера. ResourceQuota постачає загальні значення для всього простору імен та бюджети кількості об’єктів. Значення за замовчуванням без квот усе ще можуть дозволити завеликій кількості подів спожити кластер, тоді як квоти без значень за замовчуванням можуть відхилити поди, що опускають запити. Використання обох дає вам простір імен, що послідовно допускає звичайні поди, водночас усе ще забезпечуючи дотримання загального бюджету.
Останнє правило прийняття рішень — уникати сліпої зміни значень ресурсів під час інциденту. Якщо под у стані Pending, доведіть, що запитаний ресурс — це обмеження. Якщо контейнер OOMKilled, доведіть, чи обмеження нижче за спостережуваний пік, чи застосунок виділяє пам’ять неочікувано. Якщо сервіс повільний, доведіть, чи відбувається дроселювання CPU, перш ніж підвищувати обмеження. Швидка діагностика — це не те саме, що випадкове редагування YAML; це короткий шлях від симптому до механізму.
Чи знали ви?
Розділ «Чи знали ви?»- CPU стискуваний, пам’ять — ні. Якщо ви перевищите обмеження CPU, вас задроселюють. Якщо ви перевищите обмеження пам’яті, вас вб’ють.
- Запити впливають на планування, обмеження — на час виконання. Под із запитом пам’яті 1Gi не запланується на ноді, де доступно лише 512Mi, навіть якщо контейнер використовує лише 100Mi.
- Kubernetes не запобігає переобтяженню пам’яті. Якщо всі поди одночасно сплеснуть до своїх обмежень, на ноді може скінчитися пам’ять, і вона почне витісняти чи вбивати робочі навантаження.
- Синтаксис
cpu: 0.1еквівалентнийcpu: 100m, бо Kubernetes виражає дробовий CPU в міліядрах, де1000mдорівнює одному ядру.
Типові помилки
Розділ «Типові помилки»Більшість помилок із ресурсами походить від плутання синтаксису поля з його операційним значенням. Наведена нижче таблиця тримає збій, причину та виправлення в одному рядку, тож ви можете зіставити кожну помилку з фазою, де вона з’являється. Коли практикуєтеся, проговорюйте фазу вголос, перш ніж вибирати виправлення; ця звичка запобігає напрочуд великій кількості неправильних правок.
| Помилка | Чому вона трапляється | Як її виправити |
|---|---|---|
| Не встановлено ресурсів | Поди BestEffort легко створити, і вони можуть працювати в порожніх кластерах | Встановіть принаймні запити CPU та пам’яті для важливих подів |
| Запит більший за обмеження | Автор сприймає обидва поля як незалежні нотатки, а не як впорядкований конверт | Тримайте кожен запит меншим чи рівним відповідному обмеженню |
| Обмеження пам’яті занадто низьке | Накладні витрати часу виконання, сплески під час запуску чи зростання кешу не були враховані | Профілюйте застосунок, огляньте стан OOMKilled і підвищуйте обмеження лише за наявності доказів |
| Обмеження CPU занадто низьке | Под залишається у стані Running, тож дроселювання виглядає як сповільнення застосунку | Перевірте використання та сигнали дроселювання, потім налаштуйте обмеження, запити чи репліки |
| Запит рівний ємності ноди | Под не залишає доступного для виділення місця для системних резервувань чи інших подів | Залиште запас на ноді й розмірюйте запити відносно доступної для виділення ємності |
| Квота без запитів за замовчуванням | Поди, що опускають ресурси, не можна чисто врахувати у обчислювальній квоті | Поєднуйте ResourceQuota зі значеннями за замовчуванням LimitRange у спільних просторах імен |
| Редагування Deployment, але огляд старого Pod | Контролери створюють заміщувальні поди, а старі поди зберігають старі спеки до перестворення | Розгорніть оновлений шаблон і огляньте збережені ресурси нового пода |
Тест
Розділ «Тест»Використовуйте ці сценарії, щоб перевірити, чи можете ви ідентифікувати фазу, перш ніж називати виправлення. Кожна відповідь пояснює міркування, бо усунення несправностей із ресурсами здебільшого полягає у з’єднанні симптому з компонентом Kubernetes, що його породив. Якщо ви можете робити це послідовно, правки YAML стають простими.
Запитання 1: Под постійно перезапускається, і `kubectl describe` показує `Last State: Terminated, Reason: OOMKilled`. Контейнер має `limits.memory: 128Mi`, а розробник каже, що застосунок зазвичай використовує близько 80MB. Що ви перевіряєте, перш ніж змінювати маніфест?
Перевірте фактичне використання пам’яті контейнером, поведінку під час запуску, накладні витрати часу виконання та будь-які кеші чи тимчасові виділення, які не входять до оцінки розробника. Причина OOMKilled вказує на застосування пам’яті під час виконання, тож обмеження пам’яті безпосередньо релевантне, але сліпе його підвищення може перемістити тиск на ноду. Порівняйте спостережувані піки з обмеженням, потім вирішіть, чи підвищувати обмеження, чи зменшувати використання пам’яті застосунком, чи змінювати рівень паралелізму. Ключ у тому, що запити впливають на планування, тоді як цей симптом походить від межі пам’яті під час виконання.
Запитання 2: Под залишається у стані Pending з `0/3 nodes are available: 3 Insufficient cpu`. Под запитує два ядра CPU, а кожна нода має чотири ядра, але вже запускає кілька робочих навантажень. Які ваші практичні варіанти?
Планувальник не може знайти ноду з двома незарезервованими доступними для виділення ядрами CPU, тож вам потрібно змінити запит чи доступну ємність. Ви можете зменшити запит, якщо докази показують, що робоче навантаження не потребує двох зарезервованих ядер, перемістити чи зменшити масштаб інших робочих навантажень або додати ємність ноди. Зміна лише обмеження CPU не виправить цей стан Pending, бо планувальник вміщує запити. Огляньте виділені ресурси через kubectl describe node, щоб побачити, скільки CPU вже зарезервовано.
Запитання 3: Деплоймент має п'ять реплік без запитів чи обмежень ресурсів. Під час тиску на пам'ять ноди ці поди витісняються раніше за сусідні сервіси. Чому Kubernetes сприйняв їх як легших кандидатів на витіснення?
Поди без запитів та без обмежень — це BestEffort, якщо тільки значення за замовчуванням простору імен не змінили збережену спеку. Поди BestEffort не мають оголошеного резервування, тож будь-яке використання пам’яті перевищує їхній запит, що дорівнює нулю. Під час тиску логіка витіснення kubelet дає слабший захист подам, що перевищують запити, особливо тим, що не мають резервування. Виправлення — встановити реалістичні запити, а для критичних робочих навантажень розглянути, чи доречний QoS Guaranteed або ретельно розмірений Burstable.
Запитання 4: Простір імен має LimitRange зі значеннями CPU та пам'яті за замовчуванням. Розробник створює под без ресурсів, а потім бачить запити та обмеження на збереженому поді. Що сталося, і чому це може допомогти з ResourceQuota?
Плагін допуску LimitRange застосував значення за замовчуванням простору імен до контейнера, перш ніж об’єкт було збережено. Це означає, що маніфест, який написав розробник, — не вся історія; збережений под включає значення ресурсів, керовані політикою. Це допомагає ResourceQuota, бо обчислювальним квотам потрібні значення запитів та обмежень, щоб послідовно рахувати використання ресурсів. Правильні діагностичні команди — це kubectl get pod ... -o jsonpath для збережених ресурсів та kubectl describe limitrange для значень за замовчуванням простору імен.
Запитання 5: Сервіс у стані Running і ніколи не перезапускається, але затримка різко зростає під навантаженням після того, як обмеження CPU було знижено. Запит пода залишився тим самим. Який механізм ресурсів найбільш підозрілий?
Дроселювання CPU — це перший механізм ресурсів для дослідження, бо обмеження CPU сповільнюють контейнер, а не вбивають його. Незмінений запит означає, що резервування для планування не змінилося, тож под усе ще може потрапляти на ті самі ноди. Зниження обмеження зменшило максимальний процесорний час, який контейнер може спожити під час сплесків, що може проявитися як затримка чи нижча пропускна здатність. Підтвердьте метриками використання CPU та дроселювання, якщо вони доступні, потім вирішіть, чи підвищувати обмеження, налаштовувати репліки чи оптимізувати застосунок.
Запитання 6: Новий под одразу відхиляється з помилкою квоти, але в кластері є ноди з вільною пам'яттю. Чому планувальник — не той компонент, який налагоджувати першим?
Об’єкт було відхилено під час допуску, тож планувальник так і не отримав под для розміщення. ResourceQuota обмежена простором імен і може відхилити под, коли додавання його запитів чи обмежень перевищило б бюджет простору імен. Вільна пам’ять ноди не перекриває квоту простору імен, бо квоти захищають межі виділення перед плануванням. Огляньте kubectl describe resourcequota, потім зменшіть запит пода, видаліть інші робочі навантаження простору імен або запросіть зміну квоти.
Практична вправа
Розділ «Практична вправа»Ця вправа використовує невеликі поди, тож її можна запустити в локальному навчальному кластері, але спостереження ті самі, які ви використовуєте у більших середовищах. Ви створите под із явними ресурсами, спричините збій обмеження пам’яті, огляньте QoS, а потім попрактикуєте короткі команди, що розкривають запити, обмеження, виділення на ноді та значення за замовчуванням простору імен. Якщо у вашому кластері немає Metrics Server, частини з kubectl top необов’язкові, а решта вправи все одно навчає основної механіки.
Завдання 1: Створіть Под з явними запитами та обмеженнями
Розділ «Завдання 1: Створіть Под з явними запитами та обмеженнями»Створіть под, що запитує менше, ніж йому дозволено використовувати, потім огляньте збережені ресурси та клас QoS. Перш ніж застосовувати його, передбачте клас QoS з маніфесту: запити існують, обмеження існують, а значення не рівні. Це передбачення має привести вас до Burstable, якщо тільки політика простору імен не мутує об’єкт неочікуваним чином.
Розв'язок
cat << 'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: resource-demospec: containers: - name: app image: nginx resources: requests: memory: "64Mi" cpu: "50m" limits: memory: "128Mi" cpu: "100m"EOF
# Check QoS classkubectl get pod resource-demo -o jsonpath='{.status.qosClass}'echo
# Check resourceskubectl get pod resource-demo -o jsonpath='{.spec.containers[0].resources}'echoЗавдання 2: Спричиніть та огляньте контейнер OOMKilled
Розділ «Завдання 2: Спричиніть та огляньте контейнер OOMKilled»Створіть под, що навмисно намагається виділити більше пам’яті, ніж дозволяє його обмеження. Це не продакшен-патерн; це контрольована лабораторія для з’єднання обмеження пам’яті з останнім станом контейнера. Стягування образу може зайняти трохи часу, тож зачекайте на ініціалізацію, перш ніж перевіряти причину збою.
Розв'язок
cat << 'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: memory-hogspec: containers: - name: app image: polinux/stress command: ["stress"] args: ["--vm", "1", "--vm-bytes", "200M", "--vm-hang", "1"] resources: limits: memory: "100Mi"EOF
# Wait for pod initialization because image pull may take timekubectl wait --for=condition=Initialized pod/memory-hog --timeout=60s
# Allow time for the stress test to hit the memory limitsleep 10kubectl get pod memory-hog
# Check the previous container statekubectl describe pod memory-hog | grep -A3 "Last State"Завдання 3: Попрактикуйте швидкий огляд ресурсів
Розділ «Завдання 3: Попрактикуйте швидкий огляд ресурсів»Використовуйте короткі огляди, щоб з’єднати налаштування ресурсів зі станом пода та ноди. Ці команди навмисно повторювані, бо швидкість у CKAD походить зі знання, яке поле доводить яке твердження. Якщо команда повертає порожнє значення, вирішіть, чи под не має ресурсів, чи JSONPath неправильний, чи політика допуску змінила інше поле, ніж ви очікували.
Розв'язок
cat << 'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: drill1spec: containers: - name: nginx image: nginx resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "200m" memory: "256Mi"EOF
kubectl get pod drill1 -o jsonpath='{.spec.containers[0].resources}'echokubectl get pod drill1 -o jsonpath='{.status.qosClass}'echokubectl delete pod drill1Завдання 4: Порівняйте поди Guaranteed та Burstable
Розділ «Завдання 4: Порівняйте поди Guaranteed та Burstable»Створіть под, чиї запити дорівнюють обмеженням, і порівняйте його з першим подом цієї вправи. Мета — не стверджувати, що один клас QoS завжди кращий. Мета — побачити, як невелика зміна YAML змінює захист від витіснення та резервування планувальником. Guaranteed сильніший під тиском, тоді як Burstable часто ущільнюється ефективніше.
Розв'язок
cat << 'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: drill2spec: containers: - name: nginx image: nginx resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "100m" memory: "128Mi"EOF
kubectl get pod drill2 -o jsonpath='{.status.qosClass}'echokubectl delete pod drill2Завдання 5: Додайте ресурси до шаблону Deployment
Розділ «Завдання 5: Додайте ресурси до шаблону Deployment»Створіть Деплоймент із двома репліками й переконайтеся, що блок ресурсів живе під контейнером шаблону пода. Це завдання віддзеркалює патерн іспиту, де ви генеруєте чи редагуєте об’єкт-контролер, а потім оглядаєте створені поди. Важлива відмінність у тому, що зміна шаблону Деплойменту впливає на нові поди, створені з цього шаблону, а не на довільні старі поди з попередніх маніфестів.
Розв'язок
cat << 'EOF' | kubectl apply -f -apiVersion: apps/v1kind: Deploymentmetadata: name: drill4spec: replicas: 2 selector: matchLabels: app: drill4 template: metadata: labels: app: drill4 spec: containers: - name: nginx image: nginx resources: requests: cpu: "50m" memory: "64Mi" limits: cpu: "100m" memory: "128Mi"EOF
kubectl get pods -l app=drill4kubectl get deploy drill4 -o jsonpath='{.spec.template.spec.containers[0].resources}'echokubectl delete deploy drill4Завдання 6: Спостерігайте значення за замовчуванням простору імен з LimitRange
Розділ «Завдання 6: Спостерігайте значення за замовчуванням простору імен з LimitRange»Створіть простір імен із LimitRange, потім створіть под, що опускає ресурси. Збережений под має показати запити та обмеження за замовчуванням, навіть якщо команда створення пода їх не включала. Це завдання доводить, що допуск може мутувати об’єкт ще до того, як планувальник його побачить, — це той самий механізм, що допомагає ResourceQuota послідовно рахувати використання ресурсів.
Розв'язок
# Create namespace with LimitRangekubectl create namespace drill6
cat << 'EOF' | kubectl apply -n drill6 -f -apiVersion: v1kind: LimitRangemetadata: name: default-limitsspec: limits: - default: cpu: "200m" memory: "256Mi" defaultRequest: cpu: "100m" memory: "128Mi" type: ContainerEOF
# Create pod without resourceskubectl run drill6-pod --image=nginx -n drill6
# Check defaults were appliedkubectl get pod drill6-pod -n drill6 -o jsonpath='{.spec.containers[0].resources}'echo
# Cleanupkubectl delete namespace drill6Прибирання
Розділ «Прибирання»Видаліть усі поди, що залишилися з попередніх завдань, щоб простір імен був готовий до наступного модуля. Прибирання — частина вправи, бо лабораторії з ресурсами можуть залишати по собі збійні поди, і ці поди можуть заплутати пізніші огляди. Якщо ресурс не існує, бо ви вже його видалили, прапорець --ignore-not-found робить прибирання ідемпотентним.
Розв'язок
kubectl delete pod resource-demo memory-hog drill1 drill2 --ignore-not-foundkubectl delete deploy drill4 --ignore-not-foundkubectl delete namespace drill6 --ignore-not-foundКритерії успіху
Розділ «Критерії успіху»- Ви можете пояснити, чому
resource-demoє Burstable, виходячи зі значень його запиту та обмеження. - Ви можете знайти
OOMKilledу попередньому стані контейнера дляmemory-hog. - Ви можете оглянути збережені ресурси пода за допомогою JSONPath.
- Ви можете відрізнити результат QoS на рівні пода від блоку ресурсів на рівні контейнера.
- Ви можете ідентифікувати, де належать ресурси всередині шаблону пода Деплойменту.
- Ви можете показати, що значення за замовчуванням LimitRange були застосовані до пода, який опустив ресурси.
Джерела
Розділ «Джерела»- Kubernetes: Resource Management for Pods and Containers
- Kubernetes: Pod Quality of Service Classes
- Kubernetes: Node-pressure Eviction
- Kubernetes: Limit Ranges
- Kubernetes: Resource Quotas
- Kubernetes API Reference: LimitRange v1
- Kubernetes API Reference: ResourceQuota v1
- Kubernetes kubectl reference: describe
- Kubernetes kubectl reference: top
- Kubernetes: Assign CPU Resources to Containers and Pods
- Kubernetes: Assign Memory Resources to Containers and Pods
- Kubernetes: Configure Default Memory Requests and Limits for a Namespace
Наступний модуль
Розділ «Наступний модуль»Модуль 4.4: SecurityContexts — далі ви налаштуєте параметри безпеки пода й контейнера, а потім з’єднаєте ці засоби контролю з межами часу виконання, які ввели налаштування ресурсів тут.