8.14. 高级虚拟机管理


8.14.1. 为虚拟机使用资源配额

为虚拟机创建和管理资源配额。

8.14.1.1. 为虚拟机设置资源配额限制

只有使用请求自动用于虚拟机 (VM) 的资源配额。如果您的资源配额使用限制,则必须为虚拟机手动设置资源限值。资源限值必须至少大于资源请求的 100 MiB。

流程

  1. 通过编辑 VirtualMachine 清单来为虚拟机设置限值。例如:

    apiVersion: kubevirt.io/v1
    kind: VirtualMachine
    metadata:
      name: with-limits
    spec:
      running: false
      template:
        spec:
          domain:
    # ...
            resources:
              requests:
                memory: 128Mi
              limits:
                memory: 256Mi  1
    1
    这个配置被支持,因为 limits.memory 值至少比 requests.memory 的值大 100Mi
  2. 保存 VirtualMachine 清单。

8.14.1.2. 其他资源

8.14.2. 为虚拟机指定节点

您可以使用节点放置规则将虚拟机放置到特定的节点上。

8.14.2.1. 关于虚拟机的节点放置

要确保虚拟机在适当的节点上运行,您可以配置节点放置规则。如果出现以下情况,您可能需要进行此操作:

  • 您有多台虚拟机。为确保容错,您希望它们在不同节点上运行。
  • 您有两个 chatty 虚拟机。为了避免冗余节点间路由,您希望虚拟机在同一节点上运行。
  • 您的虚拟机需要所有可用节点上不存在的特定硬件功能。
  • 您有一个 pod 可以向节点添加功能,并想将虚拟机放置到该节点上,以便它可以使用这些功能。
注意

虚拟机放置依赖于工作负载的现有节点放置规则。如果组件级别上的特定节点排除工作负载,则虚拟机无法放置在这些节点上。

您可以在 VirtualMachine 清单的 spec 字段中使用以下规则类型:

nodeSelector
允许将虚拟机调度到使用此字段中指定的键值对标记的节点上。节点必须具有与所有列出的对完全匹配的标签。
关联性

这可让您使用更具表达力的语法来设置与虚拟机匹配的规则。例如,您可以指定规则是首选项,而非硬要求,因此在规则不满足时仍然可以调度虚拟机。虚拟机放置支持 Pod 关联性、pod 反关联性和节点关联性。Pod 关联性适用于虚拟机,因为 VirtualMachine 工作负载类型基于 Pod 对象。

注意

关联性规则仅在调度期间应用。如果不再满足限制,OpenShift Container Platform 不会重新调度正在运行的工作负载。

容限(tolerations)
允许将虚拟机调度到具有匹配污点的节点。如果污点应用到某个节点,则该节点只接受容许该污点的虚拟机。

8.14.2.2. 节点放置示例

以下示例 YAML 文件片断使用 nodePlacementaffinitytolerations 字段为虚拟机自定义节点放置。

8.14.2.2.1. 示例:使用 nodeSelector 放置虚拟机节点

在本例中,虚拟机需要一个包含 example-key-1 = example-value-1example-key-2 = example-value-2 标签的元数据的节点。

警告

如果没有节点适合此描述,则不会调度虚拟机。

VM 清单示例

metadata:
  name: example-vm-node-selector
apiVersion: kubevirt.io/v1
kind: VirtualMachine
spec:
  template:
    spec:
      nodeSelector:
        example-key-1: example-value-1
        example-key-2: example-value-2
...

8.14.2.2.2. 示例:使用 pod 关联性和 pod 反关联性的虚拟机节点放置

在本例中,虚拟机必须调度到具有标签 example-key-1 = example-value-1 的正在运行的 pod 的节点上。如果没有在任何节点上运行这样的 pod,则不会调度虚拟机。

如果可能,虚拟机不会调度到具有标签 example-key-2 = example-value-2 的 pod 的节点上。但是,如果所有候选节点都有具有此标签的 pod,调度程序会忽略此约束。

VM 清单示例

metadata:
  name: example-vm-pod-affinity
apiVersion: kubevirt.io/v1
kind: VirtualMachine
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution: 1
      - labelSelector:
          matchExpressions:
          - key: example-key-1
            operator: In
            values:
            - example-value-1
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution: 2
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: example-key-2
              operator: In
              values:
              - example-value-2
          topologyKey: kubernetes.io/hostname
...

1
如果您使用 requiredDuringSchedulingIgnoredDuringExecution 规则类型,如果没有满足约束,则不会调度虚拟机。
2
如果您使用 preferredDuringSchedulingIgnoredDuringExecution 规则类型,只要满足所有必要的限制,仍会调度虚拟机(如果未满足约束)。
8.14.2.2.3. 示例:使用节点关联性进行虚拟机节点放置

在本例中,虚拟机必须调度到具有标签 example.io/example-key = example-value-1 或标签 example.io/example-key = example-value-2 的节点上。如果节点上只有一个标签,则会满足约束。如果没有标签,则不会调度虚拟机。

若有可能,调度程序会避免具有标签 example-node-label-key = example-node-label-value 的节点。但是,如果所有候选节点都具有此标签,调度程序会忽略此限制。

VM 清单示例

metadata:
  name: example-vm-node-affinity
apiVersion: kubevirt.io/v1
kind: VirtualMachine
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution: 1
        nodeSelectorTerms:
        - matchExpressions:
          - key: example.io/example-key
            operator: In
            values:
            - example-value-1
            - example-value-2
      preferredDuringSchedulingIgnoredDuringExecution: 2
      - weight: 1
        preference:
          matchExpressions:
          - key: example-node-label-key
            operator: In
            values:
            - example-node-label-value
...

1
如果您使用 requiredDuringSchedulingIgnoredDuringExecution 规则类型,如果没有满足约束,则不会调度虚拟机。
2
如果您使用 preferredDuringSchedulingIgnoredDuringExecution 规则类型,只要满足所有必要的限制,仍会调度虚拟机(如果未满足约束)。
8.14.2.2.4. 示例:带有容限的虚拟机节点放置

在本例中,为虚拟机保留的节点已使用 key=virtualization:NoSchedule 污点标记。由于此虚拟机具有匹配的容限,它可以调度到污点节点上。

注意

容许污点的虚拟机不需要调度到具有该污点的节点。

VM 清单示例

metadata:
  name: example-vm-tolerations
apiVersion: kubevirt.io/v1
kind: VirtualMachine
spec:
  tolerations:
  - key: "key"
    operator: "Equal"
    value: "virtualization"
    effect: "NoSchedule"
...

8.14.2.3. 其他资源

8.14.3. 配置证书轮转

配置证书轮转参数以替换现有证书。

8.14.3.1. 配置证书轮转

您可以在 web 控制台中的 OpenShift Virtualization 安装过程中,或者在安装 HyperConverged 自定义资源(CR)后完成此操作。

流程

  1. 运行以下命令打开 HyperConverged CR:

    $ oc edit hco -n openshift-cnv kubevirt-hyperconverged
  2. 按照以下示例所示,编辑 spec.certConfig 字段。要避免系统过载,请确保所有值都大于或等于 10 分钟。将所有值显示为符合 golang ParseDuration 格式的字符串

    apiVersion: hco.kubevirt.io/v1beta1
    kind: HyperConverged
    metadata:
     name: kubevirt-hyperconverged
     namespace: openshift-cnv
    spec:
      certConfig:
        ca:
          duration: 48h0m0s
          renewBefore: 24h0m0s 1
        server:
          duration: 24h0m0s  2
          renewBefore: 12h0m0s  3
    1
    ca.renewBefore 的值必须小于或等于 ca.duration 的值。
    2
    server.duration 的值必须小于或等于 ca.duration 的值。
    3
    server.renewBefore 的值必须小于或等于 server.duration 的值。
  3. 将 YAML 文件应用到集群。

8.14.3.2. 证书轮转参数故障排除

删除一个或多个 certConfig 值会导致它们恢复到默认值,除非默认值与以下条件之一冲突:

  • ca.renewBefore 的值必须小于或等于 ca.duration 的值。
  • server.duration 的值必须小于或等于 ca.duration 的值。
  • server.renewBefore 的值必须小于或等于 server.duration 的值。

如果默认值与这些条件冲突,您将收到错误。

如果您删除了以下示例中的 server.duration 值,则默认值 24h0m0s 大于 ca.duration 的值,并与指定条件冲突。

示例

certConfig:
   ca:
     duration: 4h0m0s
     renewBefore: 1h0m0s
   server:
     duration: 4h0m0s
     renewBefore: 4h0m0s

这会生成以下出错信息:

error: hyperconvergeds.hco.kubevirt.io "kubevirt-hyperconverged" could not be patched: admission webhook "validate-hco.kubevirt.io" denied the request: spec.certConfig: ca.duration is smaller than server.duration

错误消息仅提及第一个冲突。在继续操作前,查看所有 certConfig 值。

8.14.4. 自动执行管理任务

您可以使用 Red Hat Ansible Automation Platform 自动完成 OpenShift Virtualization 管理任务。通过使用 Ansible Playbook 创建新虚拟机来了解基础知识。

8.14.4.1. 关于 Red Hat Ansible Automation

Ansible 是用于配置系统、部署软件和执行滚动更新的自动化工具。Ansible 包含对 OpenShift Virtualization 的支持,Ansible 模块可用于自动执行集群管理任务,如模板、持久性卷声明和虚拟机操作。

Ansible 提供了一种方式来自动执行 OpenShift Virtualization 管理,您也可以使用 oc CLI 工具或 API 来完成此项操作。Ansible 独具特色,因其可用于将 KubeVirt 模块与其他 Ansible 模块集成。

8.14.4.2. 自动创建虚拟机

使用 Red Hat Ansible Automation Platform,您可使用 kubevirt_vm Ansible Playbook 在 OpenShift Container Platform 集群中创建虚拟机。

先决条件

流程

  1. 编辑 Ansible Playbook YAML 文件,以便其包含 kubevirt_vm 任务:

      kubevirt_vm:
        namespace:
        name:
        cpu_cores:
        memory:
        disks:
          - name:
            volume:
              containerDisk:
                image:
            disk:
              bus:
    注意

    该片断仅包含 playbook 的 kubevirt_vm 部分。

  2. 编辑这些值以反应您要创建的虚拟机,包括 namespacecpu_cores 数、memory 以及 disks。例如:

      kubevirt_vm:
        namespace: default
        name: vm1
        cpu_cores: 1
        memory: 64Mi
        disks:
          - name: containerdisk
            volume:
              containerDisk:
                image: kubevirt/cirros-container-disk-demo:latest
            disk:
              bus: virtio
  3. 如果希望虚拟机创建后立即启动,请向 YAML 文件添加 state: running。例如:

      kubevirt_vm:
        namespace: default
        name: vm1
        state: running 1
        cpu_cores: 1
    1
    将该值改为 state: absent 会删除已存在的虚拟机。
  4. 运行 ansible-playbook 命令,将 playbook 文件名用作唯一参数:

    $ ansible-playbook create-vm.yaml
  5. 查看输出以确定该 play 是否成功:

    输出示例

    (...)
    TASK [Create my first VM] ************************************************************************
    changed: [localhost]
    
    PLAY RECAP ********************************************************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

  6. 如果您未在 playbook 文件中包含 state: running,而您希望立即启动虚拟机,请编辑文件使其包含 state: running 并再次运行 playbook:

    $ ansible-playbook create-vm.yaml

要验证是否已创建虚拟机,请尝试访问虚拟机控制台

8.14.4.3. 示例:用于创建虚拟机的 Ansible Playbook

您可使用 kubevirt_vm Ansible Playbook 自动创建虚拟机。

以下 YAML 文件是一个 kubevirt_vm playbook 示例。如果运行 playbook,其中会包含必须替换为您自己的信息的样本值。

---
- name: Ansible Playbook 1
  hosts: localhost
  connection: local
  tasks:
    - name: Create my first VM
      kubevirt_vm:
        namespace: default
        name: vm1
        cpu_cores: 1
        memory: 64Mi
        disks:
          - name: containerdisk
            volume:
              containerDisk:
                image: kubevirt/cirros-container-disk-demo:latest
            disk:
              bus: virtio

8.14.5. 将 EFI 模式用于虚拟机

您可以使用可扩展固件界面(EFI)模式引导虚拟机(VM)。

8.14.5.1. 关于虚拟机的 EFI 模式

像传统的 BIOS 一样,可扩展固件界面(EFI)在计算机启动时初始化硬件组件和操作系统镜像文件。EFI 支持比 BIOS 更先进的功能和自定义选项,从而可以更快地启动时间。

它将初始化和启动的所有信息保存在带有 .efi 扩展的文件中,该扩展被保存在名为 EFI 系统分区(ESP)的特殊分区中。ESP 还包含安装在计算机上的操作系统的引导装载程序程序。

注意

在使用 EFI 模式时,OpenShift Virtualization 只支持使用安全引导机制的虚拟机(VM)。如果没有启用安全引导机制,则虚拟机会重复崩溃。但是,虚拟机可能不支持安全引导。在引导虚拟机前,请通过检查虚拟机设置来验证它是否支持安全引导。

8.14.5.2. 在 EFI 模式中引导虚拟机

您可以通过编辑 VM 或 VMI 清单,将虚拟机配置为在 EFI 模式中引导。

先决条件

  • 安装 OpenShift CLI (oc) 。

流程

  1. 创建定义虚拟机对象或虚拟机实例(VMI)对象的 YAML 文件。使用示例 YAML 文件的固件小节:

    使用安全引导活跃在 EFI 模式中引导

      apiversion: kubevirt.io/v1
      kind: VirtualMachineInstance
      metadata:
        labels:
          special: vmi-secureboot
        name: vmi-secureboot
      spec:
        domain:
          devices:
            disks:
            - disk:
                bus: virtio
              name: containerdisk
          features:
            acpi: {}
            smm:
              enabled: true 1
          firmware:
            bootloader:
              efi:
                secureBoot: true 2
    ...

    1
    OpenShift Virtualization 需要为 EFI 模式的安全引导启用系统管理模式(SMM)。
    2
    在使用 EFI 模式时,OpenShift Virtualization 只支持使用安全引导机制的虚拟机(VM)。如果没有启用安全引导机制,则虚拟机会重复崩溃。但是,虚拟机可能不支持安全引导。在引导虚拟机前,请通过检查虚拟机设置来验证它是否支持安全引导。
  2. 运行以下命令,将清单应用到集群:

    $ oc create -f <file_name>.yaml

8.14.6. 为虚拟机配置 PXE 启动

OpenShift Virtualization 中提供 PXE 启动或网络启动。网络启动支持计算机启动和加载操作系统或其他程序,无需本地连接的存储设备。例如,在部署新主机时,您可使用 PXE 启动从 PXE 服务器中选择所需操作系统镜像。

8.14.6.1. 先决条件

  • Linux 网桥 必须已连接
  • PXE 服务器必须作为网桥连接至相同 VLAN。

8.14.6.2. 使用指定的 MAC 地址的 PXE 引导

作为管理员,您可首先为您的 PXE 网络创建 NetworkAttachmentDefinition 对象,以此通过网络引导客户端。然后在启动虚拟机实例前,在您的虚拟机实例配置文件中引用网络附加定义。如果 PXE 服务器需要,您还可在虚拟机实例配置文件中指定 MAC 地址。

先决条件

  • 必须已连接 Linux 网桥。
  • PXE 服务器必须作为网桥连接至相同 VLAN。

流程

  1. 在集群上配置 PXE 网络:

    1. 为 PXE 网络 pxe-net-conf 创建网络附加定义文件:

      apiVersion: "k8s.cni.cncf.io/v1"
      kind: NetworkAttachmentDefinition
      metadata:
        name: pxe-net-conf
      spec:
        config: '{
          "cniVersion": "0.3.1",
          "name": "pxe-net-conf",
          "plugins": [
            {
              "type": "cnv-bridge",
              "bridge": "br1",
              "vlan": 1 1
            },
            {
              "type": "cnv-tuning" 2
            }
          ]
        }'
      1
      可选: VLAN 标签。
      2
      cnv-tuning 插件为自定义 MAC 地址提供支持。
      注意

      虚拟机实例将通过所请求的 VLAN 的访问端口附加到网桥 br1

  2. 使用您在上一步中创建的文件创建网络附加定义:

    $ oc create -f pxe-net-conf.yaml
  3. 编辑虚拟机实例配置文件以包括接口和网络的详情。

    1. 如果 PXE 服务器需要,请指定网络和 MAC 地址。如果未指定 MAC 地址,则会自动分配一个值。

      请确保 bootOrder 设置为 1,以便该接口先启动。在本例中,该接口连接到了名为 <pxe-net> 的网络中:

      interfaces:
      - masquerade: {}
        name: default
      - bridge: {}
        name: pxe-net
        macAddress: de:00:00:00:00:de
        bootOrder: 1
      注意

      启动顺序对于接口和磁盘全局通用。

    2. 为磁盘分配一个启动设备号,以确保置备操作系统后能够正确启动。

      将磁盘 bootOrder 值设置为 2

      devices:
        disks:
        - disk:
            bus: virtio
          name: containerdisk
          bootOrder: 2
    3. 指定网络连接到之前创建的网络附加定义。在这种情况下,<pxe-net> 连接到名为 <pxe-net-conf> 的网络附加定义:

      networks:
      - name: default
        pod: {}
      - name: pxe-net
        multus:
          networkName: pxe-net-conf
  4. 创建虚拟机实例:

    $ oc create -f vmi-pxe-boot.yaml

输出示例

  virtualmachineinstance.kubevirt.io "vmi-pxe-boot" created

  1. 等待虚拟机实例运行:

    $ oc get vmi vmi-pxe-boot -o yaml | grep -i phase
      phase: Running
  2. 使用 VNC 查看虚拟机实例:

    $ virtctl vnc vmi-pxe-boot
  3. 查看启动屏幕,验证 PXE 启动是否成功。
  4. 登录虚拟机实例:

    $ virtctl console vmi-pxe-boot
  5. 验证虚拟机上的接口和 MAC 地址,并验证连接到网桥的接口是否具有指定的 MAC 地址。在本例中,我们使用了 eth1 进行 PXE 启动,无需 IP 地址。另一接口 eth0 从 OpenShift Container Platform 获取 IP 地址。

    $ ip addr

输出示例

...
3. eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
   link/ether de:00:00:00:00:de brd ff:ff:ff:ff:ff:ff

8.14.6.3. 模板:用于 PXE 引导的虚拟机实例配置文件

apiVersion: kubevirt.io/v1
kind: VirtualMachineInstance
metadata:
  creationTimestamp: null
  labels:
    special: vmi-pxe-boot
  name: vmi-pxe-boot
spec:
  domain:
    devices:
      disks:
      - disk:
          bus: virtio
        name: containerdisk
        bootOrder: 2
      - disk:
          bus: virtio
        name: cloudinitdisk
      interfaces:
      - masquerade: {}
        name: default
      - bridge: {}
        name: pxe-net
        macAddress: de:00:00:00:00:de
        bootOrder: 1
    machine:
      type: ""
    resources:
      requests:
        memory: 1024M
  networks:
  - name: default
    pod: {}
  - multus:
      networkName: pxe-net-conf
    name: pxe-net
  terminationGracePeriodSeconds: 0
  volumes:
  - name: containerdisk
    containerDisk:
      image: kubevirt/fedora-cloud-container-disk-demo
  - cloudInitNoCloud:
      userData: |
        #!/bin/bash
        echo "fedora" | passwd fedora --stdin
    name: cloudinitdisk
status: {}

8.14.7. 管理客户机内存

如果要调整客户机内存设置以适应特定用例,可通过编辑客户机的 YAML 配置文件来实现。OpenShift Virtualization 可用于配置客户机内存过量使用,以及禁用客户机内存开销核算。

警告

以下流程会增加虚拟机进程因内存压力而被终止的机率。只有当您了解风险时方可继续。

8.14.7.1. 配置客户机内存过量使用

如果您的虚拟工作负载需要的内存超过可用内存,您可利用内存过量使用来为您的虚拟机实例(VMI)分配全部或大部分主机内存。启用“内存过量使用”意味着您可以最大程度利用通常为主机保留的资源。

例如,如果主机具有 32 Gb RAM,则可利用内存过量功能,运行 8 个每个分配了 4GB RAM 的虚拟机(VM)。该分配方案假设所有虚拟机不会同时使用分配给它们的所有内存。

重要

内存过量使用增加虚拟机进程因内存压力(OOM 终止)被终止的可能性。

虚拟机被 OOM 终止的可能性取决于您的具体配置、节点内存、可用 swap 空间、虚拟机内存消耗、使用内核相同的页面合并(KSM)以及其它因素。

流程

  1. 要明确告知虚拟机实例它的可用内存超过集群请求内存,请编辑虚拟机配置文件,并将 spec.domain.memory.guest 设置为超过 spec.domain.resources.requests.memory 的值。这一过程即为“内存过量使用”。

    在本例中,对集群的请求内存为 1024M,但虚拟机实例被告知它有 2048M 可用。只要相关的节点上有足够的可用内存,虚拟机实例最多可消耗 2048M 内存。

    kind: VirtualMachine
    spec:
      template:
        domain:
        resources:
            requests:
              memory: 1024M
        memory:
            guest: 2048M
    注意

    如果节点面临内存压力,则适用于 pod 的驱除规则也适用于虚拟机实例。

  2. 创建虚拟机:

    $ oc create -f <file_name>.yaml

8.14.7.2. 禁用客户机内存开销核算

除了您所请求的内存量之外,每个虚拟机实例还会额外请求少量内存。这部分额外内存将用于打包每个 VirtualMachineInstance 进程的基础结构。

虽然通常不建议这么设置,但可以通过禁用客户机内存开销核算来提高节点上的虚拟机实例密度。

重要

禁用客户机内存开销核算会增加虚拟机进程因内存压力(OOM 被终止)被终止的可能性。

虚拟机被 OOM 终止的可能性取决于您的具体配置、节点内存、可用 swap 空间、虚拟机内存消耗、使用内核相同的页面合并(KSM)以及其它因素。

流程

  1. 要禁用客户机内存开销核算,请编辑 YAML 配置文件并将 overcommitGuestOverhead 值设置为 true。默认禁用此参数。

    kind: VirtualMachine
    spec:
      template:
        domain:
        resources:
            overcommitGuestOverhead: true
            requests:
              memory: 1024M
    注意

    如果启用 overcommitGuestOverhead,则会在内存限值中添加客户机开销(如果存在)。

  2. 创建虚拟机:

    $ oc create -f <file_name>.yaml

8.14.8. 在虚拟机中使用巨页

您可以使用巨页作为集群中虚拟机的后备内存。

8.14.8.1. 先决条件

8.14.8.2. 巨页的作用

内存在块(称为页)中进行管理。在大多数系统中,页的大小为 4Ki。1Mi 内存相当于 256 个页,1Gi 内存相当于 256,000 个页。CPU 有内置的内存管理单元,可在硬件中管理这些页的列表。Translation Lookaside Buffer (TLB) 是虚拟页到物理页映射的小型硬件缓存。如果在硬件指令中包括的虚拟地址可以在 TLB 中找到,则其映射信息可以被快速获得。如果没有包括在 TLN 中,则称为 TLB miss。系统将会使用基于软件的,速度较慢的地址转换机制,从而出现性能降低的问题。因为 TLB 的大小是固定的,因此降低 TLB miss 的唯一方法是增加页的大小。

巨页指一个大于 4Ki 的内存页。在 x86_64 构架中,有两个常见的巨页大小: 2Mi 和 1Gi。在其它构架上的大小会有所不同。要使用巨页,必须写相应的代码以便应用程序了解它们。Transparent Huge Pages(THP)试图在应用程序不需要了解的情况下自动管理巨页,但这个技术有一定的限制。特别是,它的页大小会被限为 2Mi。当有较高的内存使用率时,THP 可能会导致节点性能下降,或出现大量内存碎片(因为 THP 的碎片处理)导致内存页被锁定。因此,有些应用程序可能更适用于(或推荐)使用预先分配的巨页,而不是 THP。

在 OpenShift Virtualization 中,可将虚拟机配置为消耗预先分配的巨页。

8.14.8.3. 为虚拟机配置巨页

您可以在虚拟机配置中包括 memory.hugepages.pageSizeresources.requests.memory 参数来配置虚拟机来使用预分配的巨页。

内存请求必须按页大小分离。例如,您不能对大小为 1Gi 的页请求 500Mi 内存。

注意

主机的内存布局和客户端操作系统不相关。虚拟机清单中请求的巨页适用于 QEMU。客户端中的巨页只能根据虚拟机实例的可用内存量来配置。

如果您编辑了正在运行的虚拟机,则必须重启虚拟机才能使更改生效。

先决条件

  • 节点必须配置预先分配的巨页。

流程

  1. 在虚拟机配置中,把 resources.requests.memorymemory.hugepages.pageSize 参数添加到 spec.domain。以下配置片段适用于请求总计 4Gi 内存的虚拟机,页面大小为 1Gi:

    kind: VirtualMachine
    ...
    spec:
      domain:
        resources:
          requests:
            memory: "4Gi" 1
        memory:
          hugepages:
            pageSize: "1Gi" 2
    ...
    1
    为虚拟机请求的总内存量。这个值必须可以被按页大小整除。
    2
    每个巨页的大小。x86_64 架构的有效值为 1Gi2Mi。页面大小必须小于请求的内存。
  2. 应用虚拟机配置:

    $ oc apply -f <virtual_machine>.yaml

8.14.9. 为虚拟机启用专用资源

要提高性能,您可以将节点的资源(如 CPU)专用于特定的一个虚拟机。

8.14.9.1. 关于专用资源

当为您的虚拟机启用专用资源时,您的工作负载将会在不会被其他进程使用的 CPU 上调度。通过使用专用资源,您可以提高虚拟机性能以及延迟预测的准确性。

8.14.9.2. 先决条件

  • 节点上必须配置 CPU Manager。在调度虚拟机工作负载前,请确认节点具有 cpumanager = true 标签。
  • 虚拟机必须关机。

8.14.9.3. 为虚拟机启用专用资源

您可以在 Details 选项卡中为虚拟机启用专用资源。使用红帽模板或向导创建的虚拟机可使用专用资源启用。

流程

  1. 从侧边菜单中选择 Workloads Virtual Machines
  2. 选择一个虚拟机以打开 Virtual Machine 选项卡。
  3. Details 标签页。
  4. Dedicated Resources 项右面的铅笔标签打开 Dedicated Resources 窗口。
  5. 选择 Schedule this workload with dedicated resources (guaranteed policy)
  6. Save

8.14.10. 调度虚拟机

在确保虚拟机的 CPU 模型和策略属性与节点支持的 CPU 模型和策略属性兼容的情况下,可在节点上调度虚拟机(VM)。

8.14.10.1. 了解策略属性

您可以指定策略属性和在虚拟机调度到节点上时匹配的 CPU 功能来调度虚拟机(VM)。为虚拟机指定的策略属性决定了如何在节点上调度该虚拟机。

策略属性描述

force

VM 被强制调度到某个节点上。即使主机 CPU 不支持虚拟机的 CPU,也是如此。

require

在虚拟机没有使用特定 CPU 模型和功能规格配置时,应用于虚拟机的默认策略。如果节点没有配置为支持使用此默认策略属性或其他策略属性的 CPU 节点发现,则虚拟机不会调度到该节点上。主机 CPU 必须支持虚拟机的 CPU,或者虚拟机监控程序必须可以模拟支持的 CPU 模型。

optional

如果主机物理机器 CPU 支持该虚拟机,则虚拟机会被添加到节点。

disable

无法通过 CPU 节点发现调度虚拟机。

forbid

即使主机 CPU 支持该功能,且启用了 CPU 节点发现,也不会调度虚拟机。

8.14.10.2. 设置策略属性和 CPU 功能

您可以为每个虚拟机(VM)设置策略属性和 CPU 功能,以确保根据策略和功能在节点上调度该功能。验证您设置的 CPU 功能以确保主机 CPU 支持或者虚拟机监控程序模拟该功能。

流程

  • 编辑虚拟机配置文件的 domain spec。以下示例设置了虚拟机实例(VMI)的 CPU 功能和 require 策略:

    apiVersion: kubevirt.io/v1
    kind: VirtualMachine
    metadata:
      name: myvmi
    spec:
      domain:
        cpu:
          features:
          - name: apic 1
            policy: require 2
    1
    VM 或 VMI 的 CPU 功能名称。
    2
    VM 或 VMI 的策略属性。

8.14.10.3. 使用支持的 CPU 型号调度虚拟机

您可以为虚拟机(VM)或虚拟机实例(VMI)配置 CPU 型号,将其调度到支持其 CPU 模型的节点。

流程

  • 编辑虚拟机配置文件的 domain spec。以下示例显示了为 VMI 定义的特定 CPU 模型:

    apiVersion: kubevirt.io/v1
    kind: VirtualMachineInstance
    metadata:
      name: myvmi
    spec:
      domain:
        cpu:
          model: Conroe 1
    1
    VMI 的 CPU 模型。

8.14.10.4. 使用主机模型调度虚拟机

当将虚拟机(VM)的 CPU 模型设置为 host-model 时,虚拟机会继承调度节点的 CPU 模型。

流程

  • 编辑虚拟机配置文件的 domain spec。以下示例显示了为虚拟机实例(VMI)指定了 host-model

    apiVersion: kubevirt/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      name: myvmi
    spec:
      domain:
        cpu:
          model: host-model 1
    1
    继承调度节点的 CPU 模型的 VM 或 VMI。

8.14.11. 配置 PCI 透传

借助 Peripheral Component Interconnect(PCI)透传功能,您可以从虚拟机访问和管理硬件设备。配置 PCI 透传后,PCI 设备的功能就如同它们实际上附加到客户机操作系统上一样。

集群管理员可以使用 oc CLI 来公开和管理集群中允许在集群中使用的主机设备。

8.14.11.1. 关于为 PCI 透传准备主机设备

要使用 CLI 为 PCI 透传准备主机设备,请创建一个 MachineConfig 对象并添加内核参数,以启用输入输出内存管理单元(IOMMU)。将 PCI 设备绑定到虚拟功能 I/O(VFIO)驱动程序,然后通过编辑 HyperConverged 自定义资源(CR)的 allowedHostDevices 字段在集群中公开它。首次安装 OpenShift Virtualization Operator 时,allowedHostDevices 列表为空。

要使用 CLI 从集群中删除 PCI 主机设备,可从 HyperConverged CR 中删除 PCI 设备信息。

8.14.11.1.1. 添加内核参数以启用 IOMMU 驱动程序

要在内核中启用 IOMMU(Input-Output Memory Management Unit)驱动程序,请创建 MachineConfig 对象并添加内核参数。

先决条件

  • 正常运行的 OpenShift 容器平台集群的管理特权。
  • Intel 或 AMD CPU 硬件。
  • 启用用于直接 I/O 扩展的 Intel 虚拟化技术或 BIOS 中的 AMD IOMMU(基本输入/输出系统)。

流程

  1. 创建用于标识内核参数的 MachineConfig 对象。以下示例显示了 Intel CPU 的内核参数。

    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfig
    metadata:
      labels:
        machineconfiguration.openshift.io/role: worker 1
      name: 100-worker-iommu 2
    spec:
      config:
        ignition:
          version: 3.2.0
      kernelArguments:
          - intel_iommu=on 3
    ...
    1
    仅将新内核参数应用到 worker 节点。
    2
    name 表示此内核参数(100)在机器配置及其目的中的排名。如果您有 AMD CPU,请将内核参数指定为 amd_iommu=on
    3
    将内核参数标识为 Intel CPU 的 intel_iommu
  2. 创建新的 MachineConfig 对象:

    $ oc create -f 100-worker-kernel-arg-iommu.yaml

验证

  • 验证是否添加了新的 MachineConfig 对象。

    $ oc get MachineConfig
8.14.11.1.2. 将 PCI 设备绑定到 VFIO 驱动程序

要将 PCI 设备绑定到 VFIO(虚拟功能 I/O)驱动程序,请从每个设备获取 vendor-IDdevice-ID 的值,并创建值的列表。将这个列表添加到 MachineConfig 对象。MachineConfig Operator 在带有 PCI 设备的节点上生成 /etc/modprobe.d/vfio.conf,并将 PCI 设备绑定到 VFIO 驱动程序。

先决条件

  • 您添加了内核参数来为 CPU 启用 IOMMU。

流程

  1. 运行 lspci 命令,以获取 PCI 设备的 vendor-IDdevice-ID

    $ lspci -nnv | grep -i nvidia

    输出示例

    02:01.0 3D controller [0302]: NVIDIA Corporation GV100GL [Tesla V100 PCIe 32GB] [10de:1eb8] (rev a1)

  2. 创建 Butane 配置文件 100-worker-vfiopci.bu,将 PCI 设备绑定到 VFIO 驱动程序。

    注意

    有关 Butane 的信息,请参阅"使用 Butane 创建机器配置"。

    示例

    variant: openshift
    version: 4.8.0
    metadata:
      name: 100-worker-vfiopci
      labels:
        machineconfiguration.openshift.io/role: worker 1
    storage:
      files:
      - path: /etc/modprobe.d/vfio.conf
        mode: 0644
        overwrite: true
        contents:
          inline: |
            options vfio-pci ids=10de:1eb8 2
      - path: /etc/modules-load.d/vfio-pci.conf 3
        mode: 0644
        overwrite: true
        contents:
          inline: vfio-pci

    1
    仅将新内核参数应用到 worker 节点。
    2
    指定之前确定的 vendor-ID 值(10de)和 device-ID 值(1eb8)来将单个设备绑定到 VFIO 驱动程序。您可以使用其供应商和设备信息添加多个设备列表。
    3
    在 worker 节点上载入 vfio-pci 内核模块的文件。
  3. 使用 Butane 生成 MachineConfig 对象文件 100-worker-vfiopci.yaml,包含要发送到 worker 节点的配置:

    $ butane 100-worker-vfiopci.bu -o 100-worker-vfiopci.yaml
  4. MachineConfig 对象应用到 worker 节点:

    $ oc apply -f 100-worker-vfiopci.yaml
  5. 验证 MachineConfig 对象是否已添加。

    $ oc get MachineConfig

    输出示例

    NAME                             GENERATEDBYCONTROLLER                      IGNITIONVERSION  AGE
    00-master                        d3da910bfa9f4b599af4ed7f5ac270d55950a3a1   3.2.0            25h
    00-worker                        d3da910bfa9f4b599af4ed7f5ac270d55950a3a1   3.2.0            25h
    01-master-container-runtime      d3da910bfa9f4b599af4ed7f5ac270d55950a3a1   3.2.0            25h
    01-master-kubelet                d3da910bfa9f4b599af4ed7f5ac270d55950a3a1   3.2.0            25h
    01-worker-container-runtime      d3da910bfa9f4b599af4ed7f5ac270d55950a3a1   3.2.0            25h
    01-worker-kubelet                d3da910bfa9f4b599af4ed7f5ac270d55950a3a1   3.2.0            25h
    100-worker-iommu                                                            3.2.0            30s
    100-worker-vfiopci-configuration                                            3.2.0            30s

验证

  • 验证是否已加载 VFIO 驱动程序。

    $ lspci -nnk -d 10de:

    输出确认使用了 VFIO 驱动程序。

    输出示例

    04:00.0 3D controller [0302]: NVIDIA Corporation GP102GL [Tesla P40] [10de:1eb8] (rev a1)
            Subsystem: NVIDIA Corporation Device [10de:1eb8]
            Kernel driver in use: vfio-pci
            Kernel modules: nouveau

8.14.11.1.3. 使用 CLI 在集群中公开 PCI 主机设备

要在集群中公开 PCI 主机设备,将 PCI 设备的详细信息添加到 HyperConverged 自定义资源(CR)的 spec.permittedHostDevices.pciHostDevices 数组中。

流程

  1. 运行以下命令,在默认编辑器中编辑 HyperConverged CR:

    $ oc edit hyperconverged kubevirt-hyperconverged -n openshift-cnv
  2. 将 PCI 设备信息添加到 spec.percommitHostDevices.pciHostDevices 数组。例如:

    配置文件示例

    apiVersion: hco.kubevirt.io/v1
    kind: HyperConverged
    metadata:
      name: kubevirt-hyperconverged
      namespace: openshift-cnv
    spec:
      permittedHostDevices: 1
        pciHostDevices: 2
        - pciDeviceSelector: "10DE:1DB6" 3
          resourceName: "nvidia.com/GV100GL_Tesla_V100" 4
        - pciDeviceSelector: "10DE:1EB8"
          resourceName: "nvidia.com/TU104GL_Tesla_T4"
        - pciDeviceSelector: "8086:6F54"
          resourceName: "intel.com/qat"
          externalResourceProvider: true 5
    ...

    1
    允许在集群中使用的主机设备。
    2
    节点上可用的 PCI 设备列表。
    3
    标识 PCI 设备所需的 vendor-IDdevice-ID
    4
    PCI 主机设备的名称。
    5
    可选:将此字段设置为 true 表示资源由外部设备插件提供。OpenShift Virtualization 允许在集群中使用这个设备,但会把分配和监控留给外部设备插件。
    注意

    上例代码片段显示有两个 PCI 主机设备,名为 nvidia.com/GV100GL_Tesla_V100nvidia.com/TU104GL_Tesla_Tesla_T4。它们被添加到 HyperConverged CR 中的允许主机设备列表中。这些设备已经过测试和验证以用于 OpenShift Virtualization。

  3. 保存更改并退出编辑器。

验证

  • 运行以下命令,验证 PCI 主机设备是否已添加到节点。示例输出显示,每个设备都与 nvidia.com/GV100GL_Tesla_V100nvidia.com/TU104GL_Tesla_T4intel.com/qat 资源名称关联。

    $ oc describe node <node_name>

    输出示例

    Capacity:
      cpu:                            64
      devices.kubevirt.io/kvm:        110
      devices.kubevirt.io/tun:        110
      devices.kubevirt.io/vhost-net:  110
      ephemeral-storage:              915128Mi
      hugepages-1Gi:                  0
      hugepages-2Mi:                  0
      memory:                         131395264Ki
      nvidia.com/GV100GL_Tesla_V100   1
      nvidia.com/TU104GL_Tesla_T4     1
      intel.com/qat:                  1
      pods:                           250
    Allocatable:
      cpu:                            63500m
      devices.kubevirt.io/kvm:        110
      devices.kubevirt.io/tun:        110
      devices.kubevirt.io/vhost-net:  110
      ephemeral-storage:              863623130526
      hugepages-1Gi:                  0
      hugepages-2Mi:                  0
      memory:                         130244288Ki
      nvidia.com/GV100GL_Tesla_V100   1
      nvidia.com/TU104GL_Tesla_T4     1
      intel.com/qat:                  1
      pods:                           250

8.14.11.1.4. 使用 CLI 从集群中删除 PCI 主机设备

要从集群中删除 PCI 主机设备,请从 HyperConverged 自定义资源(CR)中删除该设备的信息。

流程

  1. 运行以下命令,在默认编辑器中编辑 HyperConverged CR:

    $ oc edit hyperconverged kubevirt-hyperconverged -n openshift-cnv
  2. 通过删除相应设备的 pciDeviceSelectorresourceNameexternalResourceProvider(如果适用)字段来从 spec.permittedHostDevices.pciHostDevices 阵列中删除 PCI 设备信息。在本例中,intel.com/qat 资源已被删除。

    配置文件示例

    apiVersion: hco.kubevirt.io/v1
    kind: HyperConverged
    metadata:
      name: kubevirt-hyperconverged
      namespace: openshift-cnv
    spec:
      permittedHostDevices:
        pciHostDevices:
        - pciDeviceSelector: "10DE:1DB6"
          resourceName: "nvidia.com/GV100GL_Tesla_V100"
        - pciDeviceSelector: "10DE:1EB8"
          resourceName: "nvidia.com/TU104GL_Tesla_T4"
    ...

  3. 保存更改并退出编辑器。

验证

  • 运行以下命令,验证 PCI 主机设备已从节点移除。示例输出显示,与 intel.com/qat 资源名称关联的设备为零。

    $ oc describe node <node_name>

    输出示例

    Capacity:
      cpu:                            64
      devices.kubevirt.io/kvm:        110
      devices.kubevirt.io/tun:        110
      devices.kubevirt.io/vhost-net:  110
      ephemeral-storage:              915128Mi
      hugepages-1Gi:                  0
      hugepages-2Mi:                  0
      memory:                         131395264Ki
      nvidia.com/GV100GL_Tesla_V100   1
      nvidia.com/TU104GL_Tesla_T4     1
      intel.com/qat:                  0
      pods:                           250
    Allocatable:
      cpu:                            63500m
      devices.kubevirt.io/kvm:        110
      devices.kubevirt.io/tun:        110
      devices.kubevirt.io/vhost-net:  110
      ephemeral-storage:              863623130526
      hugepages-1Gi:                  0
      hugepages-2Mi:                  0
      memory:                         130244288Ki
      nvidia.com/GV100GL_Tesla_V100   1
      nvidia.com/TU104GL_Tesla_T4     1
      intel.com/qat:                  0
      pods:                           250

8.14.11.2. 为 PCI 透传配置虚拟机

将 PCI 设备添加到集群中后,您可以将它们分配到虚拟机。PCI 设备现在可用。就像它们被物理地连接到虚拟机一样。

8.14.11.2.1. 为虚拟机分配 PCI 设备

当集群中有 PCI 设备时,您可以将其分配到虚拟机并启用 PCI 透传。

流程

  • 将 PCI 设备分配到虚拟机作为主机设备。

    示例

    apiVersion: kubevirt.io/v1
    kind: VirtualMachine
    spec:
      domain:
        devices:
          hostDevices:
          - deviceName: nvidia.com/TU104GL_Tesla_T4 1
            name: hostdevices1

    1
    集群中作为主机设备允许的 PCI 设备的名称。虚拟机可以访问此主机设备。

验证

  • 使用以下命令,验证主机设备可从虚拟机使用。

    $ lspci -nnk | grep NVIDIA

    输出示例

    $ 02:01.0 3D controller [0302]: NVIDIA Corporation GV100GL [Tesla V100 PCIe 32GB] [10de:1eb8] (rev a1)

8.14.11.3. 其他资源

8.14.12. 配置 watchdog

通过为 watchdog 设备配置虚拟机(VM)、安装 watchdog 并启动 watchdog 服务来公开 watchdog。

8.14.12.1. 先决条件

  • 虚拟机必须具有对 i6300esb watchdog 设备的内核支持。Red Hat Enterprise Linux (RHEL) 镜像支持 i6300esb

8.14.12.2. 定义 watchdog 设备

定义在操作系统(OS)没有响应时 watchdog 如何进行处理。

表 8.3. 可能的操作

poweroff

虚拟机(VM)立即关闭。如果 spec.running 设为 true,或者 spec.runStrategy 没有设置为 manual,则 VM 会重启。

reset

虚拟机将进行重启,客户机操作系统无法响应。由于客户机操作系统重启所需一定的时间完成,可能会导致存活度探测超时,因此不建议使用这个选项。如果集群级别的保护发现存活度探测失败并强制重新调度存活度探测,则此超时可以延长虚拟机重启所需的时间。

shutdown

虚拟机通过停止所有服务来正常关闭电源。

流程

  1. 创建包含以下内容的 YAML 文件:

    apiVersion: kubevirt.io/v1
    kind: VirtualMachine
    metadata:
      labels:
        kubevirt.io/vm: vm2-rhel84-watchdog
      name: <vm-name>
    spec:
      running: false
      template:
        metadata:
         labels:
            kubevirt.io/vm: vm2-rhel84-watchdog
        spec:
          domain:
            devices:
              watchdog:
                name: <watchdog>
                i6300esb:
                  action: "poweroff" 1
    ...
    1
    指定 watchdog 操作(poweroffresetshutdown)。

    上面的示例使用 poweroff 操作配置 RHEL8 虚拟机上的 i6300esb watchdog 设备,并将设备公开为 /dev/watchdog

    现在,watchdog 二进制文件可以使用这个设备。

  2. 运行以下命令,将 YAML 文件应用到集群:

    $ oc apply -f <file_name>.yaml
重要

此流程仅用于测试 watchdog 功能,且不得在生产环境中运行。

  1. 运行以下命令来验证虚拟机是否已连接到 watchdog 设备:

    $ lspci | grep watchdog -i
  2. 运行以下命令之一以确认 watchdog 处于活跃状态:

    • 触发内核 panic:

      # echo c > /proc/sysrq-trigger
    • 终止 watchdog 服务:

      # pkill -9 watchdog

8.14.12.3. 安装 watchdog 设备

在虚拟机上安装 watchdog 软件包,再启动 watchdog 服务。

流程

  1. 作为 root 用户,安装 watchdog 软件包和依赖项:

    # yum install watchdog
  2. /etc/watchdog.conf 文件中取消注释以下行,并保存更改:

    #watchdog-device = /dev/watchdog
  3. 在引导时启用 watchdog 服务:

    # systemctl enable --now watchdog.service

8.14.12.4. 其他资源

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

© 2024 Red Hat, Inc.