Подробный гайд: Настройка CPU-пиннинга для KVM в Astra Linux 1.8
Примечание:
- Astra Linux 1.8 основана на Debian 11/12. Все утилиты
libvirt,qemu-kvmиsystemdработают по стандартам Debian, поэтому гайд совместим и с другими deb-based дистрибутивами. Для версий Special Edition (SE) учитывайте модуль мандатного контроля доступаParsec(обычно не мешает работе libvirt).
Что такое CPU-пиннинг и зачем он нужен
CPU-пиннинг (привязка vCPU к физическим ядрам/потокам) исключает миграцию задач планировщиком ядра Linux между ядрами.
Это:
- Снижает задержки (latency) и jitter
- Уменьшает кэш-промахи L1/L2/L3
- Повышает производительность ВМ с реальным временем, СУБД, сетевыми функциями (DPDK, OVS)
- Гарантирует предсказуемое распределение ресурсов
Важно:
Пиннинг применяется только при старте ВМ. Динамическое изменение требует перезапуска.
1. Подготовка системы
# Обновить пакеты
sudo apt update && sudo apt upgrade -y
# Установить необходимые компоненты (если ещё не стоят)
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst
# Убедиться, что libvirt работает
sudo systemctl enable --now libvirtd
2. Анализ топологии CPU
Перед пиннингом нужно понять, как физически расположены ядра, потоки и NUMA-узлы.
# Подробная таблица ядер, потоков, сокетов и NUMA
lscpu -e
# Визуальная схема (установить, если нет)
sudo apt install -y hwloc-nox
hwloc-ls --output-format png > cpu_topology.png
# Проверка NUMA
numactl --hardware
Пример вывода lscpu -e:
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ
0 0 0 0 0:0:0:0 yes 3600.0000 800.0000
1 0 0 0 0:0:0:0 yes 3600.0000 800.0000
2 0 0 1 1:1:1:0 yes 3600.0000 800.0000
3 0 0 1 1:1:1:0 yes 3600.0000 800.0000
...
CPU= логический ID (используется вcpuset)CORE= физическое ядро- Потоки с одинаковым
COREно разнымCPU— это Hyper-Threading / SMT.
Рекомендация:
- Для low-latency избегайте привязки к SMT-соседям (пиньте только чётные или только нечётные CPU, либо отключите HT в BIOS).
3. Изоляция ядер на хосте (рекомендуется)
Чтобы хост-ОС и фоновые процессы не использовали выделенные под ВМ ядра, их нужно изолировать.
Вариант A: isolcpus (проверенный, простой)
sudo nano /etc/default/grub
Найти строку GRUB_CMDLINE_LINUX_DEFAULT и добавить:
isolcpus=2,3,4,5 nohz_full=2,3,4,5 rcu_nocbs=2,3,4,5
Замените
2,3,4,5на нужные логические CPU изlscpu -e. Не изолируйте CPU 0 и 1 (оставьте под хост/IRQ).
Применить и перезагрузить:
sudo update-grub
sudo reboot
Вариант B: systemd/cgroups v2 (современный)
sudo systemctl set-property system.slice AllowedCPUs=0,1
sudo systemctl set-property user.slice AllowedCPUs=0,1
Подходит, если вы не хотите править GRUB. Требует перезапуска сервисов.
Проверка изоляции:
cat /sys/devices/system/cpu/isolated
# Должно вывести: 2,3,4,5
4. Настройка CPU-пиннинга в libvirt
Шаг 1: Открыть конфигурацию ВМ
virsh edit <имя_ВМ>
Шаг 2: Настроить <vcpu> и <cputune>
Пример для ВМ с 4 vCPU, привязанными к физическим CPU 2,3,4,5:
<vcpu placement='static'>4</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='2'/>
<vcpupin vcpu='1' cpuset='3'/>
<vcpupin vcpu='2' cpuset='4'/>
<vcpupin vcpu='3' cpuset='5'/>
<emulatorpin cpuset='0-1'/>
</cputune>
Пояснения:
placement='static'обязательно (иначе libvirt будет игнорировать пиннинг)vcpu='N'— номер виртуального ядра внутри ВМ (начинается с 0)cpuset='X'— логический ID физического CPU изlscpu- Можно указывать диапазоны:
cpuset='2-5'или списки:cpuset='2,4,6,8' <emulatorpin>привязывает эмулятор QEMU (потокqemu-kvm, не vCPU). Рекомендуется выносить на отдельные ядра хоста.
Шаг 3: Сохранить и выйти
virsh edit автоматически проверит синтаксис и применит изменения при сохранении.
5. Применение и проверка
Перезапуск ВМ (пиннинг применяется только при старте)
virsh destroy <имя_ВМ>
virsh start <имя_ВМ>
Проверка привязки
# Информация по vCPU
virsh vcpuinfo <имя_ВМ>
# Пример вывода:
# VCPU: 0
# CPU: 2
# State: running
# ...
# Проверка через taskset (PID процесса qemu)
ps aux | grep qemu | grep <имя_ВМ>
taskset -pc <PID>
# Должно вывести: pid <PID>'s current affinity list: 2,3,4,5
Визуальная проверка
htop
# F2 → Setup → Display options → Tree view
# Ищите процессы qemu-system-x86_64, смотрите на столбец CPU
6. NUMA-оптимизация (бонус для производительности)
Если система многосокетная или с несколькими NUMA-узлами, пиннинг без учёта NUMA может снизить производительность из-за удалённого доступа к памяти.
<numatune>
<memory mode='strict' nodeset='0'/>
</numatune>
<cputune>
<vcpupin vcpu='0' cpuset='0,2'/>
<vcpupin vcpu='1' cpuset='1,3'/>
<emulatorpin cpuset='0,1'/>
</cputune>
<cpu mode='host-passthrough' check='partial'>
<numa>
<cell id='0' cpus='0-1' memory='4096' unit='KiB'/>
<cell id='1' cpus='2-3' memory='4096' unit='KiB'/>
</numa>
</cpu>
nodeset='0'означает, что вся память ВМ будет выделяться из NUMA-узла 0. Используйтеlscpu -eиnumactl --hardwareдля сопоставления CPU и узлов.
7. Типичные ошибки и рекомендации
| Ошибка | Причина | Решение |
|---|---|---|
invalid cpuset '6' |
Указан несуществующий логический CPU | Проверьте lscpu -e, учитывайте SMT |
vcpu pinning ignored |
placement='auto' или отсутствует static |
Замените на placement='static' |
| ВМ не стартует после правки | Синтаксическая ошибка XML | virsh domxml-to-native qemu-argv /tmp/vm.xml для проверки |
| Хост "тормозит" | Изолированы CPU под IRQ/host | Не изолируйте CPU 0, оставьте 1-2 под хост |
| Пиннинг "сбрасывается" | Используется virsh setvcpus или live-migration |
Пиннинг сохраняется только в XML, live-миграция требует перенастройки на целевом хосте |
Best Practices
- Никогда не пиньте на
cpu 0(используется под host/irq/ACPI) - Для low-latency: отключите SMT в BIOS или пиньте только на чётные CPU
- Сопоставляйте vCPU и pCPU 1:1, не используйте
overcommit - Выносите
<emulatorpin>на отдельные ядра - Регулярно проверяйте
dmesg | grep -i cpuи/var/log/libvirt/qemu/*.log - В Astra Linux SE при включённом
Parsecубедитесь, что профильlibvirtразрешаетcpuaffinity(обычно настроено по умолчанию)
Полезные команды-шпаргалка
# Топология
lscpu -e
numactl --hardware
# Редактирование ВМ
virsh edit <vm>
# Проверка привязки
virsh vcpuinfo <vm>
virsh dominfo <vm> | grep -i cpu
# Перезапуск
virsh destroy <vm> && virsh start <vm>
# Мониторинг в реальном времени
watch -n 1 'virsh vcpuinfo <vm> | grep -E "VCPU|CPU"'
Заключение
CPU-пиннинг в Astra Linux 1.8 настраивается стандартными средствами libvirt.