Задание ресурсов CPU для контейнеров и Pod'ов
На этой странице показывается, как настроить запрос CPU и лимит CPU для контейнера. Контейнер не сможет использовать больше ресурсов CPU, чем для него ограничено. Если в системе есть свободное время CPU, контейнеру гарантируется выдача запрошенных им ресурсов CPU.
Подготовка к работе
Вам нужен Kubernetes кластер и инструмент командной строки kubectl должен быть настроен на связь с вашим кластером. Если у вас ещё нет кластера, вы можете создать, его используя Minikube, или вы можете использовать одну из песочниц Kubernetes:
Чтобы проверить версию, введитеkubectl version
.
На кластере должен быть хотя бы 1 доступный для работы CPU, чтобы запускать учебные примеры.
Для некоторых шагов с этой страницы понадобится запущенный сервер метрик на вашем кластере. Если сервер метрик уже запущен, следующие шаги можно пропустить.
Если вы используете Minikube, выполните следующую команду, чтобы запустить сервер метрик:
minikube addons enable metrics-server
Проверим, работает ли сервер метрик (или другой провайдер API ресурсов метрик,
metrics.k8s.io
), выполните команду:
kubectl get apiservices
Если API ресурсов метрик доступно, в выводе будет присутствовать
ссылка на metrics.k8s.io
.
NAME
v1beta1.metrics.k8s.io
Создание пространства имён
Создадим Namespace, чтобы создаваемые в этом упражнении ресурсы были изолированы от остального кластера.
kubectl create namespace cpu-example
Установка запроса CPU и лимита CPU
Чтобы установить запрос CPU для контейнера, подключите поле resources:requests
в манифест ресурсов контейнера. Для установки ограничения по CPU подключите resources:limits
.
В этом упражнении мы создадим Pod, имеющий один контейнер. Зададим для контейнера запрос в 0.5 CPU и лимит в 1 CPU. Конфигурационный файл для такого Pod'а:
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr
image: vish/stress
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
args:
- -cpus
- "2"
Раздел args
конфигурационного файла содержит аргументы для контейнера в момент старта.
Аргумент -cpus "2"
говорит контейнеру попытаться использовать 2 CPU.
Создадим Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit.yaml --namespace=cpu-example
Удостоверимся, что Pod запущен:
kubectl get pod cpu-demo --namespace=cpu-example
Посмотрим детальную информацию о Pod'е:
kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
В выводе видно, что Pod имеет один контейнер с запросом в 500 милли-CPU и с ограничением в 1 CPU.
resources:
limits:
cpu: "1"
requests:
cpu: 500m
Запустим kubectl top
, чтобы получить метрики Pod'a:
kubectl top pod cpu-demo --namespace=cpu-example
В этом варианте вывода Pod'ом использовано 974 милли-CPU, что лишь чуть меньше заданного в конфигурации Pod'a ограничения в 1 CPU.
NAME CPU(cores) MEMORY(bytes)
cpu-demo 974m <something>
Напомним, что установкой параметра -cpu "2"
для контейнера было задано попытаться использовать 2 CPU,
однако в конфигурации присутствует ограничение всего в 1 CPU. Использование контейнером CPU было отрегулировано,
поскольку он попытался занять больше ресурсов, чем ему позволено.
Заметка: Другое возможное объяснение для выделения менее 1.0 CPU в отсутствии на ноде достаточного количества свободных CPU ресурсов. Напомним, что в начальных условиях для этого упражнения было наличие у кластера хотя бы 1 CPU, доступного для использования. Если контейнер запущен на ноде, имеющей в своём распоряжении всего 1 CPU, контейнер не сможет использовать более 1 CPU независимо от заданных для него ограничений.
Удалим Pod:
kubectl delete pod cpu-demo --namespace=cpu-example
Единицы измерения CPU
Ресурсы CPU измеряются в CPU единицах. Один CPU, в Kubernetes, соответствует:
- 1 AWS vCPU
- 1 GCP Core
- 1 Azure vCore
- 1 гипертрединговое ядро на физическом процессоре Intel с Гипертредингом
Дробные значения возможны. Контейнер, запрашивающий 0.5 CPU, получит вполовину меньше ресурсов, чем контейнер, запрашивающий 1 CPU. Можно использовать окончание m для обозначения милли. Например, 100m CPU, 100 milliCPU и 0.1 CPU обозначают одно и то же. Точность выше 1m не поддерживается.
CPU всегда запрашивается в абсолютных величинах, не в относительных; 0.1 будет одинаковой частью от CPU для одноядерного, двухъядерного или 48-ядерного процессора.
Запрос ресурсов CPU больше доступного на ноде
Запросы и лимиты CPU устанавливаются для контейнеров, но также полезно рассматривать и Pod имеющим эти характеристики. Запросом CPU для Pod'а является сумма запросов CPU всех его контейнеров. Аналогично и лимит CPU для Pod'а - сумма всех ограничений CPU у его контейнеров.
Планирование Pod'а основано на запросах. Pod попадает в расписание запуска на ноде лишь в случае достаточного количества доступных ресурсов CPU на ноде, чтобы удовлетворить запрос CPU Pod'а.
В этом упражнении мы создадим Pod с запросом CPU, превышающим мощности любой ноды в вашем кластере. Ниже представлен конфигурационный файл для Pod'а с одним контейнером. Контейнер запрашивает 100 CPU, что почти наверняка превышет имеющиеся мощности любой ноды в кластере.
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo-2
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr-2
image: vish/stress
resources:
limits:
cpu: "100"
requests:
cpu: "100"
args:
- -cpus
- "2"
Создадим Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit-2.yaml --namespace=cpu-example
Проверим статус Pod'а:
kubectl get pod cpu-demo-2 --namespace=cpu-example
Вывод показывает Pending статус у Pod'а. То есть Pod не запланирован к запуску ни на одной ноде и будет оставаться в статусе Pending постоянно:
NAME READY STATUS RESTARTS AGE
cpu-demo-2 0/1 Pending 0 7m
Посмотрим подробную информацию о Pod'е, включающую в себя события:
kubectl describe pod cpu-demo-2 --namespace=cpu-example
В выводе отражено, что контейнер не может быть запланирован из-за нехватки ресурсов CPU на нодах:
Events:
Reason Message
------ -------
FailedScheduling No nodes are available that match all of the following predicates:: Insufficient cpu (3).
Удалим Pod:
kubectl delete pod cpu-demo-2 --namespace=cpu-example
Если ограничения на CPU не заданы
Если ограничения на использование контейнером CPU не установлены, возможны следующие варианты:
-
У контейнера отсутствует верхняя граница количества CPU доступных ему ресурсов. В таком случае он может занять все ресурсы CPU, доступные на ноде, на которой он запущен.
-
Контейнер запущен в пространстве имён, в котором задана стандартная величина ограничения ресурсов CPU. Тогда контейнеру автоматически присваивается это ограничение. Администраторы кластера могут использовать LimitRange, чтобы задать стандартную величину ограничения ресурсов CPU.
Мотивация для использования запросов и лимитов CPU
Вы можете распоряжаться ресурсами CPU на нодах вашего кластера эффективнее, если для запущенных контейнеров установлены запросы и ограничения на использование ресурсов CPU. Задание небольшого запроса CPU даёт Pod'у хорошие шансы быть запланированным. Установка лимита на ресурсы CPU, большего, чем запрос, позволяет достичь 2 вещей:
- При увеличении нагрузки Pod может задействовать дополнительные ресурсы CPU.
- Количество ресурсов CPU, которые Pod может задействовать при повышении нагрузки, ограничено некоторой разумной величиной.
Очистка
Удалим созданное для этого упражнения пространство имён:
kubectl delete namespace cpu-example
Что дальше
Для разработчиков приложений
Для администраторов кластера
-
Configure Default Memory Requests and Limits for a Namespace
-
Configure Minimum and Maximum Memory Constraints for a Namespace
-
Configure Minimum and Maximum CPU Constraints for a Namespace