Зміна розміру CPU та memory, призначених контейнерам
Kubernetes v1.33 [beta]
(стандартно увімкнено: true)Ця сторінка пояснює як змінити запити та обмеження ресурсів CPU та памʼяті повʼязані з контейнером без перестворення Podʼу.
Зазвичай, зміна ресурсів Podʼа вимагає вилучення наявного Podʼа та створення його заміни, що виконується контролером робочого навантаження. Зміна розміру Podʼа на місці дозволяє змінювати виділені його контейнерам CPU/памʼять уникаючи потенційної перерви в роботі застосунку.
Ключові концепції:
- Бажані ресурси: Поле
spec.containers[*].resources
контейнера представляє бажані ресурси і є змінюваним для значень CPU та memory. - Поточні ресурси: Поле
status.containerStatuses[*].resources
показує поточно налаштовані ресурси для запуску контейнера. Для контейнерів, що не були запущені воно показує ресурси виділені для наступного запуску контейнера. - Запуск зміни розміру: Ви можете запитати зміну розміру оновлюючи відповідні значення
requests
таlimits
в специфікації Podʼа. Це, як правило, робиться з використаннямkubectl patch
,kubectl apply
абоkubectl edit
для Podʼа залучаючи субресурсresize
. Коли бажаний ресурс не збігається з виділеними ресурсами, Kubelet намагатиметься змінити розмір контейнера. - Виділені ресурси (Advanced): Поле
status.containerStatuses[*].allocatedResources
відстежує значення ресурсів, що були підтверджені Kubelet, переважно використовується для внутрішньої логіки планування. Для більшості потреб моніторингу та валідації зосереджуйтесь наstatus.containerStatuses[*].resources
.
Якщо у вузлі є podʼи з очікуваною або незавершеною зміною розміру (див Статус Pod Resize нижче), планувальник буде використовувати максимальні запити на бажані ресурси контейнера, запити виділення та запити поточних ресурсів зі статусу для прийняття рішення.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж 1.33.Для перевірки версії введіть kubectl version
.
Має бути увімкнено функціональну можливість InPlacePodVerticalScaling
для вашої панелі управління і для всіх вузлів вашого кластера.
Версія клієнта kubectl
має бути принаймні v1.32 для використання прапорця --subresource=resize
.
Статус Pod resize
Kubelet оновлює умови статусу Pod, щоб вказати стан запиту на зміну розміру:
type: PodResizePending
: Kubelet не в змозі негайно виконати запит. Полеmessage
надає пояснення чому.reason: Infeasible
: Запитана зміна розміру є неможливою на поточному вузлі (наприклад, запитано ресурсів більше ніж є на вузлі).reason: Deferred
: Запитана зміна ресурсу зараз є неможливою, але може стати можливою згодом (наприклад, інший pod буде вилучено). Kubelet спробує змінити розмір.
type: PodResizeInProgress
: Kubelet прийняв зміну розміру та розподілив ресурси, але зміни все ще застосовуються. Зазвичай це швидко, але може зайняти більше часу залежно від типу ресурсу та поведінки під час виконання. Будь-які помилки під час активації повідомляються в поліmessage
(разом зreason: Error
).
Політики зміни розміру контейнерів
Ви можете вказати чи потрібно перезапускати контейнер під час зміни розміру за допомогою поля resizePolicy
в специфікації контейнера. Це дозволяє докладний контроль за типами ресурсів (CPU чи memory).
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired
- resourceName: memory
restartPolicy: RestartContainer
NotRequired
: (типово) застосовувати зміну ресурсів без перезапуску контейнера.RestartContainer
: перезапускати контейнер під час зміни ресурсів. Це часто необхідно для зміни memory оскільки багато застосунків та середовищ виконання не можуть підлаштовуватись до динамічної зміни виділення памʼяті.
Якщо resizePolicy[*].restartPolicy
не вказано для ресурсу, типовим значенням буде NotRequired
.
Примітка:
Якщо загальний параметр PodʼаrestartPolicy
має значення Never
, тоді параметр resizePolicy
кожного контейнера має бути NotRequired
для всіх ресурсів. Ви не зможете налаштовувати зміну ресурсів, що вимагають перезапуску в таких PodʼахПриклад сценарію:
Уявіть контейнер з налаштованими restartPolicy: NotRequired
для CPU та restartPolicy: RestartContainer
для memory.
- Якщо тільки ресурс CPU буде змінено, розмір контейнера буде змінено на місці.
- Якщо тільки ресурс memory буде змінено, контейнер буде перезапущено.
- Якщо обидва ресурси CPU та memory будуть змінені одночасно, контейнер буде перезапущено (через правило перезапуску для ресурсу memory).
Обмеження
Для Kubernetes 1.33 зміна розміру ресурсів podʼа на місці має наступні обмеження:
- Типи ресурсів: Тільки ресурси CPU та memory можуть змінювати розмір.
- Зменшення memory: Ліміт memory не може бути зменшений якщо
resizePolicy
для памʼяті єRestartContainer
. Запит memory може бути в цілому зменшений. - Клас QoS: Оригінальний клас Quality of Service (QoS) Podʼа (Guaranteed, Burstable або BestEffort) визначається під час створення і не може бути змінений під час зміни розміру. Зміна значень розміру ресурсів все ще має дотримуватись правил оригінальних класів QoS:
- Guaranteed: Запити мають продовжувати дорівнювати лімітам як для CPU, так і для memory після зміни розміру.
- Burstable: Запити та ліміти не можуть бути тотожними як для CPU, так і для memory одночасно (оскільки це призведе до їх зміни до Guaranteed).
- BestEffort: Вимоги до ресурсів (
requests
чиlimits
) не можуть бути додані (оскільки це призведе до зміни до Burstable або Guaranteed).
- Типи контейнерів: Контейнери init, що не перезапускаються, та ефемерні контейнери не можуть змінювати розмір. Контейнери sidecar можуть змінювати розмір.
- Вилучення ресурсів: Після встановлення запити та ліміти ресурсів не можуть бути вилучені; їх можна тільки змінити іншими значеннями.
- Операційна система: Podʼи Windows не підтримують зміну розміру ресурсів на місці.
- Політики Node: Podʼи, які керуються статичними політиками менеджера CPU та Memory не можуть змінювати розмір на місці.
- Swap: Podʼи, що використовують swap-памʼять, не можуть змінювати розмір запитів памʼять якщо
resizePolicy
для memory не встановлено уRestartContainer
.
Ці обмеження можуть бути послаблені в наступних версіях Kubernetes.
Приклад 1: Зміна розміру CPU без перезапуску
Спочатку, створіть Pod створений для зміни розміру CPU на місці та такий що вимагає перезапуску під час зміни memory.
apiVersion: v1
kind: Pod
metadata:
name: resize-demo
spec:
containers:
- name: pause
image: registry.k8s.io/pause:3.8
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired # Це типове значення, вказане тут явно
- resourceName: memory
restartPolicy: RestartContainer
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Створіть Pod:
kubectl create -f pod-resize.yaml
Цей Pod запускається з класом Guaranteed QoS. Перевірте його початковий стан:
# Почекайте трохи доки pod запуститься
kubectl get pod resize-demo --output=yaml
Погляньте на spec.containers[0].resources
та status.containerStatuses[0].resources
. Вони мають відповідати маніфесту (700m CPU, 200Mi memory). Зверніть увагу на status.containerStatuses[0].restartCount
(має бути 0).
Тепер збільште запит та ліміт CPU до 800m
. Використовуйте kubectl patch
з аргументом командного рядка --subresource resize
.
kubectl patch pod resize-demo --subresource resize --patch \
'{"spec":{"containers":[{"name":"pause", "resources":{"requests":{"cpu":"800m"}, "limits":{"cpu":"800m"}}}]}}'
# Альтерантивні методиs:
# kubectl -n qos-example edit pod resize-demo --subresource resize
# kubectl -n qos-example apply -f <updated-manifest> --subresource resize
Примітка:
Для використання аргументу командного рядка--subresource resize
у вас має бути версія клієнта kubectl
не менша ніж v1.32.0.Перевірте стан podʼа після накладання латки:
kubectl get pod resize-demo --output=yaml --namespace=qos-example
Ви мажте побачити:
spec.containers[0].resources
тепер показуєcpu: 800m
.status.containerStatuses[0].resources
також показуєcpu: 800m
, що означає, що зміна розміру на вузлі відбулась.status.containerStatuses[0].restartCount
залишається0
, оскільки CPUresizePolicy
булоNotRequired
.
Приклад 2: Зміна розміру memory без перезапуску
Тепер змінимо розмір memory в тому ж поді збільшивши її до 300Mi
. Оскільки memory resizePolicy
має значення RestartContainer
, контейнер має перезапуститись.
kubectl patch pod resize-demo --subresource resize --patch \
'{"spec":{"containers":[{"name":"pause", "resources":{"requests":{"memory":"300Mi"}, "limits":{"memory":"300Mi"}}}]}}'
Перевірте стан podʼа невдовзі після застосування латки:
kubectl get pod resize-demo --output=yaml
Ви маєте побачити:
spec.containers[0].resources
показуєmemory: 300Mi
.status.containerStatuses[0].resources
також показуєmemory: 300Mi
.status.containerStatuses[0].restartCount
збільшився до1
(або більше, якщо до цього вже відбувались перезапуски), що вказує на те, що контейнер було перезапущено після застосування зміни розміру memory.
Розвʼязання проблем: Неможливий запит на зміну розміру
Далі, спробуємо запитати якесь неможливе значення CPU, наприклад 1000 цілих ядер (записується як "1000"
, в той час, коли йдеться про міліядра це — "1000m"
), що очевидно перевищує можливості вузла.
# Спроба застосувати латку з запитом явно більшої кількістю CPU
kubectl patch pod resize-demo --subresource resize --patch \
'{"spec":{"containers":[{"name":"pause", "resources":{"requests":{"cpu":"1000"}, "limits":{"cpu":"1000"}}}]}}'
Запитайте інформацію Podʼа:
kubectl get pod resize-demo --output=yaml
Ви побачите зміни, що сповіщають про проблему:
- Поле
spec.containers[0].resources
показує бажаний стан (cpu: "1000"
). - Стан з
type: PodResizePending
таreason: Infeasible
було додано до Pod. - Поле
message
буде містити пояснення (Node didn't have enough capacity: cpu, requested: 800000, capacity: ...
) - Найважливіше,
status.containerStatuses[0].resources
буде все ще показувати попередні значення (cpu: 800m
,memory: 300Mi
), тому що неможлива зміна розміру не була застосована Kubelet. - Поле
restartCount
не зміниться через невдалу спробу.
Щоб виправити це, вам потрібно застосувати латку до podʼа з прийнятними параметрами.
Очищення
Видаліть ваш pod:
kubectl delete pod resize-demo