1 虚拟化管理面无感卸载

1.1 简介

虚拟化管理面,即libvirtd,而虚拟化管理面卸载,即是将libvirtd卸载到与虚拟机所在机器(以下称为host)之外的另一台机器(以下称为DPU)上运行。

我们使用了qtfs将host的一些与虚拟机运行相关的目录挂载到DPU上,使得虚拟化管理面工具可以访问到这些目录,为kvm虚拟机准备运行所需要的环境,此处,因为需要挂载远端的proc和sys,所以,我们创建了一个专门的rootfs以作为libvirtd的运行环境(以下称为/another_rootfs)。

并且通过rexec执行虚拟机的拉起、删除等操作,使得可以将虚拟化管理面和虚拟机分离在不同的两台机器上,远程对虚拟机进行管理。

1.2 相关组件介绍

1.2.1 rexec介绍

rexec是一个用c语言开发的远程执行组件,分为rexec client和rexec server。server端为一个常驻服务进程,client端为一个二进制文件,client端被执行后会基于udsproxyd服务与server端建立uds连接,并由server常驻进程在server端拉起指定程序。在libvirt虚拟化卸载中,libvirtd卸载到DPU上,当它需要在HOST拉起虚拟机qemu进程时调起rexec client进行远程拉起。

2 操作环境

物理机操作系统: openEuler 22.03 LTS 及之后的版本

libvirt版本: libvirt-6.9.0

qemu版本:6.2.0

文件下载列表:

git clone https://gitee.com/openeuler/dpu-utilities.git
cd dpu-utilities/qtfs/rexec/
make
yes | cp ./rexec* /usr/bin/
    1. DPU 机器上下载对应软件包和库文件 qtfs.ko, libvirt-6.9.0.tat.xz
    1. host 机器上安装qemu yum install qemu

3 虚拟化管理面卸载操作指南

说明:

  1. 在host端和DPU端,都要拉起rexec_server;host侧可使用 [dpu IP]:[dpu rexec端口号] 远程操作DPU上的二进制,反之亦然;
  2. host端拉起rexec_server,主要是用于DPU创建虚拟机时用rexec拉起qemu-kvm;

3.1 拉起rexec_server

3.1.1 拷贝二进制文件

rexec_server安装到DPU和host上

cp rexec_server /usr/bin/
chmod +x rexec_server

3.1.2 配置rexec_server服务

为方便起见,可以将rexec_server作为一个systemd服务;

  1. 同时在DPU和host上的/usr/lib/systemd/system/目录下,添加rexec.service服务文件,内容如下:

/usr/lib/systemd/system/rexec.service,service文件中的<端口号>根据用户的意愿自行分配

[Unit]
Description=Rexec_server Service
After=network.target

[Service]
Type=simple
Environment=CMD_NET_ADDR=tcp://0.0.0.0:<端口号>
ExecStart=/usr/bin/rexec_server
ExecReload=/bin/kill -s HUP $
KillMode=process

[Install]
WantedBy=multi-user.target
  1. 通过systemctl start rexec,拉起rexec_server服务
systemctl daemon-reload
systemctl enable --now rexec

3.1.2 rexec操作示例

配置好rexec_server服务后,如果要在DPU上调用host上的二进制,可先将rexec拷贝到/usr/bin下面,再使用如下命令远程执行对端服务器上的二进制;

CMD_NET_ADDR=tcp://<host ip>:<host端rexec_server端口号> rexec [要执行的指令]

例如,在DPU上操作host(假设ip为192.168.1.1,rexec端口号为6666)上的ls指令:

CMD_NET_ADDR=tcp://192.168.1.1:6666 rexec /usr/bin/ls

补充说明:

如果不想systemd服务的形式拉起rexec_server,可使用命令手动拉起。

例如,在host端执行CMD_NET_ADDR=tcp://0.0.0.0:<端口号> rexec_server 命令,可拉起rexec_server进程;

3.2 准备libvirtd运行的rootfs

注:本步骤仅需在DPU上执行的

在下面的文档中,我们将这个rootfs称为/another_rootfs(具体的目录名称,可以根据自己的需求进行调整)

rootfs可使用如下3.2.1或3.2.2两种方案之一,推荐使用openEuler官方qcow2镜像。在准备好rootfs后,按照3.2.3中的方式,向/another_rootfs中安装软件包

3.2.1 拷贝根目录

一般来说,只需要将根目录直接拷贝到这个文件夹即可

请使用如下命令操作拷贝动作

mkdir /another_rootfs
cp -r /usr /another_rootfs
cp -r /sbin /another_rootfs
cp -r /bin /another_rootfs
cp -r /lib64 /another_rootfs
cp -r /lib /another_rootfs
mkdir /another_rootfs/boot
mkdir /another_rootfs/dev
mkdir /another_rootfs/etc
mkdir /another_rootfs/home
mkdir /another_rootfs/mnt
mkdir /another_rootfs/opt
mkdir /another_rootfs/proc
mkdir /another_rootfs/root
mkdir /another_rootfs/run
mkdir /another_rootfs/var
mkdir /another_rootfs/etc
mkdir /another_rootfs/sys
mkdir /another_rootfs/local_proc

3.2.2 使用openEuler官方qcow2镜像

如果根目录并非完全干净的新环境,可以使用openEuler官方提供的qcow2镜像,来准备一个新的rootfs:

3.2.2.1 工具安装

需要用yum安装xz、kpartx、qemu-img

yum install xz kpartx qemu-img

3.2.2.2 下载qcow2镜像

在openEuler官网获取22.03版本openEuler-x86虚拟机镜像(x86架构),或者22.03版本openEuler-arm64虚拟机镜像(ARM架构)。

3.2.2.3 解压qcow2镜像

使用xz -d解压为openEuler-22.03-LTS-.qcow2文件, 以x86镜像为例

xz -d openEuler-22.03-LTS-x86_64.qcow2.xz

3.2.2.4 挂载qcow2镜像并拷贝文件

  1. 使用modprobe nbd maxpart=<任意数字>来加载nbd模块,
  2. qemu-nbd -c /dev/nbd0 <虚拟机镜像的路径>
  3. 创建任意文件夹/random_dir,
  4. 执行挂载mount /dev/nbd0p2 /random_dir
  5. 拷贝文件
mkdir /another_rootfs
cp -r /random_dir/* /another_rootfs/

此时,虚拟机镜像便已经挂载到当前文件夹中了;

3.2.2.5 qcow2卸载

在准备好rootfs后,需要卸载qcow2文件,此时,需要执行如下指令:

umount /random_dir
qemu-nbd -d /dev/nbd0

3.3 在host侧拉起qtfs_server

创建容器管理面所需要的文件夹,然后插入qtfs_server.ko,并拉起engine进程。

可以用如下脚本来执行此操作,如果执行错误,可能需要dos2unix来将此脚本的格式转换(如下所有脚本皆同理)。注意,在最后两行,需要将qtsf_server.ko和engine的路径填写为存放这两个组件的路径

#!/bin/bash
mkdir /var/lib/libvirt

insmod <ko路径>/qtfs_server.ko qtfs_server_ip=0.0.0.0 qtfs_log_level=INFO #此处需要自行修改ko的路径
<engine路径>/engine 4096 16 #此处需要自行修改engine的路径

3.4 UDSPROXYD服务部署

3.4.1 简介

udsproxyd是一个跨主机的unix domain socket代理服务,需要分别部署在host和dpu上,在host和dpu上的udsproxyd组件是对等的关系,可以实现分布在host与dpu上的2个进程之间的uds通信,通信进程是无感的,也就是说如果这两个进程在同一主机内通过uds正常通信的功能,拉远到host和dpu之间也可以,不需要做代码适配,只需要作为client的一端加一个环境变量LD_PRELOAD=libudsproxy.so

3.4.2 部署方式

首先,在dpu-utilities工程内编译udsproxyd:

cd qtfs/ipc

make && make install

当前最新版本下,qtfs server侧的engine服务已经整合了udsproxyd的能力,所以server侧若部署了qtfs后不需要再额外启动udsproxyd。client侧则单独拉起udsproxyd服务:

nohup /usr/bin/udsproxyd <thread num> <addr> <port> <peer addr> <peer port> 2>&1 &

参数解释:

thread num: 线程数量,目前只支持单线程,填1.

addr: 本机使用的ip

port:本机占用的port

peer addr: udsproxyd对端的ip

peer port: 对端port

示例:

nohup /usr/bin/udsproxyd 1 192.168.10.10 12121 192.168.10.11 12121 2>&1 &

如果未拉起qtfs的engine服务,想单独测试udsproxyd,则在server端也对等拉起udsproxyd即可:nohup /usr/bin/udsproxyd 1 192.168.10.11 12121 192.168.10.10 12121 2>&1 &

然后将libudsproxy.so拷贝到libvirt的chroot目录下的/usr/lib64中以提供给libvirtd服务使用,这一步在后面介绍。

3.5 挂载host上依赖目录至DPU

3.5.1 安装软件包

3.5.2.1 在根目录的安装

  1. 在/another_rootfs中安装libvirt-client
yum install libvirt-client

3.5.2.2 another_rootfs环境配置

  1. /another_rootfs中,安装libvirtd;
cd /another_rootfs
tar -xf <path_to>/libvirtd-6.9.0.tar.xz #此处需要改动libvirtd-6.9.0.tar.xz的路径
cd libvirtd-6.9.0
patch -p1 < 0001-libvirt_6.9.0_1201_offload.patch #此处需要改动path_to_patch的路径为libvirt的patch路径,并按顺序一个一个打入patch
patch -p1 < 0003-fix-get-affinity.patch #此处需要改动path_to_patch的路径为libvirt的patch路径,并按顺序一个一个打入patch
patch -p1 < 0004-qmp-port-manage.patch #此处需要改动path_to_patch的路径为libvirt的patch路径,并按顺序一个一个打入patch
chroot /another_rootfs
yum groupinstall "Development tools" -y
yum install -y vim meson qemu qemu-img strace edk2-aarch64 tar

yum install -y rpcgen python3-docutils glib2-devel gnutls-devel libxml2-devel libpciaccess-devel libtirpc-devel yajl-devel systemd-devel dmidecode glusterfs-api numactl

cd /libvirtd-6.9.0

CFLAGS='-Wno-error=format -Wno-error=int-conversion -Wno-error=implicit-function-declaration -Wno-error=nested-externs -Wno-error=declaration-after-statement -Wno-error=unused-result -Wno-error=missing-prototypes -Wno-error=int-conversion -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=pointer-sign -Wno-error=discarded-qualifiers -Wno-error=unused-function' meson build --prefix=/usr -Ddriver_remote=enabled -Ddriver_network=enabled -Ddriver_qemu=enabled -Dtests=disabled -Ddocs=enabled -Ddriver_libxl=disabled -Ddriver_esx=disabled -Dsecdriver_selinux=disabled -Dselinux=disabled

ninja -C build install
exit
  1. 并需要将rexec拷贝到/another_rootfs/usr/bin下面,并对其添加可执行权限
cp rexec /another_rootfs/usr/bin
chmod +x /another_rootfs/usr/bin/rexec
  1. /another_rootfs中,通过如下脚本创建脚本/usr/bin/qemu-kvm, /usr/libexec/qemu-kvm,此脚本需要将<host的ip>和<rexec server端口>改为host的ip和host上rexec_server的端口号
chroot /another_rootfs
touch /usr/bin/qemu-kvm
touch /usr/libexec/qemu-kvm
cat > /usr/bin/qemu-kvm <<EOF
#!/bin/bash
host=<host的ip>
port=<rexec server端口>
CMD_NET_ADDR=tcp://\$host:\$port exec /usr/bin/rexec /usr/bin/qemu-kvm \$*
EOF
cat > /usr/libexec/qemu-kvm <<EOF
#!/bin/bash
host=<host的ip>
port=<rexec server端口>
CMD_NET_ADDR=tcp://\$host:\$port exec /usr/bin/rexec /usr/bin/qemu-kvm \$*
EOF
chmod +x /usr/libexec/qemu-kvm
chmod +x /usr/bin/qemu-kvm
exit

3.5.2.3 目录挂载

在DPU上执行如下的脚本,将libvirtd所需要的host目录挂载到DPU。

并且,需要确保在以下脚本 prepare.sh 中被挂载的远程目录在host和DPU都存在。

#!/bin/bash
insmod <qtfs.ko路径>/qtfs.ko qtfs_server_ip=<server ip> qtfs_log_level=INFO #此处需要改动qtfs.ko的路径,并改动<server ip>

systemctl stop libvirtd
 
mkdir -p /var/run/rexec/pids
cat >/var/run/rexec/qmpport << EOF
<qmp端口号>
EOF
cat > /var/run/rexec/hostaddr <<EOF
<服务端ip>
EOF
cat > /var/run/rexec/rexecport << EOF
<rexec端口号>
EOF

rm -f `find /var/run/libvirt/ -name "*.pid"`
rm -f /var/run/libvirtd.pid

if [ ! -d "/another_rootfs/local_proc" ]; then
    mkdir -p /another_rootfs/local_proc
fi
if [ ! -d "/another_rootfs/local" ]; then
    mkdir -p /another_rootfs/local
fi
mount -t proc proc /another_rootfs/local_proc/
mount -t proc proc /another_rootfs/local/proc
mount -t sysfs sysfs /another_rootfs/local/sys
mount --bind /var/run/ /another_rootfs/var/run/
mount --bind /var/lib/ /another_rootfs/var/lib/
mount --bind /var/cache/ /another_rootfs/var/cache
mount --bind /etc /another_rootfs/etc

mkdir -p /another_rootfs/home/VMs/
mount -t qtfs /home/VMs/ /another_rootfs/home/VMs/

mount -t qtfs /var/lib/libvirt /another_rootfs/var/lib/libvirt

mount -t devtmpfs devtmpfs /another_rootfs/dev/
mount -t hugetlbfs hugetlbfs /another_rootfs/dev/hugepages/
mount -t mqueue mqueue /another_rootfs/dev/mqueue/
mount -t tmpfs tmpfs /another_rootfs/dev/shm

mount -t sysfs sysfs /another_rootfs/sys
mkdir -p /another_rootfs/sys/fs/cgroup
mount -t tmpfs tmpfs /another_rootfs/sys/fs/cgroup
list="perf_event freezer files net_cls,net_prio hugetlb pids rdma cpu,cpuacct memory devices blkio cpuset"
for i in $list
do
        echo $i
        mkdir -p /another_rootfs/sys/fs/cgroup/$i
        mount -t cgroup cgroup -o rw,nosuid,nodev,noexec,relatime,$i /another_rootfs/sys/fs/cgroup/$i
done

## common system dir
mount -t qtfs -o proc /proc /another_rootfs/proc
echo "proc"

mount -t qtfs /sys /another_rootfs/sys
echo "cgroup"
mount -t qtfs /dev/pts /another_rootfs/dev/pts
mount -t qtfs /dev/vfio /another_rootfs/dev/vfio

3.6 拉起libvirtd

在DPU上,打开一个窗口,并且chroot到/another_rootfs

chroot /another_rootfs

用如下的命令先拉起virtlogd,后拉起virtlogd

#!/bin/bash
virtlogd -d
libvirtd -d

因为我们已经将/var/run//another_rootfs/var/run/绑定在了一起,所以,我们可以在正常的rootfs下,通过virsh来访问libvirtd,从而管理容器。

4 环境恢复

如果需要卸载相关的目录,需要执行如下指令

#!/bin/bash

umount /root/p2/dev/hugepages
umount /root/p2/etc
umount /root/p2/home/VMs
umount /root/p2/local_proc
umount /root/p2/var/lib/libvirt
umount /root/p2/var/lib
umount /root/p2/*
umount /root/p2/dev/pts
umount /root/p2/dev/mqueue
umount /root/p2/dev/shm
umount /root/p2/dev/vfio
umount /root/p2/dev
rmmod qtfs

umount /root/p2/sys/fs/cgroup/*
umount /root/p2/sys/fs/cgroup
umount /root/p2/sys

文档捉虫

“有虫”文档片段

问题描述

提交类型 issue

有点复杂...

找人问问吧。

PR

小问题,全程线上修改...

一键搞定!

问题类型
规范和低错类

● 错别字或拼写错误;标点符号使用错误;

● 链接错误、空单元格、格式错误;

● 英文中包含中文字符;

● 界面和描述不一致,但不影响操作;

● 表述不通顺,但不影响理解;

● 版本号不匹配:如软件包名称、界面版本号;

易用性

● 关键步骤错误或缺失,无法指导用户完成任务;

● 缺少必要的前提条件、注意事项等;

● 图形、表格、文字等晦涩难懂;

● 逻辑不清晰,该分类、分项、分步骤的没有给出;

正确性

● 技术原理、功能、规格等描述和软件不一致,存在错误;

● 原理图、架构图等存在错误;

● 命令、命令参数等错误;

● 代码片段错误;

● 命令无法完成对应功能;

● 界面错误,无法指导操作;

风险提示

● 对重要数据或系统存在风险的操作,缺少安全提示;

内容合规

● 违反法律法规,涉及政治、领土主权等敏感词;

● 内容侵权;

您对文档的总体满意度

非常不满意
非常满意
提交
根据您的反馈,会自动生成issue模板。您只需点击按钮,创建issue即可。