您的位置:首页 > 科技 > 能源 > OpenShift4 - 为 OpenShift Virtualization 的 VM 配置内存的策略

OpenShift4 - 为 OpenShift Virtualization 的 VM 配置内存的策略

2024/12/23 4:37:14 来源:https://blog.csdn.net/weixin_43902588/article/details/141408233  浏览:    关键词:OpenShift4 - 为 OpenShift Virtualization 的 VM 配置内存的策略

《OpenShift / RHEL / DevSecOps 汇总目录》
说明:本文已经在 OpenShift 4.16 环境中验证

文章目录

  • VM 内存分配和使用情况
    • VM 内存分配和使用情况
    • Pod 内存分配和使用情况
    • 模拟消耗VM内存
  • 增加 VM 的运行密度
    • 内存超配
      • 显性内存超配 - 为运行 VMI 的 Pod 指定较小的 Request 内存
      • 隐性内存超配
    • 不为运行 VM 的 Pod 分配附加内存
    • 为节点配置内存 swap 交换空间
  • 为 VM 配置内存 Hotplug
  • 参考

VM 内存分配和使用情况

  1. 创建一个测试用的 VM。
    在这里插入图片描述

VM 内存分配和使用情况

  1. 查看在 VMI 中可以看到的内存。
$ oc get vmi rhel8-vm1 -n my-vm -ojsonpath={.spec.domain.memory.guest}
2Gi 
  1. 查看运行 VMI 的 Pod 申请的内存,缺省和上面一样。
$ oc get vmi rhel8-vm1 -n my-vm -ojsonpath={.spec.domain.resources.requests.memory}
2Gi
  1. 查看 VMI 的内存情况。
$ oc get vmi rhel8-vm1 -n my-vm -ojsonpath={.status.memory} | jq
{"guestAtBoot": "2Gi","guestCurrent": "2Gi","guestRequested": "2Gi"
}
  1. 进入该 VM 的 Linux 中,查看内存使用情况,确认 total=used+free+buff+cache
$ free -b -wtotal        used        free      shared     buffers       cache   available
Mem:     1864249344   142319616  1475407872     8966144     4014080   242507776  1558335488
Swap:             0           0           0
  1. 也可在控制台查看 VM 内存分配和使用情况。其中 (total-available) / 1024 /1024 = 291.8 MiB,就是下图的 Memory used。
    在这里插入图片描述
    在这里插入图片描述
  2. 点击上图 Memory 区域,然后在下图中添加以下和内存相关的指标。注意,图中显示的数值单位不是 GiB 和 MiB。
    last_over_time(kubevirt_vmi_memory_used_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    last_over_time(kubevirt_vmi_memory_available_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    last_over_time(kubevirt_vmi_memory_cached_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    last_over_time(kubevirt_vmi_memory_domain_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    last_over_time(kubevirt_vmi_memory_usable_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    last_over_time(kubevirt_vmi_memory_unused_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    last_over_time(kubevirt_vmi_memory_resident_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    last_over_time(kubevirt_vmi_memory_actual_balloon_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    last_over_time(kubevirt_vmi_memory_swap_in_traffic_bytes{name=‘rhel8-vm1’,namespace=‘my-vm’}[5m])
    在这里插入图片描述
  3. 确认以下 kubevirt_vmi_memory_available_bytes 指标的值(1864249344)是以上第 4 步的 total 内存。
    在这里插入图片描述
  4. 确认以下 kubevirt_vmi_memory_used_bytes 指标 307015680 / 1024 /1024 = 292.7 MiB,和以上第 5 步的 Memory used (截图时间不同,获取到的数值稍有差异)。
    在这里插入图片描述
  5. 确认 kubevirt_vmi_memory_unused_bytes 指标的值为以上第 4 步的 free 内存。
  6. 确认 kubevirt_vmi_memory_usable_bytes 指标的值为以上第 4 步的 available 内存。

Pod 内存分配和使用情况

  1. 查看运行 VMI 的 Pod 的内存使用情况。
$ oc get pod -n my-vm  virt-launcher-rhel8-vm1-lqwvp -ojsonpath={.spec.containers[0].resources} | jq
{"limits": {"devices.kubevirt.io/kvm": "1","devices.kubevirt.io/tun": "1","devices.kubevirt.io/vhost-net": "1"},"requests": {"cpu": "100m","devices.kubevirt.io/kvm": "1","devices.kubevirt.io/tun": "1","devices.kubevirt.io/vhost-net": "1","ephemeral-storage": "50M","memory": "2294Mi"}
}
  1. 在控制台查看该 Pod 的内存使用情况。
    在这里插入图片描述

模拟消耗VM内存

  1. 在 VM 中运行以下命令,将 1G 数据写道内存中。
sudo -i
mkdir z
mount -t ramfs ramfs z/
dd if=/dev/zero of=z/file bs=1M count=1024
  1. 再次查看 Linux 中的内存使用情况
$ free -b -wtotal        used        free      shared     buffers       cache   available
Mem:     1864249344   145862656   372514816     8966144     4014080  1341857792   479592448
Swap:             0           0           0
  1. 查看 VM 的监控指标,注意内存指标的变化情况。
    在这里插入图片描述
  2. 还可再次查看运行 VMI 的 Pod 的内存使用情况。

增加 VM 的运行密度

在启动 VM 后 OpenShift 首先要为它调度到运行所需的 CPU 和 Memory 资源。如果此时无法调度到足够的资源,会提示以下 ErrorUnschedulable 错误。例如可将 rhel8-vm1 的内存提高到 8GiB,启动后提示以下错误:
在这里插入图片描述
缺省时 OpenShift 会为 VM 分配其所声明的内存量,即便大多数时间 VM 都不会把其声明的内存全部占满,因此缺省情况能同时运行的 VM 数量就会受限。可以通过以下方法提升 VM 的运行密度。

内存超配

显性内存超配 - 为运行 VMI 的 Pod 指定较小的 Request 内存

为 VM 配置的最大内存缺省情况下基本就是运行该 VM 的 Pod 的 Request 内存(差异是该 Pod 自身会占用一部分附加内存,下一节将介绍)。

执行命令可以看到以下 VM 和 VMI 需要 8Gi 内存,且没有为运行 VM 的 Pod 指定内存策略,此时将使用缺省的内存策略,即 VM 的 spec.template.spec.domain.resources 将等于 spec.template.spec.domain.memory.guest。

$ oc get vm rhel8-vm1 -n my-vm -ojsonpath={.spec.template.spec.domain.memory.guest}
8Gi$ oc get vmi rhel8-vm1 -ojsonpath={.spec.domain.resources.requests.memory}
8Gi$ oc get vm rhel8-vm1 -n my-vm -ojsonpath={.spec.template.spec.domain.resources}
{}

在运行起 rhel8-vm1后,查看运行该 VM 的 Pod 申请内存情况,为 8450Mi。

$ oc get pod virt-launcher-rhel8-vm1-8pkzl -n my-vm -ojsonpath={.spec.containers[0].resources.requests.memory} 
8450Mi

如果当前集群无法为 Pod 调度到 8450Mi 内存,则在启动 VM 后会提示 ErrorUnschedulable 错误。为了解决该问题,可以修改为这个 Pod 分配的 Request 内存。通过减小运行 Pod 初始分配的内存,以便 OpenShift 能够为要启动的 VM 调度到资源。

可以执行以下命令,设置 VirtualMachine 对象的 spec.template.spec.domain.resources.requests.memory,这样在启动 VM 时只需为对应的 Pod 申请 2Gi 内存即可。

$ oc patch vm rhel8-vm1 -n my-vm -p '{"spec":{"template":{"spec":{"domain":{"resources":{"requests":{"memory":"2Gi"}}}}}}}' --type=merge$ oc get vm rhel8-vm1 -n my-vm -ojsonpath={.spec.template.spec.domain.resources.requests.memory}
2Gi

这时再启动 VM 就可顺利调度到内存资源了(确保当前 OpenShift 可以调度到 2Gi 内存)。当 VM 启动后再执行以下命令查看运行该 VM 的 VMI 和 Pod 使用内存情况,分别为 2Gi 和 2294Mi(两者的差异是 Pod 自身会占用一部分附加内存)。

$ virtctl restart rhel8-vm1$ oc get vmi rhel8-vm1 -ojsonpath={.spec.domain.resources.requests.memory}
2Gi$ oc get pod virt-launcher-rhel8-vm1-wld56 -n my-vm -ojsonpath={.spec.containers[0].resources.requests.memory}
2294Mi

另外还可单独监控运行 VM 的 Pod 使用内存情况。
在这里插入图片描述

隐性内存超配

手动设置 VirtualMachine 对象的 spec.template.spec.domain.resources.requests.memory 属于显性设置内存超配。可以通过以下方式为所有未设置 spec.template.spec.domain.resources 的 VM 配置内存超配比例。

首先执行命令,设置隐性内存超配的比例。以下将 memoryOvercommitPercentage 设为 150,即对于所有未显性设置内存超配的 VM,初始为运行 VM 的 Pod 分配的内存的 150% 才是在控制台中为 VM 设置的内存量。比如 VM 需要的是 3GB 内存, 而开始为运行 VM 的 Pod 只分配 2GB 内存。

$ oc patch HyperConverged kubevirt-hyperconverged -n openshift-cnv -p '{"spec":{"higherWorkloadDensity":{"memoryOvercommitPercentage":150}}}' --type=merge

不为运行 VM 的 Pod 分配附加内存

在上一节操作中可以看到在缺省情况时运行 VM 的 Pod 自身会占用一部分附加内存,可以设置 VM 的 overcommitGuestOverhead 参数以不让 Pod 使用这部分额外的内存。

首先查看运行 VM 的 Pod 申请的内存,2294Mi 比 2Gi 多出一定的额外附加内存。

$ oc get pod virt-launcher-rhel8-vm1-wld56 -n my-vm -ojsonpath={.spec.containers[0].resources.requests.memory}
2294Mi

为 VM 设置 overcommitGuestOverhead 参数,重启 VM 后再次查看运行 VM 的 Pod 申请的内存,此时已经正好是 2Gi 了。

$ oc patch vm rhel8-vm1 -n my-vm -p '{"spec":{"template":{"spec":{"domain":{"resources":{"overcommitGuestOverhead":"true"}}}}}}' --type=merge$ virtctl restart rhel8-vm1$ oc get pod virt-launcher-rhel8-vm1-w9dtg  -n my-vm -ojsonpath={.spec.containers[0].resources.requests.memory}
2Gi

为节点配置内存 swap 交换空间

https://docs.redhat.com/zh_hans/documentation/openshift_container_platform/4.16/html/virtualization/virt-configuring-higher-vm-workload-density

为 VM 配置内存 Hotplug

缺省情况下在修改了 VM 的内存后需要重启才能生效,不过在支持 LiveMigratable 的 OpenShift Virtualization 环境中可以使用 memory hotplug 特性让 VM 调整的内存即使生效,无需重启 。

  1. 确认在 kubevirt 中启动了 VMLiveUpdateFeatures 特性。
$ oc get kubevirt -n openshift-cnv kubevirt-kubevirt-hyperconverged -ojsonpath={.spec.configuration.developerConfiguration.featureGates} | jq
["DataVolumes","SRIOV","CPUManager","CPUNodeDiscovery","Snapshot","HotplugVolumes","ExpandDisks","GPU","HostDevices","NUMA","VMExport","DisableCustomSELinuxPolicy","KubevirtSeccompProfile","HotplugNICs","VMPersistentState","NetworkBindingPlugins","CommonInstancetypesDeploymentGate","VMLiveUpdateFeatures","WithHostModelCPU","HypervStrictCheck"
]
  1. 确认在 kubevirt 中的 workloadUpdateMethods 配置是 LiveUpdate。
$ oc get kubevirt -n openshift-cnv kubevirt-kubevirt-hyperconverged -ojsonpath={.spec.workloadUpdateStrategy.workloadUpdateMethods}
["LiveMigrate"]
  1. 确认在 kubevirt 中的 vmRolloutStrategy 配置是 LiveUpdate。
$ oc get kubevirt -n openshift-cnv kubevirt-kubevirt-hyperconverged -ojsonpath={.spec.configuration.vmRolloutStrategy}
LiveUpdate
  1. 删去为运行 VM 的 Pod 设置的 request 内存。
$ oc patch vm rhel8-vm1 -n my-vm -p='[{"op": "remove", "path": "/spec/template/spec/domain/resources/requests"}]' --type='json'
  1. 先查看 VMI 当前使用的内存量。
$ oc get vmi rhel8-vm1 -n my-vm -o json | jq .status.memory
{"guestAtBoot": "8Gi","guestCurrent": "8Gi","guestRequested": "8Gi"
}
  1. 修改分配给 VM 的内存量,maxGuest 为最大分配量,guest 为当前分配量。
$ oc patch vm rhel8-vm1 -n my-vm -p='[{"op": "replace", "path": "/spec/template/spec/domain/memory/maxGuest", "value": "8Gi"}]' --type='json'
$ oc patch vm rhel8-vm1 -n my-vm -p='[{"op": "replace", "path": "/spec/template/spec/domain/memory/guest", "value": "4Gi"}]' --type='json'
  1. 再确认此 VMI 使用的内存量已经变化。
$ oc get vmi rhel8-vm1 -n my-vm -o json | jq .status.memory
{"guestAtBoot": "4Gi","guestCurrent": "4Gi","guestRequested": "4Gi"
}
  1. 如果 OpenShift Virtualization 环境不支持 LiveMigratable,则会看到以下错误提示:
    在这里插入图片描述

参考

https://docs.openshift.com/container-platform/4.16/virt/virtual_machines/advanced_vm_management/virt-working-with-resource-quotas-for-vms.html
https://docs.redhat.com/zh_hans/documentation/openshift_container_platform/4.16/html/virtualization/virt-configuring-higher-vm-workload-density
https://docs.redhat.com/zh_hans/documentation/openshift_container_platform/4.16/html/nodes/nodes-cluster-overcommit
https://kubevirt.io/user-guide/compute/node_overcommit/
https://kubevirt.io/2018/KubeVirt-Memory-Overcommit.html
https://kubevirt.io/user-guide/compute/memory_hotplug/

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com