VK Private Cloud logo
Помощь
Обновлена 5 июня 2026 г. в 11:57

Отсутствуют данные о PCI-устройствах в nova-compute

Подсистема
Cloud Servers
Компонент
Nova

При создании виртуальной машины с GPU или при изменении шаблона конфигурации ВМ на шаблон с GPU возникает ошибка вида Нет свободных хостов для размещения. При этом GPU доступны в операционной системе гипервизора, но в логах сервиса nova-compute в списке pci_stats они не отображаются:

INFO nova.compute.resource_tracker [req-...] Final resource view: name=<ГИПЕРВИЗОР> phys_ram=...MB used_ram=...MB phys_disk=...GB used_disk=100GB total_vcpus=96 used_vcpus=42 pci_stats=[]

Доступность GPU в ОС гипервизора и пустой список pci_stats говорят о том, что Nova не анонсирует GPU как доступные PCI-устройства. Причин может быть несколько:

  • неправильный драйвер для GPU;
  • БД nova содержит устаревшие данные об аллокациях для PCI-устройств на этом гипервизоре.

Проблема может возникнуть, если гипервизор был некорректно выведен из кластера, а затем добавлен обратно с тем же именем.

Решение

  1. Проверьте, какие PCI-устройства доступны в операционной системе гипервизора:

    $ lspci -nn | grep -i nvidia

    Пример ожидаемого вывода:

    17:00.0 3D controller [0302]: NVIDIA Corporation Device [<КОД_ПРОИЗВОДИТЕЛЯ>:<КОД_УСТРОЙСТВА>] (rev a1)

    Здесь:

    • 17:00.0 — слот, в который подключено PCI-устройство;
    • <КОД_ПРОИЗВОДИТЕЛЯ> — код производителя PCI-устройства, например 10de;
    • <КОД_УСТРОЙСТВА> — код PCI-устройства, например 20b5.
  2. Проверьте текущие настройки загрузки ядра. Для этого на гипервизоре выполните команду:

    $ cat /proc/cmdline

    Пример ожидаемого вывода:

    rd.driver.pre=vfio-pci vfio-pci.ids=<КОД_ПРОИЗВОДИТЕЛЯ>:<КОД_УСТРОЙСТВА> rd.driver.blacklist=nouveau nouveau.modeset=0 intel_iommu=on iommu=pt
  3. Убедитесь, что в выводе есть параметры:

    • intel_iommu=on или amd_iommu=on в зависимости от производителя CPU;
    • iommu=pt — режим passthrough для IOMMU;
    • rd.driver.pre=vfio-pci — тип драйвера GPU для QEMU;
    • vfio-pci.ids=<КОД_ПРОИЗВОДИТЕЛЯ>:<КОД_УСТРОЙСТВА> — код производителя и код PCI-устройства;
    • rd.driver.blacklist=nouveau — обязательное отключение модуля ядра для GPU-драйвера nouveau;
    • nouveau.modeset=0 — обязательное отключение GPU-драйвера nouveau.

    Если параметров нет:

    1. Добавьте параметры в переменную GRUB_CMDLINE_LINUX в файле /etc/default/grub:

      intel_iommu=on iommu=pt rd.driver.pre=vfio-pci vfio-pci.ids=<КОД_ПРОИЗВОДИТЕЛЯ>:<КОД_УСТРОЙСТВА> rd.driver.blacklist=nouveau nouveau.modeset=0
    2. Пересоберите grub:

      $ grub2-mkconfig -o /boot/grub2/grub.cfg$ dracut -f
    3. Перезагрузите гипервизор:

      $ reboot
  4. Проверьте, что запрещена загрузка драйвера nouveau. В файле /etc/modprobe.d/blacklist-nouveau.conf должно быть указано:

    blacklist nouveauoptions nouveau modeset=0
  5. Убедитесь, что в файле /etc/modprobe.d/vfio.conf указано PCI-устройство, для которого нужно загружать модуль vfio-pci:

    options vfio-pci ids=<КОД_ПРОИЗВОДИТЕЛЯ>:<КОД_УСТРОЙСТВА>
  6. Проверьте, что модуль vfio-pci загружается:

    $ lsmod | grep vfio

    Пример ожидаемого вывода:

    vfio_pci              16384  0vfio_pci_core         73728  1 vfio_pcivfio_virqfd           16384  1 vfio_pci_corevfio_iommu_type1      45056  0vfio                  49152  3 vfio_pci_core,vfio_iommu_type1,vfio_pciirqbypass             16384  2 vfio_pci_core,kvm
  7. Убедитесь, что GPU привязан к модулю vfio-pci:

    1. Выполните команду:

      lspci -nnk -s 17:00.0

      Здесь 17:00.0 — слот, в который подключено PCI-устройство.

      Пример ожидаемого вывода:

      17:00.0 3D controller [0302]: NVIDIA Corporation GA100 [A100 PCIe 80GB] [10de:20b5] (rev a1)        Kernel driver in use: vfio-pci        Kernel modules: nouveau
    2. Убедитесь, что в выводе в параметре Kernel driver in use указан драйвер vfio-pci.

    3. Проверьте символическую ссылку:

      ls -l /sys/bus/pci/devices/0000:17:00.0/driver

      Здесь 17:00.0 — слот, в который подключено PCI-устройство.

      Пример ожидаемого вывода:

      /sys/bus/pci/devices/0000:17:00.0/driver -> ../../../bus/pci/drivers/vfio-pci
    4. Убедитесь, что в выводе указан драйвер vfio-pci.

    5. Если указан другой драйвер, привяжите GPU к модулю vfio-pci принудительно:

      $ modprobe vfio-pciecho "0000:17:00.0" > /sys/bus/pci/devices/0000:17:00.0/driver/unbindecho vfio-pci > /sys/bus/pci/devices/0000:17:00.0/driver_overrideecho "0000:17:00.0" > /sys/bus/pci/drivers_probe

      Здесь 17:00.0 — слот, в который подключено PCI-устройство.

  8. Проверьте, что включен IOMMU (Input-Output Memory Management Unit):

    $ dmesg -T | grep -iE 'iommu|dmar|vfio'

    Пример ожидаемого вывода:

    DMAR: IOMMU enablediommu: Default domain type: Passthrough (set via kernel command line)VFIO - User Level meta-driver version: 0.3vfio_pci: add [10de:20b5[ffffffff:ffffffff]] class 0x000000/00000000
  9. Проверьте IOMMU-группы:

    ls -l /sys/bus/pci/devices/0000:17:00.0/iommu_group/devices/

    Здесь 17:00.0 — слот, в который подключено PCI-устройство.

  10. Проверьте, что libvirt видит GPU:

    $ virsh nodedev-list | grep 17$ virsh nodedev-dumpxml pci_0000_17_00_0

    Пример корректного dumpxml:

    <driver>  <name>vfio-pci</name></driver><capability type='pci'>  <product id='0x20b5'>GA100 [A100 PCIe 80GB]</product>  <vendor id='0x10de'>NVIDIA Corporation</vendor>
  11. Проверьте настройки в nova.conf:

    $ grep -nE '^\[pci\]|alias|passthrough_whitelist|pci_passthrough_whitelist' /etc/nova/nova.conf

    Пример корректной настройки в nova.conf:

    [pci]alias = {"vendor_id": "<КОД_ПРОИЗВОДИТЕЛЯ>", "product_id": "<КОД_УСТРОЙСТВА>", "device_type": "type-PF", "name": "<ИМЯ_УСТРОЙСТВА>"}passthrough_whitelist = [{"vendor_id": "<КОД_ПРОИЗВОДИТЕЛЯ>", "product_id": "<КОД_УСТРОЙСТВА>"}]
  12. Проверьте, появились ли в логах сервиса nova-compute PCI-устройства:

    $ grep -i pci_stats /var/log/nova/nova-compute.log | tail -20

    В списке pci_stats должно быть указано описание всех GPU с count=1.

  13. Если PCI-устройства не появились в логах сервиса nova-compute:

    1. На управляющем узле с ролью MariaDB подключитесь к БД nova:

      $ mysql -S /srv/mysql/nova/socket/nova.sock nova
    2. Получите из таблицы pci_devices информацию о PCI-записях проблемного гипервизора:

      SELECT id, address, vendor_id, product_id, status, instance_uuid, compute_node_idFROM pci_devicesWHERE compute_node_id IN (SELECT id FROM compute_nodes WHERE hypervisor_hostname = '<ГИПЕРВИЗОР>') AND product_id = '<КОД_УСТРОЙСТВА>';

      Здесь:

      • <ГИПЕРВИЗОР> — имя проблемного гипервизора;
      • <КОД_УСТРОЙСТВА> — код PCI-устройства, например 20b5.

      Пример вывода:

      +--------+-------------+-----------+------------+-----------+---------------+-----------------+| id     | address     | vendor_id | product_id | status    | instance_uuid | compute_node_id |+--------+-------------+-----------+------------+-----------+---------------+-----------------+| 143    | 0000:17:00.0| 10de      | 20b5       | available | NULL          | <ГИПЕРВИЗОР>    || 146    | 0000:17:00.0| 10de      | 20b5       | allocated | 4a1811c7-8b1f | <ГИПЕРВИЗОР>    |+--------+-------------+-----------+------------+-----------+---------------+-----------------+
    3. Получите идентификатор актуального (не удаленного) гипервизора:

      SELECT id FROM compute_nodes WHERE hypervisor_hostname = '<ГИПЕРВИЗОР>' AND deleted=0;

      Это поможет определить, какие записи из предыдущего запроса относятся к актуальному гипервизору.

    4. Убедитесь, что ВМ, идентификатор которой указан в instance_uuid, находится на другом гипервизоре. Тогда эта PCI-запись является устаревшей (stale allocation).

    5. На проблемном гипервизоре остановите сервис openstack-nova-compute:

      # systemctl stop openstack-nova-compute
    6. На управляющем узле с ролью MariaDB сделайте резервную копию всех БД Nova:

      $ cd /srv/backup$ bash +x ./backup_xtra_nova.sh
    7. На управляющем узле с ролью MariaDB подключитесь к БД nova:

      $ mysql -S /srv/mysql/nova/socket/nova.sock nova
    8. Удалите устаревшие PCI-записи:

      DELETE FROM pci_devicesWHERE id IN (<ЗАПИСЬ_1>[, <ЗАПИСЬ_2>, ...]);

      Здесь <ЗАПИСЬ_1>[, <ЗАПИСЬ_2>, ...] — идентификаторы устаревших PCI-записей.

    9. На проблемном гипервизоре перезапустите сервис libvirtd:

      # systemctl restart libvirtd
    10. На проблемном гипервизоре запустите сервис openstack-nova-compute:

      # systemctl start openstack-nova-compute
    11. Убедитесь, что в логах сервиса nova-compute появились PCI-устройства:

      $ grep -i pci_stats /var/log/nova/nova-compute.log | tail -20

      В списке pci_stats должно быть указано описание всех GPU с count=1.