Резервирование CPU в кластере

Резервирование (pinning) CPU для etcd в кластере можно настроить в графическом или программном интерфейсе.

Резервирование CPU приводит к уменьшению доступных (Allocatable) CPU на узле. Это можно увидеть на странице узла или если сделать describe узла (разделы Capacity и Allocatable). Само резервирование никак не лимитирует CPU, а лишь устанавливает “веса” (приоритизацию). Т.е. pod без лимита всегда сможет потреблять 100% CPU, если в этот момент никто другой не претендует на CPU. Так же Allocatable учитывается на этапе планирования pod с указанными реквестами: если по реквестам не хватит ресурсов, то pod не будет запущен или будут вытесняться менее приоритетные поды.

Обратите внимание Рекомендуем, чтобы в результате резервирования на узле должно остаться не менее 6 свободных CPU.

Резервирование CPU в графическом интерфейсе

В интерфейсе кластера перейдите в раздел “Конфигурация узлов”, создайте новый объект NCI. Выберите раздел “Kubelet”. В селекторе узлов выберите ключ “node-role.kubernetes.io/control-plane”.

Скриншот

ncikubelet

Заполните поля:

  • Политика управления CPU (cpuManagerPolicy) со значением static. Это значение говорит kubelet, что можно привязывать поды к зарезервированным CPU.
  • Перечень резервируемых CPU (reservedSystemCPUs) в виде диапазона или через запятую, например, “0-1”.

В блоке “Feature Gates” укажите параметры в формате ключ-значение:

  • CPUManager: true
  • CPUManagerPolicyOptions: true
  • CPUManagerPolicyAlphaOptions: true
  • CPUManagerPolicyBetaOptions: true

В блоке “Параметры управления CPU” (cpuManagerPolicyOptions) укажите параметры в формате ключ-значение:

  • full-pcpus-only: “true”
  • distribute-cpus-across-numa: “true”
  • align-by-socket: “true”
Скриншот

ncikubelet-pinningcpu

Сохраните созданный объект. Kubelet будет перезапущен автоматически.

Резервирование CPU в программном интерфейсе

Подключитесь к кластеру из консоли.

Создайте манифест NCI
apiVersion: node.shturval.tech/v1beta2
kind: NodeConfigItem
metadata:
  name: cpu-pinning-test
spec:
  kubelet:
    cpuManagerPolicy: static
    featureGates:
      CPUManager: true
      CPUManagerPolicyOptions: true
      CPUManagerPolicyAlphaOptions: true
      CPUManagerPolicyBetaOptions: true 
    cpuManagerPolicyOptions:
      align-by-socket: "true"
      distribute-cpus-across-numa: "true"
      full-pcpus-only: "true"
    reservedSystemCPUs: 0-1
  nodeconfigselector:
    node-role.kubernetes.io/control-plane: ""
  priority: 100

Примените созданный манифест.

Команда
kubectl apply -f cpu-pinning-test.yaml

Проверка состояния резервирования CPU

Для проверки состояния Kubelet CPU Manager.

Команда
cat /var/lib/kubelet/cpu_manager_state
Пример результата команды
{"policyName":"static","defaultCpuSet":"0-1,4-7","entries":{"3f6868ef501db41abc9cc55c40ab1020":{"etcd":"2-3"}},"checksum":4106740397}

Здесь можно увидеть, что:

  • используется политика static
  • по умолчанию все поды размещаются в распределенном пуле процессоров 0-1,4-7
  • для пода etcd выделены CPU 2-3

В случае успешного резервирования CPU в логе kubelet будет сообщение.

Сообщение
policy_static.go:175] "Reserved CPUs not available for exclusive assignment" reservedSize=2 reserved="0-1" reservedPhysicalCPUs="0-1"

Обратите внимание! Есть вероятность, что на виртуальных машинах не заработает выравнивание по сокетам, если выставить больше, чем 1 сокет на VM, так как нет возможности повлиять на количество NUMA-node. В таком случае необходимо удалить параметр: align-by-socket: “true”.

Пример ошибки
I0613 19:29:30.525539    5408 cpu_manager.go:172] "Detected CPU topology" topology={"NumCPUs":8,"NumCores":8,"NumSockets":2,"NumNUMANodes":1,"CPUDetails":{"0":
{"NUMANodeID":0,"SocketID":0,"CoreID":0}
,"1":{"NUMANodeID":0,"SocketID":0,"CoreID":1},"2":{"NUMANodeID":0,"SocketID":0,"CoreID":2},"3":{"NUMANodeID":0,"SocketID":0,"CoreID":3},"4":{"NUMANodeID":0,"SocketID":1,"CoreID":4},"5":{"NUMANodeID":0,"SocketID":1,"CoreID":5},"6":{"NUMANodeID":0,"SocketID":1,"CoreID":6},"7":{"NUMANodeID":0,"SocketID":1,"CoreID":7}}}
июн 13 19:29:30 shturval-mycluster-cpu-master-qc2rv kubelet[5408]: E0613 19:29:30.525580    5408 container_manager_linux.go:329] "Failed to initialize cpu manager" err="new static policy error: Align by socket is not compatible with hardware where number of sockets are more than number of NUMA"
июн 13 19:29:30 shturval-mycluster-cpu-master-qc2rv kubelet[5408]: E0613 19:29:30.525610    5408 run.go:74] "command failed" err="failed to run Kubelet: new static policy error: Align by socket is not compatible with hardware where number of sockets are more than number of NUMA"

Условия использования зарезервированных ресурсов для подов

Резервирование CPU приводит к тому, что никакие поды не будут размещаться на выделенных под резервирование CPU выбранных узлов. Исключение представляют те поды, у которых выполняются все условия использования гарантированных ресурсов:

  • должны присутствовать как requests и limits;
  • requests и limits по CPU должны быть целыми числами;
  • requests и limits должны совпадать.
Пример
spec:
  containers:
    - name: etcd
      resources:
        limits:
          memory: "500Mi"
          cpu: "2"
          example.com/device: "1"
        requests:
          memory: "500Mi"
          cpu: "2"
          example.com/device: "1"

Если все условия выполнены, то после запуска пода в статусе будет указан тип QoS Class: Guaranteed.

Обратите внимание! На резервируемых процессорах в кластере могли быть зарезервированы/запущены поды до резервирования CPU. Убедитесь, что узлы перезапустились после применения настроек Kubelet. Резервирование CPU не означает, что на этих ресурсах не будут исполняться процессы ОС. Это гарантирует, что kubelet не будет размещать на зарезервированных CPU другие поды.

×