第一章实验:环境搭建

实验一:搭建 KVM 虚拟化平台

安装 Host 系统

本小节为物理机安装 ubuntu 双系统说明,如采用 VMWare 等虚拟工作站方式作为运行环境可直接跳转下一小节。

  • Ubuntu 20.04 LTS 镜像
  • 制作U盘启动盘

    MacOS 系统可采用 dd 命令将U盘制作成 ubuntu 系统启动盘(windows 系统可采用 Rufus 工具)。

    $ diskutil list
    /dev/disk0 (internal, physical):
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:      GUID_partition_scheme                        *251.0 GB   disk0
       1:                        EFI EFI                     314.6 MB   disk0s1
       2:                 Apple_APFS Container disk1         250.7 GB   disk0s2
    
    /dev/disk1 (synthesized):
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:      APFS Container Scheme -                      +250.7 GB   disk1
                                     Physical Store disk0s2
       1:                APFS Volume Macintosh HD - 数据     188.9 GB   disk1s1
       2:                APFS Volume Preboot                 2.2 GB     disk1s2
       3:                APFS Volume Recovery                1.1 GB     disk1s3
       4:                APFS Volume VM                      8.6 GB     disk1s4
       5:                APFS Volume Macintosh HD            21.5 GB    disk1s5
       6:              APFS Snapshot com.apple.os.update-... 21.5 GB    disk1s5s1
    
    /dev/disk2 (external, physical):
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:     FDisk_partition_scheme                        *7.8 GB     disk2
       1:             Windows_FAT_32 TESTONLY                7.8 GB     disk2s4
    
    $ diskutil unmountDisk /dev/disk2
    Unmount of all volumes on disk2 was successful
    $ sudo dd if=/Users/challenge/Downloads/ubuntu-20.04.5-desktop-amd64.iso of=/dev/rdisk2 bs=1m
    Password:
    
    3685+1 records in
    3685+1 records out
    3864182784 bytes transferred in 625.176597 secs (6180946 bytes/sec)
    
  • 安装双系统
    • 修改bios启动顺序 U盘优先(华硕主板开机界面按 F2 进入)
    • 进入ubuntu安装,选择新的硬盘即可
    • 重启拔掉U盘
  • 重启后可能会遇到死机进入grub命令界面
    • 首先通过ls命令显示出硬盘分区信息,目的是找到boot/grub所在位置

      grub> ls (h
      Possible devices are:
      hd0 hd1
      
      grub› ls (hd0,gpt
      Possible partitions are:
      	Partition hd0,gpt1: Filesystem type fat, UUID 890D-5C71 - Partition start at 1024K1B - Total size 524288KiB
      	Partition hd0,gpt2: Filesystem type ext* - Last modification time 2023-03-23 09:33:27 Thursday, UUID 161f2ec0-a71c-4917-8abb-e4c558884663 - Partition start at 525312K1B - Total size 976236544KiB
      
      grub> ls (hd0, gpt2) /
      Possible files are:
      	lost+found/ boot/ swapfile etc/ media/ var/ bin/ dev/ home/ lib/ 11664/ mnt/ opt/ proc/ root/ run/ sbin/ snap/ srv/ sys/ tmp/ usr/ initrd.img initrd.img.old vmlinuz vmlinuz.old cdrom/ .cache/ lib32/ libx32/
      
      grub> ls (hd0,gpt2)/boot/grub/
      Possible files are:
      	gfxblacklist.txt unicode.pf2 x86_64-efi/ locale/ fonts/ grubenv grub.cfg
      
    • 如上我们发现 (hd0, gpt2) / 下有boot/grub信息,再设置相应的入口

      grub> set root=(hd0, gpt2)
      grub> set prefix=(hd0,gpt2)/boot/grub
      grub> insmod normal
      grub> normal
      
    • 然后便进入了系统选择页面,选择进入ubuntu20.04,再在终端命令行运行以下命令修复grub

        $ sudo update-grub
        [sudo] password for chalnan:
        Sourcing file '/etc/default/grub'
        Sourcing file 'etc/default/grub.d/init-select.cfg'
        Generating grub configuration file ...
        Found linux image: /boot/vmlinuz-5.15.0-67-generic
        Found initrd image: /boot/initrd.img-5.15.0-67-generic
        Found linux image: /boot/vmlinuz-5.15.0-60-generic
        Found initrd image: /boot/initrd.img-5.15.0-60-generic
        Found linux image: /boot/vmlinuz-5.15.0
        Found initrd image: /boot/initrd.img-5.15.0
        Found Ubuntu 18.04.5 LTS (18.04) on /dev/sda2
        Adding boot menu entry for UEFI Firmware Settings
        done
        $ lsblk
        NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
        sda           8:0    0 931.5G  0 disk
        ├─sda1        8:1    0   512M  0 part /boot/efi
        └─sda2        8:2    0   931G  0 part
        sr0          11:0    1  1024M  0 rom
        nvme0n1     259:0    0 931.5G  0 disk
        └─nvme0n1p1 259:1    0 931.5G  0 part /
        $ sudo grub-install /dev/nvme0n1
        Installing for x86_64-efi platform.
        Installation finished. No error reported.
      
      
    • 重启后,可以正常引导启动进入ubuntu的图形界面系统。

源码编译安装 Linux 内核

检查硬件系统支持

检查 CPU 是否支持 KVM 虚拟化。在 x86 和 x86-64 中,Intel 系列 CPU 支持虚拟化的标志为 vmx,AMD 系列 CPU 的标志为 svm ,如下命令行如有输出则表示 CPU 支持硬件虚拟化。

grep -E '(vmx|svm)' /proc/cpuinfo

配置内核

安装基础开发工具软件包,该命令会安装一系列软件包,包括 gcc, make

sudo apt update
sudo apt install build-essential

安装 ncurses libraries、flex bison 依赖库

sudo apt-get install ncurses-dev flex bison

清空现有的配置文件

make clean
make mrproper

拷贝系统原生config文件 或者 调用默认配置文件生成config

cp /boot/config-5.15.0-70-generic .config
make defconfig

然后使用可视化的配置选项,检查/增加 KVM 支持

make menuconfig

选择 Virtualization ,选中 KVM 等支持,保存并退出。

需要再检查一下证书相关的配置(不然之后 make 会报错)

vim .config

检查 CONFIG_SYSTEM_TRUSTED_KEYSCONFIG_SYSTEM_REVOCATION_KEYS的值是否为空值。

原有值:
CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"
CONFIG_SYSTEM_REVOCATION_KEYS="debian/canonical-revoked-certs.pem"
改为:
CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_SYSTEM_REVOCATION_KEYS=""

编译内核

安装编译依赖

sudo apt install libssl-dev libelf-dev dwarves zstd

编译 kernel,-j 参数表示并行编译,本机器逻辑 cpu 的数量为8,因此选择 -j8。逻辑 cpu 的数量可通过如下命令返回:

cat /proc/cpuinfo | grep "processor" |wc -l

编译

make -j8

安装内核

安装 module

make modules_install

以上命令将 module 安装到相应的目录中,默认情况下被安装到 /lib/modules/$kernel_version/kernel 目录之中,安装完之后可以查看 KVM 模块:

ls -l /lib/modules/5.15.0/kernel/arch/x86/kvm/

安装 kernel 和 initramfs

make install

此时可见 /boot 目录下生成了内核(vmlinuz)和 initramfs 等内核启动所需的文件, grub 配置文件中自动添加了一个 grub 选项

ls -l /boot/
cat /boot/grub/grub.cfg |grep menuentry

更改 grub 配置文件

vim /etc/default/grub
# 注释掉GRUB_TIMEOUT_STYLE并将GRUB_TIMEOUT设置为10s
# GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=10

接着使更改生效

sudo update-grub

重启,ubuntu选择界面中选择新安装的内核启动,查看当前内核版本

uname -a

查看 kvm 和 kvm_intel 两个模块是否加载

lsmod |grep kvm
# 如果没有就手动加载
modprobe kvm
modprobe kvm_intel

检查 /dev/kvm 文件,该文件是 KVM 内核模块提供给用户空间的 qemu-kvm 程序使用的一个控制接口

ls -l /dev/kvm

单独编译 KVM 模块

进入 Linux 源码目录,执行以下命令单独编译 KVM 模块

make -j8 -C `pwd` M=`pwd`/arch/x86/kvm
rmmod kvm-intel
rmmod kvm
insmod arch/x86/kvm/kvm.ko
insmod arch/x86/kvm/kvm-intel.ko

源码编译安装 QEMU

配置 QEMU

安装依赖库

sudo apt install libglib2.0-dev libpixman-1-dev

创建 build 目录并配置支持 KVM 选项、目标架构名以及调试选项

mkdir build
cd build
../configure --enable-kvm --target-list=x86_64-softmmu --enable-debug

完成之后查看输出确保配置正确:

VNC support yes # 通常需要通过 VNC 连接到客户机中
KVM support yes # 这是对 KVM 的支持

编译安装 QEMU

编译 QEMU, make 完成之后在 build/x86_64-softmmu/ 目录下生成了可执行文件 qemu-system-x86_64 。执行 make install 将 QEMU 安装到 host 系统环境中。

make -j8
make install

检查安装之后的系统状态

which qemu-system-x86_64
which qemu-img

QEMU 是用户态的程序,不需要重启系统,直接用 qemu-systemx86_64 命令行工具即可启动虚拟机。

实验二:创建并启动虚拟机

下载镜像

  • 首先下载一个供虚拟机运行的镜像(本实例为 ubuntu.iso,读者可自行选择其他iso),并切换到存放镜像的路径下

创建磁盘文件

  • 创建一个空的镜像文件来存储虚拟机的系统和文件(也可采用 qemu-img 命令)

    dd if=/dev/zero of=guest.img bs=1M count=40960
    

    dd 命令用于生成虚拟块设备文件。if 参数告诉 dd 从哪个文件读取数据, of 参数表示读出的数据写入哪个文件中。 /dev/zero 是 Linux 提供的一个特殊的字符设备,其每次读取的结果都是二进制0,可用于生成空镜像文件。bs=1M 表示每一次读写1M数据,count=40960表示读写 40960 次,这样就指定了生成文件的大小为40G。

启动虚拟机

qemu-system-x86_64 -cpu host -smp 1 -m 2048 --enable-kvm guest.img -cdrom ubuntu.iso

-cpu 参数用于指定cpu类型和型号, -smp 参数用于cpu核数, -m 参数用于指定内存大小,-cdrom 参数用于指定要载入的镜像。

安装 gvncviewer 并连接虚拟机

sudo apt install gvncviewer
gvncviewer 127.0.0.1::5900 # 默认情况 QEMU 开启5900端口

Ctrl+Alt+2 切换到 QEMU 监视器窗口,可以执行 info kvm 命令来查看当前 QEMU 是否使用 KVM。Ctrl+Alt+1 切换回原窗口。