长期支持版本

    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.3 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
    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即可。
    文档捉虫
    编组 3备份