百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

手动编译安装 KVM 就是找虐,万幸我还活着

zhezhongyun 2025-01-29 19:09 56 浏览

玩过虚拟机的小伙伴们多少应该听说过 KVM 吧。

虽然它和 Keyboard Video Mouse 的缩写一样,但我们今天要分享的可不是那个用来连接显示器和键盘鼠标的机房设备。

KVMKernel-based)Virtual Machine ,是基于 Linux 的一种开源虚拟化技术。

除了 VMwareVirutalBoxHyperV 之外,KVM 也是非常流行的虚拟解决技术方案。

关于 KVM 的安装,相信很多小伙伴们多半是通过像 yumapt-get 之类的软件包管理命令来安装的。

使用软件包管理命令来安装有很多好处,比如自动解决程序依赖问题。

但是它也有些缺点,比如官方源支持程序的版本较低,可能有部分功能没有被支持,从而导致我们无法正常使用一些新功能。

好了,我忙中抽空,挑战了一把完全使用手动编译的方法来安装 KVM

赶快一起来看看,我在这个过程中是怎么被虐的吧!


环境背景及安装目标:

  • Rocky Linux 8.4 内核 4.18
  • ninja 1.10.2
  • Python 3.9
  • QEMU 6.0.94
  • libvirt 7.6.0
  • virt-manager 3.2.0


我们需要安装的大概一共有三大块,分别是 QEMUlibivrt 以及 virt-manager

KVMLinux 自带的,不需要我们安装了,我们主要把这三大块给搞定就行了。


切换更新源

如果你嫌官方源速度慢,也可以考虑用国内的源。

# 切换为上海交通大学的更新源
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
    -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.sjtug.sjtu.edu.cn/rocky|g' \
    -i.bak \
    /etc/yum.repos.d/Rocky-*.repo

# 生成缓存
dnf makecache


所需组件

dnf install tar unzip bzip2 make wget curl curl-devel gcc gcc-c++ automake autoconf libtool pixman pixman-devel zlib-devel lzo-devel glib2-devel pam-devel python39 python39-devel

dnf config-manager --set-enabled powertools
dnf install libfdt-devel SDL SDL-devel SDL2 SDL2-devel vte291-devel
dnf install libevdev-devel spice-* xorg-x11-server-Xspice libssh-devel


安装 ninja

项目下载链接:
https://github.com/ninja-build/ninja/releases


ninja-linux.zip(100K)

本地下载:
https://pan.baidu.com/s/1zdjoZaTw7bia0r2zG_Q6mQ

提取码:<头条不让放,请到网管小贾的博客中查找>


直接下载解压缩,得到一个可执行文件

https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-linux.zip

wget https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-linux.zip
unzip ninja-linux.zip
mv ninja /usr/bin/


第一大块:安装 QEMU

QEMU 是创建虚拟机的关键,它其实可以理解为虚拟机模拟器,我们跑的虚拟机就是它在工作。

如果你用 yumapt 来安装官方源中的 QEMU ,那么你就会发现它的版本是 4.2 ,而官方当前版本是 6.x ,足足高了两个版本。

怎么猜这版本的差距也包含了不少的功能增加和性能提升吧,我没有仔细阅读官方文档,纯粹主观臆断哈,小伙伴们不要介意。

好,本文的目的就是要打破现状启用新版,所以我们直接上手安装 6.x 版吧!

官方下载链接:
https://www.qemu.org/download/


以当前最新版本 6.1.0-rc4 为例,按以下步骤安装即可。

wget https://download.qemu.org/qemu-6.1.0-rc4.tar.xz
tar xvJf qemu-6.1.0-rc4.tar.xz
cd qemu-6.1.0-rc4
./configure
make
make install


由于文件数量众多,所以编译会需要比较长的时间。

安装完成后,再做几个软链接好方便调用命令。

ln -s /usr/local/bin/qemu-system-x86_64 /usr/bin/qemu-kvm
ln -s /usr/local/bin/qemu-system-x86_64 /usr/libexec/qemu-kvm
ln -s /usr/local/bin/qemu-img /usr/bin/qemu-img


查看一下当前 QEMU 版本,我这儿显示是 6.0.94

# qemu-img 是用来管理镜像文件的
qemu-img --version

# qemu-kvm 是用来管理虚拟机的
qemu-kvm --version


第二大块:安装 libvirt

官方文档说得比较文绉绉,不太容易理解,我个人的理解是,这个 libvirt 是用来管理和控制前面我们安装的 QEMU 的。

虽然 QEMU 拥有自己的命令,可以创建、启动虚拟机,但实际上管理虚拟机是非常复杂的,包括网络、磁盘等管理,所以说通常我们还是要用 libvirt 来管理虚拟机,毕竟它相对比较强大、全面、并且完善一点点。

作为小白,我也就了解这么一丢丢,复杂的也不懂,如果你有兴趣,可以花点时间去啃一啃官方文档。

好了,打起精神,这个 libvirt 可不好对付,要小心,开始罗!


安装所需组件

# X11 服务端,图形化界面所需
dnf install xorg-x11-server-Xorg xorg-x11-xauth xorg-x11-apps

dnf install cyrus-sasl-devel device-mapper-* gnutls-devel libxml2-devel dnsmasq dnsmasq-* libxslt libtirpc-devel libpciaccess libpciaccess-devel yajl-devel libacl-devel libattr-devel audit-libs-devel libblkid-devel fuse-devel fuse3-devel fuse3-libs libnl3-devel libiscsi-devel

pip3 install meson rst2html5 jsonschema==3.0.2

dnf install cyrus-sasl-devel device-mapper-* gnutls-devel libxml2-devel dnsmasq dnsmasq-* libxslt libtirpc-devel


安装 rpcgenportable-rpcgen

dnf install dnf-plugins-core

# 或者也可以编辑 /etc/yum.repos.d/Rocky-PowerTools.repo 将 enabled=0 改成 1。
dnf config-manager --set-enabled powertools

dnf install rpcgen --enablerepo=powertools


在这儿我要友情提示一下,编译 libvirt 时需要用到 python38 以上版本,否则会出现各种难以描述的错误。

YUM 默认官方源安装为 python36 版本,所以不能支持使用。


安装驱动程序

这个驱动程序是指 libvirt 联动 QEMU 的接口程序。

如果没有这些驱动,那么很可能有些功能就不支持了,默认情况下不安装的话,libvirt 也只提供一些基本的接口驱动。

我手动打包了这些驱动程序,虽然不全,但是基本上已经包括了大部分的功能,如果有特殊需求你也可以自行追加。

追加后别忘记还要再次编译安装一次 libvirt 才能生效。

unzip libvirt-daemon-drivers.zip
cd libvirt-daemon-drivers
rpm -ivh --nodeps libvirt-daemon-*

libvirt-daemon-drivers.zip(2.15M)

打包下载:
https://pan.baidu.com/s/1F-q6QniOol-AHQhgPLtRRQ

提取码:<头条不让放,请到网管小贾的博客中查找>


安装 libvirt

打开 libvirt 官网,按说明步骤安装,此处以 libvirt-7.6.0 版本为例。

官网链接:
https://libvirt.org/compiling.html

wget https://libvirt.org/sources/libvirt-7.6.0.tar.xz
tar xvJf libvirt-7.6.0.tar.xz
cd libvirt-7.6.0
meson build --localstatedir=/var
ninja -C build
ninja -C build install


整个安装过程有可能会非常不顺利,这毫不夸张,不是缺这个模块就是缺那个模块,甚至一时半会儿还不知道怎么填上坑。

不过别着急,可以通过编译时给出的结果来查看并判断是否有模块被正常识别。

同时可以使用以下命令来启用或禁用某些模块。

# 查看开关参数
meson configure

# 举例,当你需要重新配置时可以这样
# 配置目录在 ./build,同时开启 driver_qemu 支持(默认都是开启的)
meson --reconfigure --localstatedir=/var -Ddriver_qemu=enabled ./build


OK,如果你遇到什么迷之报错,那么可以先来看看下面我遇到过的这些坑。

感叹这部分的坑是真的多,深不可测,异常磨人,现举例如下,以供参考。


坑一:sock文件生成路径不同之迷

在后续使用 virt-manager 连接 libvirt 之时,可能会遇到如下图提示的错误。




这是由于 virt-manager 找不到 libvirt-sock 文件造成的。

然而事实上这个文件已经正常生成,只是其路径跑到了 /var/local/run/libvirt/ 之中,而 virt-manager 却硬要在 /var/run/libvirt/ 里乱找,结果自然是一无所获,找了个寂寞,最后以失败报错而告终。


我翻遍了整个互联网,找了一个方法,说是可以通过修改 libvirt 的配置文件,改变其生成 sock 文件的路径来解决。

vim /usr/local/etc/libvirt/libvirtd.conf

定位到 unix_sock_dir 一项,并按如下修改其参数。

# unix_sock_dir = "/var/local/run/libvirt"
unix_sock_dir = "/var/run/libvirt"




修改好后,virt-manager 的确可以正常连接到 libivrt 了,可是心情大好之后好景不长。

令人遗憾的是,virsh 等命令却无法正常使用,因为那么一修改,它们倒反而找不到原来的 sock 文件了。

我的天啊,疯了,我折腾了快一个星期才终于找到了终极解决方法,让我吐会儿血先......

解决方法很简单,即在编译 libvirt 时加上 --localstatedir=/var 参数即可(前面已经给出命令),这样 sock 文件就不会跑到 /var/local/run/libvirt 目录中去了。

大喜过望之后,我多吃了两碗饭!


坑二:需要手动修改源代码之迷

在编译过程中,屡次出现以 html.in 结尾的文档中的语法报错。




解决方法很简单,只是有点费时间,编辑一堆 html.in 结尾的文件,修改大概第17行,将 -- 修改成 - 即可。

vim build/docs/manpages/virkeycode-atset1.html.in


源代码还要自己修改,真新鲜哈,不过看那样子像是编译出来的文件,两个减号与注释符冲突造成了报错,看样子编译器识别有待改善啊!

需要修改的文件挺多,要有耐心,因为这是后续编译产生的文件,所以我也不方便打包给大家了,抱歉了,请大家自行修改吧。

修改完毕后再来编译就可以正常通过了。

可能需要修改的文件。

./build/docs/manpages/virkeycode-atset1.html.in
./build/docs/manpages/virkeycode-atset2.html.in
./build/docs/manpages/virkeycode-atset3.html.in
./build/docs/manpages/virkeycode-linux.html.in
./build/docs/manpages/virkeycode-osx.html.in
./build/docs/manpages/virkeycode-qnum.html.in
./build/docs/manpages/virkeycode-usb.html.in
./build/docs/manpages/virkeycode-win32.html.in
./build/docs/manpages/virkeycode-xtkbd.html.in
./build/docs/manpages/virkeyname-linux.html.in
./build/docs/manpages/virkeyname-osx.html.in
./build/docs/manpages/virkeyname-win32.html.in


一些后续处理

成功安装 libvirt 后,因为其自带 libvirtd.service ,所以我们可以直接使用 systemctl 来管理 libvirtd 程序。

# 重启或用以下命令重新加载服务配置
systemctl daemon-reload

# 启用 libvirtd 等服务,通常只要第一个就行,其他视情况启用
systemctl enable libvirtd
systemctl enable libvirt-guests
systemctl enable virtinterfaced
systemctl enable virtlockd
systemctl enable virtlogd
systemctl enable virtlxcd
systemctl enable virtnetworkd
systemctl enable virtnodedevd
systemctl enable virtnwfilterd
systemctl enable virtproxyd
systemctl enable virtqemud
systemctl enable virtsecretd
systemctl enable virtstoraged
systemctl enable virtvboxd

# 查看 libvirtd 状态,其他服务类推
systemctl status libvirtd

# 启动 libvirtd 状态,其他服务类推
systemctl start libvirtd

# 停止 libvirtd 状态,其他服务类推
systemctl stop libvirtd


当然,你也可以不通过 systemctl 而直接使用命令启动它。

# -d 为后台运行
libvirtd -d


服务启动后,会在 /var/run/libvirt 下产生几个 sock 文件。




如果出现如下错误提示,应该是 virtlogd 没有启动,启动之即可解决。

systemclt start virtlogd




第三大块:安装 virt-manager

virt-manager 是我等小白常用的用于创建和管理虚拟机的图形管理程序。

这玩意使用起来方便不少,但是安装它也是令人痛苦万分,希望大家少走弯路。


官方下载链接(建议使用 Github 上的最新版):

https://virt-manager.org/download/sources/virt-manager/virt-manager-3.2.0.tar.gz


安装说明:

https://github.com/virt-manager/virt-manager/blob/master/INSTALL.md


先决条件

  • gettext >= 0.19.6
  • python >= 3.4
  • gtk3 >= 3.22
  • libvirt-python3 >= 0.6.0
  • pygobject3 >= 3.22
  • libosinfo >= 0.2.10
  • gtksourceview3 >= 3


安装所需组件

dnf install gtk-update-icon-cache
dnf install rpm-build intltool
dnf install python3-devel python3-docutils
dnf install libosinfo gtksourceview3

# 安装 gtksourceview4 时需要
dnf install vala

dnf install pygobject3-devel
dnf install libvirt-glib gtk-vnc2
pip3 install Pygi gobject PyGObject


安装 gtksourceview4

最新版本好像是 4.8 ,但是它的依赖要求太高,我折腾了很久也没搞定,无奈选择了较低版本的 4.6

wget http://ftp.gnome.org/pub/gnome/sources/gtksourceview/4.6/gtksourceview-4.6.1.tar.xz
tar xvJf gtksourceview-4.6.1.tar.xz
cd gtksourceview-4.6.1
mkdir build && cd build
meson --prefix=/usr
ninja
ninja install


gtksourceview-4.6.1.tar.xz(1.10M)

本地下载:链接:
https://pan.baidu.com/s/1ib6woV9qFXRNiy-dx4pC4w

提取码:<头条不让放,请到网管小贾的博客中查找>


直接安装 virt-manager

在这儿建议尽量从 github 上下载,而不是从官网上,因为官网上可能并不是最新版,可能含有一些 Bug

sudo yum install rpm-build intltool
wget https://github.com/virt-manager/virt-manager/archive/refs/tags/v3.2.0.tar.gz
tar -zxvf v3.2.0.tar.gz
cd virt-manager-3.2.0
./setup.py install

如果你遇到了一些问题,可以先看看后面我写的坑,估计会有一些启发。


通过生成 rpm包来安装 virt-manager

由于直接使用源代码中的 ./setup.py install 可能无法成功安装(原因很多,似乎作者都不这么建议), 所以参考了某位国外网友的文章,通过生成 rpm 包来安装。

sudo yum install rpm-build intltool
wget https://github.com/virt-manager/virt-manager/archive/refs/tags/v3.2.0.tar.gz
tar -zxvf v3.2.0.tar.gz
cd virt-manager-3.2.0
./setup.py rpm


创建成功后,可以在当前目录的 ./noarch 目录中找到 rpm 包。

virt-install-3.2.0-1.el8.noarch.rpm
virt-manager-3.2.0-1.el8.noarch.rpm
virt-manager-common-3.2.0-1.el8.noarch.rpm

一共三个文件,我们要用到的是第二个和第三个文件。




使用 yumdnf 安装后面这两个文件,这样可以解决一些文件依赖问题。

cd ./noarch

# 先安装 virt-manager-common
dnf install virt-manager-common-3.2.0-1.el8.noarch.rpm

# 再安装 virt-manager
# 如果发现 virt-manager 的版本不是 3.2.0 ,那么建议用 rpm 安装
# rpm -ivh --nodeps virt-manager-3.2.0-1.el8.noarch.rpm
dnf install virt-manager-3.2.0-1.el8.noarch.rpm


OK,接下来请出你们熟悉的坑坑坑。


坑一:安装时出错,说什么 gi模块没找到

>>> import gi
Traceback (most recent call last):
  File "", line 1, in 
ModuleNotFoundError: No module named 'gi'

找了半天,才知道怎么安装这个倒霉组件,像下面这样就行了,呼呼......

dnf install cairo-devel cairo-gobject-devel
pip3 install Pygi gobject PyGObject


坑二:virt-manager无法正常启动,出现类似如下的错误

[root@localhost virt-manager-3.2.0]# Unable to init server: Could not connect: Connection refused
Unable to init server: Could not connect: Connection refused
Unable to init server: Could not connect: Connection refused

(virt-manager:99226): Gtk-WARNING **: 12:31:50.650: cannot open display:


这类问题说来尴尬,应该是显示服务没有正常启动造成的。

如果你正常安装了 X11 服务端,那么重启服务器,或检测 X11 服务端有无正常启动,一般情况下都能解决。


坑三:只要点击到磁盘或光驱就总是提示错误

TypeError: Argument 1 does not allow None as a value




这个错误好像是程序代码中 Python 语法的问题,由于较旧版本的 pygobject 无法正确处理 set_active(None) ,也就是说其参数不能为 None

参考链接:https://github.com/virt-manager/virt-manager/issues/188


这个问题起初困扰了我很久,甚至我都找到答案了却还不自知,一度颇费周折。

后来通过反复查验和测试,最后才发现我所做修改和测试的顺序搞错了。


首先,打开并编辑以下文件。

vim /usr/share/virt-manager/virtManager/device/addstorage.py

其次,在此文件大致第313行处,将原有代码追加 bool() 函数,如下。

# 原来的样子
removable = disk.removable

# 最终修改的样子
removable = bool(disk.removable)




最后,修改完成后,切记一定要关掉 virt-manager ,然后再重新打开测试。

其实还要补充一点,virt-manager 使用的是 python36 ,如果你用的是 python39 就会报各种错误,真是要吐了。


写在最后

经过一场场艰苦卓绝的战斗,我终于拿下了手动编译安装 KVM 的这块阵地!

虽然我已经被虐得体无完肤,但是至少我已经尝遍了各种酸甜苦辣。

擦干眼泪,继续前行!

亲爱的小伙伴们,到此为止我已经把全部过程分享出来了。

OK,请你们大声告诉我,你们都学废了吗?!

网管小贾 / sysadm.cc

相关推荐

Python入门学习记录之一:变量_python怎么用变量

写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...

python变量命名规则——来自小白的总结

python是一个动态编译类编程语言,所以程序在运行前不需要如C语言的先行编译动作,因此也只有在程序运行过程中才能发现程序的问题。基于此,python的变量就有一定的命名规范。python作为当前热门...

Python入门学习教程:第 2 章 变量与数据类型

2.1什么是变量?在编程中,变量就像一个存放数据的容器,它可以存储各种信息,并且这些信息可以被读取和修改。想象一下,变量就如同我们生活中的盒子,你可以把东西放进去,也可以随时拿出来看看,甚至可以换成...

绘制学术论文中的“三线表”具体指导

在科研过程中,大家用到最多的可能就是“三线表”。“三线表”,一般主要由三条横线构成,当然在变量名栏里也可以拆分单元格,出现更多的线。更重要的是,“三线表”也是一种数据记录规范,以“三线表”形式记录的数...

Python基础语法知识--变量和数据类型

学习Python中的变量和数据类型至关重要,因为它们构成了Python编程的基石。以下是帮助您了解Python中的变量和数据类型的分步指南:1.变量:变量在Python中用于存储数据值。它们充...

一文搞懂 Python 中的所有标点符号

反引号`无任何作用。传说Python3中它被移除是因为和单引号字符'太相似。波浪号~(按位取反符号)~被称为取反或补码运算符。它放在我们想要取反的对象前面。如果放在一个整数n...

Python变量类型和运算符_python中变量的含义

别再被小名词坑哭了:Python新手常犯的那些隐蔽错误,我用同事的真实bug拆给你看我记得有一次和同事张姐一起追查一个看似随机崩溃的脚本,最后发现罪魁祸首竟然是她把变量命名成了list。说实话...

从零开始:深入剖析 Spring Boot3 中配置文件的加载顺序

在当今的互联网软件开发领域,SpringBoot无疑是最为热门和广泛应用的框架之一。它以其强大的功能、便捷的开发体验,极大地提升了开发效率,成为众多开发者构建Web应用程序的首选。而在Spr...

Python中下划线 ‘_’ 的用法,你知道几种

Python中下划线()是一个有特殊含义和用途的符号,它可以用来表示以下几种情况:1在解释器中,下划线(_)表示上一个表达式的值,可以用来进行快速计算或测试。例如:>>>2+...

解锁Shell编程:变量_shell $变量

引言:开启Shell编程大门Shell作为用户与Linux内核之间的桥梁,为我们提供了强大的命令行交互方式。它不仅能执行简单的文件操作、进程管理,还能通过编写脚本实现复杂的自动化任务。无论是...

一文学会Python的变量命名规则!_python的变量命名有哪些要求

目录1.变量的命名原则3.内置函数尽量不要做变量4.删除变量和垃圾回收机制5.结语1.变量的命名原则①由英文字母、_(下划线)、或中文开头②变量名称只能由英文字母、数字、下画线或中文字所组成。③英文字...

更可靠的Rust-语法篇-区分语句/表达式,略览if/loop/while/for

src/main.rs://函数定义fnadd(a:i32,b:i32)->i32{a+b//末尾表达式}fnmain(){leta:i3...

C++第五课:变量的命名规则_c++中变量的命名规则

变量的命名不是想怎么起就怎么起的,而是有一套固定的规则的。具体规则:1.名字要合法:变量名必须是由字母、数字或下划线组成。例如:a,a1,a_1。2.开头不能是数字。例如:可以a1,但不能起1a。3....

Rust编程-核心篇-不安全编程_rust安全性

Unsafe的必要性Rust的所有权系统和类型系统为我们提供了强大的安全保障,但在某些情况下,我们需要突破这些限制来:与C代码交互实现底层系统编程优化性能关键代码实现某些编译器无法验证的安全操作Rus...

探秘 Python 内存管理:背后的神奇机制

在编程的世界里,内存管理就如同幕后的精密操控者,确保程序的高效运行。Python作为一种广泛使用的编程语言,其内存管理机制既巧妙又复杂,为开发者们提供了便利的同时,也展现了强大的底层控制能力。一、P...