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

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

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

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

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

  • Политика управления 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”

Сохраните созданный объект. 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 другие поды.