При распределении подов по нодам kube-scheduler проверяет requests и limits для контейнеров и текущую емкость нод. Это позволяет оптимально распределить поды по нодам для удовлетворения их требований и не допустить перегрузки нод. Повсеместное использование requests и limits для контейнеров является одной из лучших практик администрирования кластера Kubernetes.
Requests и limits
Если нода, на котором работает под, имеет достаточно доступных ресурсов, контейнер может использовать больше ресурсов, чем указано в request
на этот ресурс. Однако контейнеру не разрешается использовать больше, чем его limit
ресурсов.
Например, если вы задали для контейнера memory
запрос на 256 Мбайт памяти, и этот контейнер находится в поде, запланированном для узла с 8 ГБ memory
и без других подов, то контейнер может попытаться использовать больше оперативной памяти.
Если вы установите ограничение памяти в 4 ГБ для этого контейнера, kubelet применит это ограничение. Далее исполняющая среда запретит контейнеру использовать больше, чем настроенный лимит ресурсов.
В кластерах Kubernetes от Linx Cloud для запускаемых контейнеров без указанных requests и limits применяются следующие значения по умолчанию:
- Requests: 100m / 64Mb
- Limits: 500m / 512Mb
Например, когда процесс в контейнере пытается использовать больше допустимого объема памяти, ядро системы завершает процесс, который пытался выделить, с ошибкой нехватки памяти (OOM).
Ограничения могут быть реализованы двумя способами:
- Реактивно — система вмешивается, как только обнаруживает нарушение.
- Принудительно — система предотвращает превышение лимита контейнером. В разных средах могут быть разные способы реализации одних и тех же ограничений.
Limits и requests для CPU измеряются в единицах cpu. Один cpu равен одному vCPU/ядру. Для оперативной памяти (memory) requests и limits указываются в байтах. Используйте следующие значения:
- Число в байтах: 1073741824
- Целые числа с указанием суффикса: E, P, T, G, M, k, m. Например, 64M, 2G.
- Эквиваленты степени двойки: Ei, Pi, Ti, Gi, Mi, Ki. Например, 128Mi, 1Gi.
В примере ниже, под состоит из одного контейнера. Контейнеру указан request
в 0.25 cpu и 128Mi памяти. При этом, из-за указанных limits
, контейнер не может использовать более чем 0.5 cpu и 256Mi памяти.
1apiVersion: v1
2kind: Pod
3metadata:
4 name: nginx
5spec:
6 containers:
7 - name: app
8 image: nginx
9 resources:
10 requests:
11 memory: "128Mi"
12 cpu: "250m"
13 limits:
14 memory: "256Mi"
15 cpu: "500m"
Назначение ресурсов CPU
Подготовка к работе
Для начала работы понадобится кластер Kubernetes и инструмент командной строки kubectl, который настроен на связь с вашим кластером. Если у вас еще нет кластера, вы можете создать его на платформе.
Чтобы проверить версию Kubernetes, введите:
kubectl version
На кластере должен быть хотя бы один доступный для работы CPU, чтобы запускать учебные примеры.
Далее понадобится запущенный сервер метрик на вашем кластере. Если сервер метрик уже запущен, следующие шаги можно пропустить.
Проверьте, работает ли сервер метрик, выполнив команду:
kubectl get apiservices
Если API ресурсов метрик доступно, в выводе будет присутствовать ссылка на metrics.k8s.io:
NAME
v1beta1.metrics.k8s.io
Создание пространства имен
Создайте Namespace, чтобы создаваемые ресурсы были изолированы от остального кластера:
kubectl create namespace cpu-example
Установка запроса и лимита CPU
Чтобы установить запрос CPU для контейнера, добавьте поле resources:requests
в манифест ресурсов контейнера. Для установки ограничения по CPU добавьте resources:limits
.
Ниже мы создадим под, имеющий один контейнер. Затем зададим для контейнера запрос в 0.5 CPU и лимит в 1 CPU. Так же укажем запросы и лимиты для памяти в 128Mi и 256Mi соответственно. Конфигурационный файл для такого пода:
1apiVersion: v1
2kind: Pod
3metadata:
4 name: cpu-demo
5 namespace: cpu-example
6spec:
7 containers:
8 - name: cpu-demo-ctr
9 image: vish/stress
10 resources:
11 limits:
12 cpu: "1"
13 memory: "256Mi"
14 requests:
15 cpu: "0.5"
16 memory: "128Mi"
17 args:
18 - -cpus
19 - "2"
args
— содержит аргументы для контейнера в момент старта. -cpus "2"
— аргумент, который говорит контейнеру попытаться использовать 2 CPU.
Создайте под:
kubectl apply -f cpu-request-limit.yaml --namespace=cpu-example
Удостоверимся, что под запущен:
kubectl get pod cpu-demo --namespace=cpu-example
Посмотрим детальную информацию о поде:
kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
В выводе видно, что под имеет один контейнер с запросом в 500 милли-CPU / 128Mi и с ограничением в 1 CPU / 256Mi.
1resources:
2 limits:
3 cpu: "1"
4 memory: "256Mi"
5 requests:
6 cpu: "0.5"
7 memory: "128Mi"
Запустим kubectl top, чтобы получить метрики пода:
kubectl top pod cpu-demo --namespace=cpu-example
В этом варианте вывода пода использовано 914 милли-CPU, что лишь чуть меньше заданного в конфигурации пода ограничения в 1 CPU.
NAME CPU(cores) MEMORY(bytes)
cpu-demo 914m 0Mi
Напомним, что установкой параметра -cpu «2» для контейнера было задано попытаться использовать 2 CPU, однако в конфигурации присутствует ограничение всего в 1 CPU. Использование контейнером CPU было отрегулировано, поскольку он попытался занять больше ресурсов, чем ему позволено.
Удалите под командой:
kubectl delete pod cpu-demo --namespace=cpu-example
Если ограничения на использование контейнером CPU не установлены, возможны следующие варианты:
- У контейнера отсутствует верхняя граница количества CPU доступных ему ресурсов. В таком случае он может занять все ресурсы CPU, доступные на ноде, на которой он запущен.
- Контейнер запущен в пространстве имен, в котором задана стандартная величина ограничения ресурсов CPU. Тогда контейнеру автоматически присваивается это ограничение. Администраторы кластера могут использовать LimitRange, чтобы задать стандартную величину ограничения ресурсов CPU.
Можно эффективнее распоряжаться ресурсами CPU на нодах вашего кластера, если для запущенных контейнеров установить запросы и ограничения на использование ресурсов CPU. Если установить лимит больше, чем запрос, то:
- При увеличении нагрузки, под может задействовать дополнительные ресурсы CPU;
- Количество ресурсов CPU, которые Pod может задействовать при повышении нагрузки, будет ограничено разумной величиной.
Очистка
Удилите созданное пространство имен командой:
kubectl delete namespace cpu-example