Kubernetes распределение вычислительных ресурсов

Лимиты задаются для каждого контейнера, сумма этих лимитов задаёт лимит пода

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

 

 

K8S

Related Articles

0 Comment

Leave a Comment

Ваш адрес email не будет опубликован.