Лимиты задаются для каждого контейнера, сумма этих лимитов задаёт лимит пода
200m — это 200 милиядер, т.е. 1/5 времени одного ядра
apiVersion: v1 kind: Pod metadata: name: requests-pod spec: containers: - image: busybox command: ["dd", "if=/dev/zero", "of=/dev/null"] name: main resources: requests: cpu: 200m memory: 10Mi
MostRequestedPriority — при настройке этой опции на планировщике, поды будут назначаться узлам по требованиям памяти и процессора, что позволит сократить затраты на инфраструктуру, особенно это выгодно в облаке, где оплата ведётся по израсходованным ресурсам
Чтобы проверить, какими ресурсами мы располагаем
kubectl describe nodes ... Capacity: cpu: 2 ephemeral-storage: 16888216Ki hugepages-2Mi: 0 memory: 2038624Ki pods: 110 Allocatable: cpu: 2 ephemeral-storage: 15564179840 hugepages-2Mi: 0 memory: 1936224Ki pods: 110 ...
Создадим ещё 1 модуль
apiVersion: v1 kind: Pod metadata: name: requests-pod-2 spec: containers: - image: busybox command: ["dd", "if=/dev/zero", "of=/dev/null"] name: main resources: requests: cpu: 800m memory: 20Mi
Таким образом, мы использовали 1 ядро, попробуем назначить ещё 1 целое ядро, так как у нас их 2
kubectl run requests-3 --image=busybox --restart Never --requests='cpu=1,memory=20' -- dd if=/dev/zero of=/dev/null
проверим
kubectl get po requests-3 NAME READY STATUS RESTARTS AGE requests-3 0/1 Pending 0 53s
Модуль не был назначен ни одному узлу, найдём причину
kubectl describe nodes Non-terminated Pods: (14 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE --------- ---- ------------ ---------- --------------- ------------- --- default requests-pod 200m (10%) 0 (0%) 10Mi (0%) 0 (0%) 14m default requests-pod-2 800m (40%) 0 (0%) 20Mi (1%) 0 (0%) 5m29s kube-system coredns-86c58d9df4-b44p4 100m (5%) 0 (0%) 70Mi (3%) 170Mi (8%) 4h31m kube-system coredns-86c58d9df4-z4lnv 100m (5%) 0 (0%) 70Mi (3%) 170Mi (8%) 4h31m kube-system default-http-backend-5ff9d456ff-ncwx8 20m (1%) 20m (1%) 30Mi (1%) 30Mi (1%) 4h31m kube-system etcd-minikube 0 (0%) 0 (0%) 0 (0%) 0 (0%) 4h31m kube-system kube-addon-manager-minikube 5m (0%) 0 (0%) 50Mi (2%) 0 (0%) 4h31m kube-system kube-apiserver-minikube 250m (12%) 0 (0%) 0 (0%) 0 (0%) 4h31m kube-system kube-controller-manager-minikube 200m (10%) 0 (0%) 0 (0%) 0 (0%) 4h31m kube-system kube-proxy-nqjf4 0 (0%) 0 (0%) 0 (0%) 0 (0%) 4h31m kube-system kube-scheduler-minikube 100m (5%) 0 (0%) 0 (0%) 0 (0%) 4h31m kube-system kubernetes-dashboard-ccc79bfc9-5qbfc 0 (0%) 0 (0%) 0 (0%) 0 (0%) 4h31m kube-system nginx-ingress-controller-7c66d668b-hjss6 0 (0%) 0 (0%) 0 (0%) 0 (0%) 4h31m kube-system storage-provisioner 0 (0%) 0 (0%) 0 (0%) 0 (0%) 4h31m Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 1775m (88%) 20m (1%) memory 250Mi (13%) 370Mi (19%) ephemeral-storage 0 (0%) 0 (0%)
У нас есть ещё системные модули, которым тоже нужен CPU, таким образом мы превысили лимит
Запросы на ЦП влияют, не только на назначение подов узлам, но и на то как свободное процессорное время будет распределяться между подами
Но так же действует принцип, если под простаивает, а другому поду требуется больше процессорного времени, то оно будет ему предоставлено, до тех пор, пока первый модуль не запросит его.
Так же можно создавать свой ресурс и распределять его при создании подов, например это могут быть ноды с GPU
Установка ресурсных запросов, позволяет предоставить модулю, минимальное количество ресурсов, но так же можно установить максимальный порог потребляемых ресурсов
Создадим контейнер, который не сможет потреблять более 1 ядра и 20М памяти
apiVersion: v1 kind: Pod metadata: name: limited-pod spec: containers: - image: busybox command: ["dd", "if=/dev/zero", "of=/dev/null"] name: main resources: limits: cpu: 1 memory: 20Mi
Не указывая ресурсные запросы, они будут равны ресурсным лимитам
Превышение лимитов
Когда процесс выйдет за пределы используемой памяти, он будет убит и перезапущен, в соответствии со своей политикой, время между перезапусками будет увеличиваться по 10 секунд, до 300.
Диагностируется просмотром describe или логов, в describe будет указана причина — OOMKilled
Проблема лимитов заключается в том что контейнер видит всю память узла и все ядра, таким образом приложение может расчитывать на больше памяти, чем ему выделено, например так часто делает java. Так же приложение может определить сколько потоков запускать по числу ядер.
Классы QoS модулей
- BestEffort — самый низкий приоритет
- Burstable
- Guaranteed — самый высокий
Так можно определять какие модули можо удалять, какие нет, при высоких нагрузках. Эти приоритеты назначаются на основе запрошенных ресурсов
BestEffort — назначается подам у которых нет запросов на ресурсы
Guarantedd — запросы на лимиты должны стаять на CPU и RAM, должны стоять для каждого контейнера в поде, лимит должен соответствовать запросу
Burstable — попадают сюда все оставшиеся контейнеры, и те у которых запросы не соответствуют лимитам
В команде kubectl describe pod в поле status — qosClass показан QoS
Таким образом поды будут удалять от меньшего приоритета к большему, если будет слишком высокая нагрузка
Модули с одинковым QoS — будет уничтожен тот кто использует больше ресурсов от запрошенных
LimitRange
Позволяет указывать минимальный и максимальный лимит для namespace и так же стандартные ресурсные запросы, для контейнеров, где не заданы запросы
apiVersion: v1 kind: LimitRange metadata: name: example spec: limits: - type: Pod min: cpu: 50m memory: 5Mi max: cpu: 1 memory: 1Gi - type: Container defaultRequest: cpu: 100m memory: 10Mi default: cpu: 200m memory: 100Mi min: cpu: 50m memory: 5Mi max: cpu: 1 memory: 1Gi maxLimitRequestRatio: cpu: 4 memory: 10 - type: PersistentVolumeClaim min: storage: 1Gi max: storage: 10Gi
Если попытаться создать модуль, который привышает лимиты
kubectl create -f pod-too-big.yaml The Pod "too-big" is invalid: spec.containers[0].resources.requests: Invalid value: "2": must be less than or equal to cpu limit
Создадим без лимитов и посмотрим применились ли лимиты из LimitRange
apiVersion: v1 kind: Pod metadata: name: kubia-manual spec: containers: - image: luksa/kubia name: kubia ports: - containerPort: 8080 protocol: TCP
kubectl describe po kubia-manual Limits: cpu: 200m memory: 100Mi Requests: cpu: 100m memory: 10Mi
Лимит ресурсов в namespace
Делается это при помощи ResourceQuota, лимит будет задан для всех контейнеров в namespace, это относится к памяти, процессору, дискам
apiVersion: v1 kind: ResourceQuota metadata: name: cpu-and-mem spec: hard: requests.cpu: 400m requests.memory: 200Mi limits.cpu: 600m limits.memory: 500Mi
Отличие от LimitRange состоит в том что применяется ко всему namespace а не к каждому модулю отдельно
Просмотерть можно при помощи
kubectl describe quota
ResourceQuota делает указание лимитов в подах обязательным
Лимитируем использование дискового пространства, для каждого типа, свой лимит
apiVersion: v1 kind: ResourceQuota metadata: name: storage spec: hard: requests.storage: 500Gi ssd.storageclass.storage.k8s.io/requests.storage: 300Gi standard.storageclass.storage.k8s.io/requests.storage: 1Ti
Лимитирование других ресурсов, служб, словарей, контроллеров репликации
apiVersion: v1 kind: ResourceQuota metadata: name: objects spec: hard: pods: 10 replicationcontrollers: 5 secrets: 10 configmaps: 10 persistentvolumeclaims: 5 services: 5 services.loadbalancers: 1 services.nodeports: 2 ssd.storageclass.storage.k8s.io/persistentvolumeclaims: 2
Так же есть возможность применять ResourceQuota только к подам с определённым статусом, BestEffort, NotBestEffort, Terminating и NotTerminating
0 Comment