在 RHEL 9 for Real Time 中配置虚拟化


Red Hat Enterprise Linux for Real Time 9

在 RHEL for Real Time 主机上安装和测试虚拟机。

Red Hat Customer Content Services

摘要

设置、优化和测试服务器,以便在使用 KVM 作为实时管理程序的环境中开发和部署应用程序。

对红帽文档提供反馈

我们感谢您对我们文档的反馈。让我们了解如何改进它。

通过 Jira 提交反馈(需要帐户)

  1. 登录到 Jira 网站。
  2. 在顶部导航栏中点 Create
  3. Summary 字段中输入描述性标题。
  4. Description 字段中输入您对改进的建议。包括文档相关部分的链接。
  5. 点对话框底部的 Create

第 1 章 RHEL for Real Time 上的虚拟化是什么

要在实时工作负载中使用虚拟机,红帽在 RHEL for Real Time 中提供虚拟化功能。

在 RHEL for Real Time 中,您可以配置主机和客户机操作系统,以实现虚拟机的低延迟和确定性行为。这使得实时虚拟机更适用于需要实时性能的应用程序,如工业自动化、电信和自主系统。

有关使用实时 RHEL 系统的好处的详情,请参阅 RHEL for Real Time 以优化延迟

第 2 章 实时虚拟化的主机系统要求

要托管实时虚拟机,RHEL 9 系统必须满足以下要求:

  • 实时内核

    要将 RHEL 9 主机配置为实时内核,您必须安装实时内核。具体步骤请参阅 安装 RHEL for Real Time

    另外,您必须在主机上安装 tuned-profiles-nfv

    # dnf install tuned-profiles-nfv
    Copy to Clipboard
  • 虚拟化

    RHEL 9 虚拟化软件包必须安装在您的主机上。具体步骤请参阅 启用虚拟化

  • BIOS

    要成功部署并运行实时虚拟机,必须配置主机系统 BIOS 以实现最低延迟。要做到这一点,请按照特定于主机硬件模型的说明进行操作。例如:

    特定的低延迟设置因不同的供应商和型号而异,但通常情况下,最小化延迟的步骤包括:

    • 禁用高级硬件电源管理选项。它们提供对各种特定电源管理方面的更多控制,但也可能会导致延迟激增。
    • 禁用较低 CPU 电源状态,如 C-states 或 C1E。

      重要

      有些低延迟 BIOS 指南可能会建议禁用虚拟化。但是,必须跳过这一步,才能在主机上正常工作实时虚拟机。

第 3 章 为实时虚拟机配置主机环境

为确保 RHEL 9 可以作为主机用于实时虚拟机,您必须优化主机的性能并在输入和系统响应之间测试其延迟。

3.1. 为实时虚拟化主机配置 TuneD

要将 RHEL 9 系统优化为实时虚拟机(VM)的主机,请为 TuneD 配置并启用 realtime-virtual-host 配置集。

先决条件

  • 您的主机满足 实时虚拟化的系统要求
  • irqbalance 服务被禁用。如果启用了 irqbalance,则处理中断请求(IRQ)可能与 TuneD 冲突。禁用 irqbalance

    # systemctl stop irqbalance && systemctl disable irqbalance
    Copy to Clipboard

流程

  1. 开始编辑 TuneD 的 realtime-virtual-host 配置集的配置。要做到这一点,请在文本编辑器中打开 /etc/tuned/realtime-virtual-host-variables.conf 文件。
  2. 调整 /etc/tuned/realtime-virtual-host-variables.conf 中的配置以满足您的要求。在设置中特别考虑以下因素:

    • 机器拥有的内核和 NUMA 节点数量
    • 您要运行的 RT 客户机数量
    • 每个 RT 客户机将具有的 vCPU 数量

    /etc/tuned/realtime-virtual-host-variables.conf 的最重要的修改包括:

    • 更新 isolated_cores 参数,以调整每个插槽的主机内核将专用于 RT 虚拟化任务,哪些内核将保留主机上的系统维护(也称为 内务处理)。

      例如,以下设置使用核心 3、核心 6 和内核 8 到 RT 任务,所有其他内核作为内务操作:

      isolated_cores=3,6,8-15
      Copy to Clipboard

      请注意,默认情况下,每个插槽有一个核心(内核 0)用于内务处理,所有其他内核用于 RT 任务。

      重要

      核心 0 必须始终设置为内务内核。将核心 0 用于 RT 任务会破坏 RT 功能。

    • 为内核管理的 IRQ 启用 IRQ 隔离。要做到这一点,请确保在配置中没有注释掉以下行:

      isolate_managed_irq=Y
      Copy to Clipboard

      如果禁用了 IRQ 隔离,主机内核管理的 IRQ 可能会中断隔离的内核,这可能会导致意外的延迟。

    • 取消注释 netdev_queue_count 参数,并将其值设为内务内核数。
  3. 将更改保存到 /etc/tuned/realtime-virtual-host-variables.conf
  4. 激活实时虚拟主机配置文件。

    # tuned-adm profile realtime-virtual-host
    Copy to Clipboard
  5. 重启主机。

3.2. 为实时虚拟化主机配置巨页

要进一步降低 RHEL 9 的虚拟机(VM)的延迟,请将主机设置为使用巨页。巨页可能会显著提高使用大量内存的应用程序的性能,通常是 RT 应用程序的情况。

有关巨页的更多信息,请参阅配置巨页

先决条件

流程

  1. 将默认巨页大小设置为 1 gibibyte。

    $ grubby --args "default_hugepagesz=1G" --update-kernel ALL
    Copy to Clipboard
  2. 在主机上保留巨页。

    $ echo <X> > /sys/devices/system/node/node_<Y>_/hugepages/<hugepages-size_dir>/nr-hugepages
    Copy to Clipboard

    在这个命令中,按如下所示替换变量:

    • < x>,带有要保留的巨页数。这个值取决于虚拟机数量及其具有的内存量。如果您正在运行单个虚拟机,请从两个 1GB 页面开始。
    • &lt;y> 带有固定实时 vCPU 的 NUMA 节点数量。
    • <hugepage-size_dir >,其巨页大小为 kB。例如,对于 2MB 巨页,这将是 hugepages-2048kB
    重要

    此命令临时设置巨页。因此,在启动任何实时虚拟机前,您必须在每个主机重启后使用该命令。要避免这种情况,请执行以下可选步骤,使巨页持久。

  3. 可选:如果要使巨页配置持久,还要执行以下操作:

    1. 创建名为 /usr/lib/systemd/system/hugetlb-gigantic-pages.service 的文件,其内容如下:

      [Unit]
      Description=HugeTLB Gigantic Pages Reservation
      DefaultDependencies=no
      Before=dev-hugepages.mount
      ConditionPathExists=/sys/devices/system/node
      ConditionKernelCommandLine=default_hugepagesz=1G
      
      [Service]
      Type=oneshot
      RemainAfterExit=yes
      ExecStart=/usr/lib/systemd/hugetlb-reserve-pages
      
      [Install]
      WantedBy=sysinit.target
      Copy to Clipboard
    2. 创建名为 /usr/lib/systemd/hugetlb-reserve-pages' 的文件,其内容如下:

      #!/bin/bash
      nodes_path=/sys/devices/system/node/
      if [ ! -d $nodes_path ]; then
      	echo "ERROR: $nodes_path does not exist"
      	exit 1
      fi
      
      reserve_pages()
      {
      	echo $1 > $nodes_path/$2/hugepages/hugepages-1048576kB/nr_hugepages
      }
      
      # This example reserves 2 1G pages on node0 and 1 1G page on node1. You
      # can modify it to your needs or add more lines to reserve memory in
      # other nodes. Don't forget to uncomment the lines, otherwise then won't
      # be executed.
      # reserve_pages 2 node0
      # reserve_pages 1 node1
      Copy to Clipboard
    3. 使用以下命令启用早期引导保留:

      $ chmod +x /usr/lib/systemd/hugetlb-reserve-pages
      $ sudo systemctl enable hugetlb-gigantic-pages
      $ sudo systemctl status hugetlb-gigantic-pages
      Copy to Clipboard
    4. 取消注释 /usr/lib/systemd/hugetlb-reserve-pages 底部两行,并根据您的巨页保留要求更新它们。
  4. 重启以应用所有配置更改。

3.3. 验证实时虚拟化的主机 BIOS 设置

要验证实时内核的 BIOS 是否已成功为低延迟工作负载设置,请使用 hwlatdetect 程序。

先决条件

流程

  1. 至少为一个小时运行 hwladetect 工具,并确保测量的延迟不超过 1 微秒(wagons)。

    # hwlatdetect --threshold=1μs –duration=60m
    
      hwlatdetect:  test duration 60 minutes
    	parameters:
    		Latency threshold: 1μs
    		Sample window:     1000000μs
    		Sample width:      500000μs
    		Non-sampling period:  500000μs
    		Output File:       None
    
    Starting test
    test finished
    Max Latency: 0us
    Samples recorded: 0
    Samples exceeding threshold: 0
    Copy to Clipboard
  2. 可选:为了改进验证,请在 24 小时内运行相同的测试。

    # hwlatdetect --threshold=1μs –duration=24h
    Copy to Clipboard

3.4. 验证实时虚拟化主机环境

为实时虚拟机(VM)配置了主机后,您必须验证它是否设置是否正确。要做到这一点,检查内核、巨页和隔离的 CPU 的设置,并确保 TuneD 配置集处于活跃状态。

先决条件

流程

  1. 查看 /proc/cmdline 文件的内容,并检查以下参数的值是否与您配置的方式对应:

    • 实时内核
    • 巨页
    • 隔离的 CPU

      例如:

      cat /proc/cmdline
      
      BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.14.0-70.13.1.rt21.83.el9_0.x86_64 root=/dev/mapper/rhel_virtlab505-root ro crashkernel=auto resume=/dev/mapper/rhel_virtlab505-swap rd.lvm.lv=rhel_virtlab505/root rd.lvm.lv=rhel_virtlab505/swap console=ttyS1,115200 default_hugepages=1G skew_tick=1 isolcpus=1,3,5,7,9,11,13,14,15 intel_pstate=disable nosoftlockup tsc=nowatchdog nohz=on nohz_full=1,3,5,7,9,11,13,14,15 rcu_nocbs=1,3,5,7,9,11,13,14,15
      Copy to Clipboard
  2. 确保 realtime-virtual-host 调优配置集处于活动状态。

    $ tuned-adm active
    Current active profile: realtime-virtual-host
    Copy to Clipboard
  3. 检查巨页数量。例如:

    $ cat /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages
    
    2
    Copy to Clipboard

3.5. 压力测试实时虚拟化系统

要确保 RHEL for Real Time 主机或客户机在负载过重时设置了低延迟,请执行实时延迟测试。

先决条件

流程

  1. 为内务核心增加压力。为此,请在上几节中设置的内务内核数上开始编译 linux 内核。

    1. 克隆 Linux 内核存储库并移动到其目录中。

      # git clone https://github.com/torvalds/linux.git ; cd linux
      Copy to Clipboard
    2. 为内核编译创建默认配置。

      # make defconfig
      Copy to Clipboard
    3. 开始编译 Linux 内核。

      # while true; do make -j <double-number-of-housekeeping-cpus> && make clean; done
      Copy to Clipboard
  2. 在主机上执行 cyclictest 步骤 12 小时。在以下示例中,将 &lt ;list_isolated_cores& gt; 替换为为实时任务隔离的内核列表,如 1,3,5,7,9,11,13,14,15

    # cyclictest -m -q -p95 --policy=fifo -D 12h -h60 -t <number_of_isolated_cpus> -a <list_isolated_cores> -mainaffinity <list_housekeeping_cpus> -i 200
    Copy to Clipboard

    当使用现代高端 AMD64 或 Intel 64 处理器(也称为 x86_64)时,输出中的 Max Latencies 的最佳值是 40 微秒(5-6s)。要终止测试,如果测量的延迟超过 405-4,请在命令中添加 -b 40 选项。

  3. 在主机上执行 OS 级别延迟测试(OSLAT),时间为 12 小时。

    # ./oslat --cpu-list <list_isolated_cores> --rtprio 1 --D 12h -w memmove -m 4K
    Copy to Clipboard

    使用现代高端 x86_64 处理器时,输出中的最佳值是 20 HEKETIs。要终止测试,测量的延迟是否超过 20 个,请在命令中添加 -T 20 选项。

第 4 章 设置实时虚拟机

要使用 RHEL 9 for Real Time 客户机操作系统设置虚拟机(VM),您必须创建一个虚拟机、配置其客户机并优化并测试虚拟机的性能。

4.1. 为实时虚拟机优化 vCPU 固定

要正确设置 RHEL 实时(RT)虚拟机(VM),您必须首先有一个计划来优化将虚拟机的虚拟 CPU (vCPU)固定到主机的物理 CPU。

先决条件

  • 您已为实时虚拟化设置主机系统。具体步骤请参阅 为实时虚拟机配置主机环境。
  • 已安装 hwloc 软件包。

    # dnf install hwloc
    Copy to Clipboard
  • 您已评估了虚拟机的性能,以获取基础进行验证。有关执行此操作的各种方法,请参阅 虚拟机性能监控工具

流程

  1. 查看主机系统的 CPU 拓扑:

    # lstopo-no-graphics
    Copy to Clipboard

    以下示例输出显示了启用了超线程的 32 个物理内核的系统,分为 2 个插槽("软件包"),每个内核有 4 个 CPU 划分。系统还有 250 GB RAM 分布到 2 个 NUMA 节点。

    请注意,这个过程中的以下示例基于这个拓扑。

    Machine (250GB total)
      Package L#0
        NUMANode L#0 (P#0 124GB)
        Die L#0 + L3 L#0 (16MB)
          L2 L#0 (1024KB) + L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0
            PU L#0 (P#0)
            PU L#1 (P#32)
          L2 L#1 (1024KB) + L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1
            PU L#2 (P#1)
            PU L#3 (P#33)
          L2 L#2 (1024KB) + L1d L#2 (32KB) + L1i L#2 (32KB) + Core L#2
            PU L#4 (P#2)
            PU L#5 (P#34)
          L2 L#3 (1024KB) + L1d L#3 (32KB) + L1i L#3 (32KB) + Core L#3
            PU L#6 (P#3)
            PU L#7 (P#35)
        Die L#1 + L3 L#1 (16MB)
          L2 L#4 (1024KB) + L1d L#4 (32KB) + L1i L#4 (32KB) + Core L#4
            PU L#8 (P#4)
            PU L#9 (P#36)
          L2 L#5 (1024KB) + L1d L#5 (32KB) + L1i L#5 (32KB) + Core L#5
            PU L#10 (P#5)
            PU L#11 (P#37)
          L2 L#6 (1024KB) + L1d L#6 (32KB) + L1i L#6 (32KB) + Core L#6
            PU L#12 (P#6)
            PU L#13 (P#38)
          L2 L#7 (1024KB) + L1d L#7 (32KB) + L1i L#7 (32KB) + Core L#7
            PU L#14 (P#7)
            PU L#15 (P#39)
        Die L#2 + L3 L#2 (16MB)
          L2 L#8 (1024KB) + L1d L#8 (32KB) + L1i L#8 (32KB) + Core L#8
            PU L#16 (P#8)
            PU L#17 (P#40)
          L2 L#9 (1024KB) + L1d L#9 (32KB) + L1i L#9 (32KB) + Core L#9
            PU L#18 (P#9)
            PU L#19 (P#41)
          L2 L#10 (1024KB) + L1d L#10 (32KB) + L1i L#10 (32KB) + Core L#10
            PU L#20 (P#10)
            PU L#21 (P#42)
          L2 L#11 (1024KB) + L1d L#11 (32KB) + L1i L#11 (32KB) + Core L#11
            PU L#22 (P#11)
            PU L#23 (P#43)
        Die L#3 + L3 L#3 (16MB)
          L2 L#12 (1024KB) + L1d L#12 (32KB) + L1i L#12 (32KB) + Core L#12
            PU L#24 (P#12)
            PU L#25 (P#44)
          L2 L#13 (1024KB) + L1d L#13 (32KB) + L1i L#13 (32KB) + Core L#13
            PU L#26 (P#13)
            PU L#27 (P#45)
          L2 L#14 (1024KB) + L1d L#14 (32KB) + L1i L#14 (32KB) + Core L#14
            PU L#28 (P#14)
            PU L#29 (P#46)
          L2 L#15 (1024KB) + L1d L#15 (32KB) + L1i L#15 (32KB) + Core L#15
            PU L#30 (P#15)
            PU L#31 (P#47)
      Package L#1
        NUMANode L#1 (P#1 126GB)
        Die L#4 + L3 L#4 (16MB)
          L2 L#16 (1024KB) + L1d L#16 (32KB) + L1i L#16 (32KB) + Core L#16
            PU L#32 (P#16)
            PU L#33 (P#48)
          L2 L#17 (1024KB) + L1d L#17 (32KB) + L1i L#17 (32KB) + Core L#17
            PU L#34 (P#17)
            PU L#35 (P#49)
          L2 L#18 (1024KB) + L1d L#18 (32KB) + L1i L#18 (32KB) + Core L#18
            PU L#36 (P#18)
            PU L#37 (P#50)
          L2 L#19 (1024KB) + L1d L#19 (32KB) + L1i L#19 (32KB) + Core L#19
            PU L#38 (P#19)
            PU L#39 (P#51)
        Die L#5 + L3 L#5 (16MB)
          L2 L#20 (1024KB) + L1d L#20 (32KB) + L1i L#20 (32KB) + Core L#20
            PU L#40 (P#20)
            PU L#41 (P#52)
          L2 L#21 (1024KB) + L1d L#21 (32KB) + L1i L#21 (32KB) + Core L#21
            PU L#42 (P#21)
            PU L#43 (P#53)
          L2 L#22 (1024KB) + L1d L#22 (32KB) + L1i L#22 (32KB) + Core L#22
            PU L#44 (P#22)
            PU L#45 (P#54)
          L2 L#23 (1024KB) + L1d L#23 (32KB) + L1i L#23 (32KB) + Core L#23
            PU L#46 (P#23)
            PU L#47 (P#55)
        Die L#6 + L3 L#6 (16MB)
          L2 L#24 (1024KB) + L1d L#24 (32KB) + L1i L#24 (32KB) + Core L#24
            PU L#48 (P#24)
            PU L#49 (P#56)
          L2 L#25 (1024KB) + L1d L#25 (32KB) + L1i L#25 (32KB) + Core L#25
            PU L#50 (P#25)
            PU L#51 (P#57)
          L2 L#26 (1024KB) + L1d L#26 (32KB) + L1i L#26 (32KB) + Core L#26
            PU L#52 (P#26)
            PU L#53 (P#58)
          L2 L#27 (1024KB) + L1d L#27 (32KB) + L1i L#27 (32KB) + Core L#27
            PU L#54 (P#27)
            PU L#55 (P#59)
        Die L#7 + L3 L#7 (16MB)
          L2 L#28 (1024KB) + L1d L#28 (32KB) + L1i L#28 (32KB) + Core L#28
            PU L#56 (P#28)
            PU L#57 (P#60)
          L2 L#29 (1024KB) + L1d L#29 (32KB) + L1i L#29 (32KB) + Core L#29
            PU L#58 (P#29)
            PU L#59 (P#61)
          L2 L#30 (1024KB) + L1d L#30 (32KB) + L1i L#30 (32KB) + Core L#30
            PU L#60 (P#30)
            PU L#61 (P#62)
          L2 L#31 (1024KB) + L1d L#31 (32KB) + L1i L#31 (32KB) + Core L#31
            PU L#62 (P#31)
            PU L#63 (P#63)
    Copy to Clipboard
  2. 根据 lstopo-no-graphics 的输出以及所需的实时虚拟机设置,确定如何将 vCPU 固定到物理 CPU。以下项目显示了对上述示例主机输出和具有 4 个 vCPU 的实时虚拟机有效 XML 配置:

    • 以下固定放置为每个 vCPU 使用专用内核。要使这样的固定配置生效,分配的物理 CPU 必须被隔离在主机上,且不得在它们上运行的任何进程。

      <cputune>
        <vcpupin vcpu='0' cpuset='4'/>
        <vcpupin vcpu='1' cpuset='5'/>
        <vcpupin vcpu='2' cpuset='6'/>
        <vcpupin vcpu='3' cpuset='7'/>
      [...]
      Copy to Clipboard
    • 以下固定放置为每个 vCPU 使用专用 L3 内核:

      <cputune>
        <vcpupin vcpu='0' cpuset='16'/>
        <vcpupin vcpu='1' cpuset='20'/>
        <vcpupin vcpu='2' cpuset='24'/>
        <vcpupin vcpu='3' cpuset='28'/>
      [...]
      Copy to Clipboard

验证

  • 再次监控虚拟机的性能,并将值与之前获取的基准进行比较。有关执行此操作的各种方法,请参阅 虚拟机性能监控工具

4.2. 安装 RHEL 实时客户机操作系统

要为实时工作负载准备虚拟机(VM)环境,请创建新虚拟机并调整其配置以实现低延迟性能。

先决条件

流程

  1. 使用 virt-install 工具创建带有以下属性的 RHEL 9 虚拟机:

    • 虚拟机有 2 个或更多分配的 vCPU
    • 虚拟机使用巨页来支持内存。

    以下示例命令创建一个名为 RHEL9-RT 的虚拟机,它符合上述要求:

    # virt-install -n RHEL9-RT \
        --os-variant=rhel9.6 --memory=3072,hugepages=yes \
        --memorybacking hugepages=yes,size=1,unit=G,locked=yes \
        --vcpus=4 --numatune=1 --disk path=./rhel9-rt.img,bus=virtio,cache=none,format=raw,io=threads,size=30 \
        --graphics none --console pty,target_type=serial \
        -l downloads/rhel9.iso \
        --extra-args 'console=ttyS0,115200n8 serial'
    Copy to Clipboard
  2. 安装完成后,关闭虚拟机。

    # virsh shutdown <RHEL9-RT>
    Copy to Clipboard
  3. 打开虚拟机的 XML 配置。

    # virsh edit <RHEL9-RT>
    Copy to Clipboard
  4. 调整 CPU 配置,如下所示:

    <cpu mode='host-model' check='partial'>
        <feature policy='require' name='tsc-deadline'/>
    </cpu>
    Copy to Clipboard
  5. 从虚拟机中删除非必要的虚拟硬件,以提高性能。

    1. 删除 virtio RNG 设备的 部分。

        <rng model='virtio'>
            <backend model='random'>/dev/urandom</backend>
            <address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
        </rng>
      Copy to Clipboard
    2. 删除 USB 设备,如下所示:

      <hostdev mode='subsystem' type='usb' managed='yes'>
        <source>
          <vendor id='0x1234'/>
          <product id='0xabcd'/>
        </source>
      </hostdev>
      Copy to Clipboard
    3. 删除串行设备,如下所示:

      <serial type='dev'>
        <source path='/dev/ttyS0'/>
        <target port='0'/>
      </serial>
      Copy to Clipboard
    4. 删除 QXL 设备。

      <video>
        <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1'/>
      </video>
      Copy to Clipboard
    5. 禁用图形显示。

      <graphics type='vnc' ports='-1' autoport='yes' listen='127.0.0.1'>
        <listen type='address' address='127.0.0.1'>
      </graphics>
      Copy to Clipboard
    6. 在 USB 控制器设置中,将模型改为 none 以禁用它。

      <controller type='usb' index='0' model='none'/>
      Copy to Clipboard
    7. 删除 Trusted Platform 模块(TPM)配置,使其不会影响 RT 操作。

        <tpm model='tpm-crb'>
            <backend type='emulator' version='2.0'/>
        </tpm>
      Copy to Clipboard
    8. 禁用 memballoon 功能。

        <memballoon model='none'>
      Copy to Clipboard
    9. 在配置的 <features > 部分中,确保禁用 PMUvmport 功能,以避免它们可能导致的延迟。

        <features>
           [...]
           <pmu state='off'/>
           <vmport state='off'/>
        </features>
      Copy to Clipboard
  6. 编辑 & lt;numatune > 部分以设置 NUMA 节点。

      <numatune>
        <memory mode='strict' nodeset='1'/>
      </numatune>
    Copy to Clipboard
  7. 编辑 配置的 &lt;cputune> 部分,以按照为实时虚拟机优化 vCPU 固定 中的计划设置 vCPU NUMA 固定。

    以下示例使用 4 个 vCPU 和这些参数配置虚拟机:

    • 从 NUMA 节点 0 的隔离内核 15 是非实时 vCPU
    • 来自 NUMA 节点 1 - 3 的核心 16、47 和 48 是实时 vCPU
    • 配置将所有 QEMU I/O 线程固定到主机内务处理内核(0 和 32)。
    <cputune>
      <vcpupin vcpu='0' cpuset='15'/>
      <vcpupin vcpu='1' cpuset='47'/>
      <vcpupin vcpu='2' cpuset='16'/>
      <vcpupin vcpu='3' cpuset='48'/>
      <emulatorpin cpuset='0,32'/>
      <emulatorsched scheduler='fifo' priority='1'/>
      <vcpusched vcpus='0' scheduler='fifo' priority='1'/>
      <vcpusched vcpus='1' scheduler='fifo' priority='1'/>
      <vcpusched vcpus='2' scheduler='fifo' priority='1'/>
      <vcpusched vcpus='3' scheduler='fifo' priority='1'/>
    </cputune>
    Copy to Clipboard
    注意

    如果您的主机使用 启用了超线程 的硬件,还要确保 < cputune& gt; 配置满足以下要求:

    • 分配物理内核的同级功能,以执行实时或内务任务。
    • 在同一虚拟机上同时使用物理内核同级设备。
    • 对于固定到同一物理内核的同级的 vCPU,请将 vCPU 分配给同一任务(实时进程或日常处理)。

    请注意,上面的示例配置满足这些要求。

  8. 保存并退出 XML 配置。

故障排除

验证

  • 在主机上,查看虚拟机的配置,并验证它具有必要的参数:

    # virsh dumpxml <RHEL9-RT>
    Copy to Clipboard

4.3. 实时配置 RHEL 客户机操作系统

要为实时工作负载优化 RHEL 9 虚拟机(VM)环境,请配置客户机操作系统以实现低延迟性能。

先决条件

流程

  1. 启动虚拟机。
  2. 在客户端操作系统中安装实时软件包。

    # dnf install -y kernel-rt tuned tuned-profiles-realtime tuned-profiles-nfv realtime-tests
    Copy to Clipboard
  3. 调整 tuned 的虚拟客户机配置文件。要做到这一点,请编辑 /etc/tuned/realtime-virtual-guest-variables.conf 文件并添加以下行:

    isolated_cores=<isolated-core-nrs>
    isolate_managed_irq=Y
    Copy to Clipboard

    将 < isolated-core-nrs > 替换为您要为实时工作负载隔离的主机内核数。

  4. 确定在客户端操作系统中禁用 irqbalance。

    # rpm -q irqbalance && systemctl stop irqbalance && systemctl disable irqbalance
    Copy to Clipboard
  5. 激活 tuned 的 realtime-virtual-guest 配置集。

    # tuned-adm profile realtime-virtual-guest
    Copy to Clipboard
  6. 确保客户机操作系统默认使用实时内核。

    # grubby --set-default vmlinuz-5.14.0-XXX.el9.x86_64+rt
    Copy to Clipboard
  7. 与主机中的相同,为客户端操作系统配置巨页。具体步骤请参阅 为实时虚拟化主机配置巨页

验证

故障排除

如果压力测试的结果超过所需的延迟,请执行以下操作:

  1. 再次在主机上执行压力测试。如果延迟结果是子优化,请调整 TuneD 和巨页的主机配置,并重新测试。具体步骤请参阅 为实时虚拟化主机配置 TuneD并为实时虚拟化主机配置巨页
  2. 如果主机上的压力测试结果显示足够低的延迟,但在它们没有的客户机上,请使用 trace-cmd 工具来生成详细的测试报告。具体步骤请参阅 RHEL 实时客户机对延迟问题进行故障排除

4.4. 为实时虚拟机设置缓存保护

驱除缓存行可能会导致实时虚拟机(VM)中的性能问题。要避免这个问题,请使用 User Interface for Resource Control (resctrlfs')功能管理您的缓存和缓存分区:

  • 将主机系统的主内存缓存划分为分区
  • 为每个分区分配单独的任务
  • 将运行实时应用程序的 vCPU 分配给一个缓存分区
  • 将运行日常工作负载的 vCPU 和主机 CPU 分配给不同的缓存分区

先决条件

  • 您已在主机上创建了一个实时虚拟机。具体步骤请参阅 安装 RHEL 实时客户机操作系统
  • 您的主机使用支持 L2 或 L3 缓存分区的 Intel 处理器。要确定是这种情况:

    1. 安装 intel-cmt-cat 工具。

      # dnf install intel-cmt-cat
      Copy to Clipboard
    2. 使用 pqos 实用程序显示您的核心缓存详细信息。

      # pqos -d
      
      [...]
         Allocation
            Cache Allocation Technology (CAT)
              L3 CAT
      Copy to Clipboard

      此输出表示您的 CPU 支持 L3 缓存分区。

流程

以下步骤假设您有以下 NUMA 固定将 vCPU 分配给 CPU。

<cputune>
    <vcpupin vcpu='0' cpuset='16'/>
    <vcpupin vcpu='1' cpuset='17'/>
    <vcpupin vcpu='2' cpuset='18'/>
    <vcpupin vcpu='3' cpuset='19'/>
Copy to Clipboard
  1. 挂载 resctrl 文件系统。这样便可使用处理器的资源控制功能。

    # mount -t resctrl resctrl /sys/fs/resctrl
    Copy to Clipboard

    根据您的系统是否支持 L2 还是 L3 缓存分区,名为 L2L3 的子目录挂载到 /sys/fs/resctrl/info 目录中。以下步骤假设您的系统支持 L3 缓存分区。

  2. 移到缓存目录并列出其内容。

    # cd /sys/fs/resctrl/info/L3/; ls
    
    bit_usage  cbm_mask  min_cbm_bits  num_closids  shareable_bits  sparse_masks
    Copy to Clipboard
  3. 查看 cbm_mask 文件的值。

    # cat cbm_mask
    
    ffff
    Copy to Clipboard

    这个值代表十六进制代码中的缓存位掩码。ffff 表示工作负载可以使用所有 16 位的缓存。

  4. 查看 "shareable_bits" 文件的值。

    # cat shareable_bits
    
    0
    Copy to Clipboard

    这个值代表了由其他执行进程(如 I/O)共享的 L3 缓存的分区,因此不应在独占缓存分区中使用。0 表示您可以使用所有 L3 缓存分区。

  5. 查看 schemata 文件,以查看全局缓存分配。

    # cat /sys/fs/resctrl/schemata
    
    L3:0=ffff;2=ffff;4=ffff;6=ffff;8=ffff;10=ffff;12=ffff;14=ffff
    Copy to Clipboard

    此输出显示,对于 L3 缓存分区,CPU 插槽 0、2、4、6、8、10、12 和 14 已完全分配给默认控制组。在本例中,CPU 插槽 16 到 19 被固定到 vCPU 0-3。

  6. 确定您要为实时应用程序设置的缓存分发。例如,对于实时应用程序和内务应用程序,平均分配 8 MB:

    • 实时应用程序的缓存位掩码为 ff00
    • housekeeping 应用程序的缓存位掩码为 00ff
  7. 使用日常进程所需的缓存分配来调整默认的 schemata 文件。例如,要将 8MB 分配给 CPU 套接字 8,请执行以下操作:

    # echo "L3:0=ffff;2=ffff;4=ffff;6=ffff;8=00ff;10=ffff;12=ffff;14=ffff" > /sys/fs/resctrl/schemata
    Copy to Clipboard
  8. 为实时进程创建特定的控制组,如 part1

    # mkdir /sys/fs/resctrl/part1
    Copy to Clipboard
  9. part1 控制组创建一个 schemata 文件,并将其设置为使用与内务缓存分配不冲突的缓存分配。

    # echo "L3:0=ffff;2=ffff;4=ffff;6=ffff;8=ff00;10=ffff;12=ffff;14=ffff" > /sys/fs/resctrl/part1/schemata
    Copy to Clipboard

    有了这个设置,L3 缓存 8 会将一半的缓存分配用于实时进程,其他一半用于内务进程。所有其他 L3 缓存都可以由实时进程和内务操作自由使用。

  10. 将固定到实时 vCPU 的 CPU (本例中为 17、18 和 19))分配给此控制组。

    # echo 17,18,19 > part1/cpus_list
    Copy to Clipboard

验证

  • 如果您之前测试了虚拟机延迟,请再次运行 cyclictest 工具。具体步骤请查看 Stress 测试实时虚拟化系统。

    如果最大延迟低于之前,则代表您已正确设置了缓存保护。

4.5. RHEL 实时客户机安装故障排除

实时主机上安装 RHEL 9 虚拟机(VM) 时,您可能会遇到以下错误之一。使用以下建议修复或临时解决这些问题。

  • 错误:主机不支持任何虚拟化选项

    • 确定在主机 BIOS 中启用了虚拟化
    • 检查主机上的 cpu 标志是否包含 Intel 的 vmx 或 AMD 的 svm

      $ cat /proc/cpuinfo | grep vmx
      Copy to Clipboard
    • 检查 lsmod 命令是否检测到 kvmkvm_intelkvm_amd 模块。

      $ lsmod | grep kvm
      Copy to Clipboard
    • 确保已安装了 kernel-rt-kvm 软件包。

      $ dnf info kernel-rt-kvm
      Copy to Clipboard
    • 检查 /dev/kvm 设备是否存在。
    • 运行 virt-host-validate 程序来检测任何其他问题。
    • 运行 kvm-unit-tests
  • 访问磁盘镜像时的权限相关问题

    • /etc/libvirt/qemu.conf 文件中,取消注释 group =user = 行。
    • 重启 virtqemud 服务。

      $ service virtqemud restart
      Copy to Clipboard

4.6. RHEL 实时客户机的延迟问题故障排除

要排除 RHEL 实时客户机操作系统的延迟,请通过运行 trace-cmd 测试为客户机生成内核追踪文件。之后,您可以使用此测试的输出来请求红帽的支持。

先决条件

  • 已安装 RHEL 9 虚拟机,并根据实时工作负载调整其配置。具体步骤请参阅 安装 RHEL 实时客户机操作系统
  • 您可以使用 SSH 连接到 guest。具体步骤请参阅 使用 SSH 连接到虚拟机
  • trace-cmd 工具安装在主机和客户机上。

    # dnf install trace-cmd
    Copy to Clipboard

流程

  1. 配置您要测试的虚拟机以使用 VSOCK 接口:

    1. 在主机上,使用 virsh edit 命令打开虚拟机的 XML 配置。
    2. 在配置的 &lt ;devices& gt; 部分添加以下行。

      <vsock model="virtio">
        <cid auto="no" address="3"/>
      Copy to Clipboard

      如果在多个虚拟机上执行测试,请为每个 虚拟机设置 不同的地址值。

    3. 保存并退出配置。
  2. 为确保追踪正常工作,请在主机上运行以下简短测试:这可防止客户机因为在 SCHED_FIFO 优先级运行的 vCPU 而变得无响应。

    1. 在主机上使用以下命令:

      # trace-cmd record -m 1000 -e kvm_exit
      Copy to Clipboard
    2. 大约 10 秒后,按 Ctrl-C 中止测试。
    3. 确保测试在同一目录中创建了一个 trace.dat 文件,且该文件不为空。
  3. 启动虚拟机。
  4. 在主机上,配置对虚拟机的无密码 SSH 访问:

    1. 获取虚拟机的 IP 地址。

      # virsh domifaddr <vm-name>
      
       Name       MAC address          Protocol     Address
      -------------------------------------------------------------------
       vnet0      52:54:00:6b:29:9f    ipv4         192.168.122.145/24
      Copy to Clipboard
    2. 将您的 SSH 公钥复制到虚拟机。

      # ssh-copy-id root@<vm-ip>
      Copy to Clipboard
    3. 可选:测试无密码登录到虚拟机:

      # ssh root@<vm-ip>
      Copy to Clipboard

      如果这样可以连接到客户机的 root 访问权限,则代表您已成功配置了无密码的 SSH。

  5. 在客户端操作系统中,在后台启动 trace-cmd 代理。

    # trace-cmd agent &
    Copy to Clipboard

    代理将在客户机上持续运行,并等待主机中的命令。

  6. 在主机上,使用 trace-cmd 命令,并调整虚拟机中 vCPU 固定配置的参数:

    # trace-cmd record --poll -m 1000 \
      -e <host-trace-points> \
      -f "cpu==<host_cpu_num> || cpu==<host_cpu_num> || cpu==<host_cpu_num>" \
      -A <guest-vsock-port> \
      -e <guest-trace-points> \
      -f "cpu==<guest_cpu_num> || cpu==<guest_cpu_num> || cpu==<guest_cpu_num>" \
      ssh root@<vm-ip> "<latency-test-command>"
    Copy to Clipboard

    按如下方式替换命令中的值:

    • <host-trace-points > 带有您要在主机上跟踪的 trace 事件,如 sched_switchreschedule_entry
    • <host_cpu_num > 带有配置 vCPU 的每个主机 CPU。
    • 使用您在上一步中配置的 VSOCK 端口。
    • 使用您要跟踪的 trace 事件 。最好地,它们与 < host-trace-points > 相同。
    • <vm-ip > 带有虚拟机的 IP 地址。
    • <latency-test-command > 带有您要执行的特定压力测试命令,如 Stress 测试实时虚拟化系统的详细情况。使用 cyclictest 过程时,还要添加 a- tracemark 参数。

    如果要同时测试多个虚拟机,请按如下所示调整命令:

    # trace-cmd record -m 1000 \
      -e <host-trace-points> \
      -A <guest1-vsock-port> -e <guest-trace-points> \
      -A <guest2-vsock-port> -e <guest-trace-points> \
      bash -c "ssh root@<vm1-ip> \
      \"<latency-test-command>\" \
      & ssh root@<vm2-ip> \
      \"<latency-test-command>\""
    Copy to Clipboard

    例如:

    # trace-cmd record --poll -m 1000 \
      -e sched_switch -e hrtimer_start -e hrtimer_expire_entry -e hrtimer_expire_exit -e irq_handler_entry -e local_timer_entry -e local_timer_exit -e reschedule_entry -e reschedule_exit -e call_function_entry -e call_function_exit -e call_function_single_entry -e call_function_single_exit -e irq_work_entry -e irq_work_exit -e tick_stop -e ipi_send_cpumask -e kvm_exit -e kvm_entry -e ipi_send_cpu -e csd_queue_cpu -e csd_function_entry -e csd_function_exit \
      -f "cpu==3 || cpu==5 || cpu==7 || cpu==9 || cpu==11 || cpu==13 || cpu==15 || cpu==17" \
      -A 3 \
      -e sched_switch -e hrtimer_start -e hrtimer_expire_entry -e hrtimer_expire_exit -e irq_handler_entry -e local_timer_entry -e local_timer_exit -e reschedule_entry -e reschedule_exit -e call_function_entry -e call_function_exit -e call_function_single_entry -e call_function_single_exit -e irq_work_entry -e irq_work_exit -e tick_stop -e ipi_send_cpumask -e kvm_exit -e kvm_entry -e ipi_send_cpu -e csd_queue_cpu -e csd_function_entry -e csd_function_exit \
      -f "cpu==2 || cpu==3 || cpu==4 || cpu==5 || cpu==6 || cpu==7 || cpu==8 || cpu==9" \
      ssh root@192.168.122.10 "cyclictest -m -q -p95 --policy=fifo -D 10min -h60 -t 8 -a 2,3,4,5,6,7,8,9 -i 200 -b 50 --mainaffinity 0,1 --tracemark"
    Copy to Clipboard

    这个命令执行以下操作:

    • 测试 IP 为 192.168.122.10 和 VSOCK 端口 3 的单个虚拟机
    • 使用与实时部署相关的典型追踪点。
    • 跟踪主机 CPU 3、5、7、9、11、13、15 和 17,vCPU 2-9 是 NUMA 固定。
    • 触发 cyclictest 达到 10 分钟。

    测试完成后,追踪数据会作为 trace.dat 文件和 trace-.dat 文件保存在主机上。

  7. trace-cmd 数据生成人类可读的报告。例如,如果虚拟机的 VSOCK 端口为 3:

    # trace-cmd report -i trace.dat -i trace-3.dat > kvm_rt_latency.log
    Copy to Clipboard

    如果您在多个虚拟机上执行测试,请为每个虚拟机创建一个报告:

    # trace-cmd report -i trace.dat -i trace-3.dat > kvm_rt_latency_1.log
    # trace-cmd report -i trace.dat -i trace-4.dat > kvm_rt_latency_2.log
    Copy to Clipboard
  8. 完成测试后,停止客户端操作系统中的 trace-cmd 代理:

    # pkill trace-cmd
    Copy to Clipboard
  9. 向红帽创建一个支持问题单,并附加前面步骤中获取的 trace 日志。

故障排除

如果追踪失败,请执行以下操作并重试:

  • 验证 vsock 是否在客户机中正确配置。
  • 确保 trace-cmd 代理在客户机中运行。
  • 确保主机有足够的磁盘空间用于追踪文件。最好会每分钟至少有 2 GB 的可用磁盘空间。
  • 验证虚拟机上的 vCPU 固定配置是否与您用于 trace-cmd 的参数匹配。要查看虚拟机配置的相关部分,请使用 virsh vcpupin < vm-name >。

法律通告

Copyright © 2025 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat