开源免费虚拟化KVM的部署及其虚拟机资源变更、快照、克隆等常见运维操作

实践说明:基于RHEL9(AlmaLinux9.1)部署,同类系统(CentOS9,RockyLinux9等)适用,但适用场景是不限于此的。

文档说明:本文档旨在帮助快速应用KVM虚拟化技术,重在实践操作,提供了简要参考。

文档形成时期:2021-2023年

因系统或软件版本不同,构建部署可能略有差异,但本文未做细分,对稍有经验者应不存在明显障碍。

因软件世界之复杂和个人能力之限,难免疏漏和错误,欢迎指正。

文章目录

kvm基本了解

KVM(Kernel-based Virtual Machine)即基于内核的虚拟机,是一种开源的虚拟化技术。

KVM技术由KVM引擎、虚拟化程序QEMU和管理工具Libvirt组成。

KVM引擎:它是一种基于虚拟化扩展(Intel VT或者AMD-V)的X86硬件的Linux原生全虚拟化引擎,在其中虚拟机被实现为常规的linux进程,由标准linux调度程序进行调度。

虚拟化软件QEMU:

虚拟化软件QEMU:开源的I/O虚拟化软件,可以对一个完整的计算机物理层环境进行虚拟化(如网卡、硬盘等)。QEMU原本并不是KVM的一部分,但其代码包含一套完整的虚拟化解决方案(处理机虚拟化、内存虚拟化、设备虚拟化),而被KVM所采用。

管理工具Libvirt

管理工具Libvirt:其设计目的是通过相同的方式管理不同的虚拟化引擎,如KVM、Xen、LXC等,是一种开源工具,主要由以下三部分功能组成:

(1)支持主流编程语言,如C、Python、Ruby等的API和库。

(2)Libvirtd服务。

(3)命令行工具virsh。

libvirt可以对虚拟机进行管理,包括虚拟机的创建、启动、关闭、挂起、恢复等,也可以对虚拟机的硬件设备进行添加和删除。

安装

KVM相关软件的安装方法

检查宿主机BIOS设置

开启Inter VT-x/EPT或AMD-V/RVI(V)等,如果用vmware做实验,共有三项虚拟化引擎相关的配置可启用,除前面的一项,还有虚拟化CPU性能计数器(U),虚拟化IOMMU(IO内存管理单元)(I)。

安装VNC相关组件

yum -y install tigervnc tigervnc-server tigervnc-server-module

复制VNC配置模板文件

cp /lib/systemd/system/vncserver@.service /lib/systemd/system/vncserver@:1.service

可修改VNC配置文件

启动VNC服务

systemctl start vncserver@:1.service

systemctl enable vncserver@:1.service

防火墙开启5901端口

KVM引擎启用和组件安装

检查cpu是否支持虚拟化

egrep '(vmx|svm)' /proc/cpuinfo

检查BIOS虚拟化

lsmod | grep kvm

以上有相关输出结果,则说明虚拟化开关已开启

加载KVM模块到宿主机系统中

Intel CPU使用:

modprobe kvm-intel

AMD CPU使用:

modprobe kvm-amd

yum安装kvm相关组件

sudo dnf install qemu-kvm virt-manager libvirt virt-install virt-viewer virt-top bridge-utils bridge-utils virt-top libguestfs-tools -y

QEMU/KVM代码下载编译安装

暂略

图形界面创建和管理虚拟机

安装Linux图形界面(也许可选)

yum groupinstall "X Window System"

创建网桥

首次创建虚拟机可以不自行创建网桥,使用默认网桥。

启动虚拟机管理界面(已安装图形界面的情况下)

virt-manager

接下来可安装配置各类虚拟机,就像esxi和vmware一样部署虚拟机。

命令行方式创建网桥和管理虚拟机

启动 libvirtd 守护进程

systemctl start libvirtd

systemctl enable libvirtd

systemctl status libvirtd

设置桥接接口

nmcli connection show

创建网桥,首先,使用以下语法用其 UUID 删除连接(准备给客户机桥接的网卡):

nmcli connection delete UUID

创建一个新的桥接接口(也可以改用libvirtd默认网桥,即删除默认网桥再新建,或直接修改IP地址达到预期配置也行)

语法:

nmcli connection add type bridge autoconnect yes con-name BRIDGE NAME ifname BRIDGE NAME

实例:

nmcli connection add type bridge autoconnect yes con-name kvmbr0 ifname kvmbr0

配置桥接网卡

nmcli connection modify kvmbr0 ipv4.addr 192.168.130.85/24 ipv4.gateway 192.168.130.1 ipv4.method manual ipv4.dns 223.5.5.5,223.6.6.6

nmcli con reload kvmbr0

nmcli con up kvmbr0

添加网桥从属设备(把刚才删除UUID的宿主机网卡加入桥接网络来)

nmcli connection add type bridge-slave autoconnect yes con-name eth0 ifname eth0 master kvmbr0

查看网卡从属状态,可执行

ip a (其中master便是其主网卡)

brctl show

编辑网桥配置文件

vi /etc/qemu-kvm/bridge.conf

添加

allow all

重新启动虚拟化守护进程以应用更改

systemctl restart libvirtd

防火墙调整

桥接网络受宿主机iptables的FORWARD链控制,在有docker环境情况下默认是DROP的,可以添加一条允许,或者更为严格的策略脚本。

详细参考脚本:/root/sh/iptables_for_kvm.sh

bash 复制代码
#!/bin/bash
###################################
# function  iptables config for kvm
#
# create: touch /root/sh/iptables_for_kvm.sh; chmod 700 /root/sh/iptables_for_kvm.sh
#
# Change History:
# date        author          note
# 2012/08/31  N  创建
# 2013/07/04  N  为xen环境的iptables转发控制设计
# ......
# 2023/07/22  N  基于原xen环境的iptables转发控制,改编为适用于kvm
###################################

 
######### ENV #################

# 脚本名称,临时文件或邮件中可能用到,避免同类脚本的变量的冲突,下面直接取脚本名
export project_name=`echo ${0##*/} | cut -d'.' -f 1`

kvmbr_eth=kvmbr0
kvmbr_net=192.168.130.160/27  # 160-191

export LANG=C
export LC_ALL=C
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin


### filter table ###
 
## FORWARD chains ##
# 在默认配置中添加自定义链
iptables -F KVM_CUSTOM > /dev/null 2>&1
iptables -D FORWARD -j KVM_CUSTOM > /dev/null 2>&1
iptables -X KVM_CUSTOM > /dev/null 2>&1
iptables -N KVM_CUSTOM
iptables -I FORWARD -j KVM_CUSTOM

# 在自定义链中配置策略
# global
# iptables -A KVM_CUSTOM -j ACCEPT # allow all
iptables -A KVM_CUSTOM -d $kvmbr_net -o $kvmbr_eth -m state --state RELATED,ESTABLISHED -j ACCEPT
#iptables -A KVM_CUSTOM -s $kvmbr_net -i $kvmbr_eth -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A KVM_CUSTOM -s $kvmbr_net -i $kvmbr_eth -j ACCEPT
iptables -A KVM_CUSTOM -d $kvmbr_net -o $kvmbr_eth -p udp -m multiport --dport 53,5353,123,323 -j ACCEPT
iptables -A KVM_CUSTOM -p udp -m multiport --dport 67:68 -j ACCEPT


# 独立配置
iptables -A KVM_CUSTOM -s 0.0.0.0/0 -d 192.168.130.160 -p tcp -m multiport --dport 20,21,22 -j ACCEPT


# 记录将被阻止的连接
iptables -A KVM_CUSTOM -j LOG

### nat table ###


###### save ####################
iptables-save -c > /etc/sysconfig/iptables
iptables-save -c > /etc/sysconfig/iptables_$(date +%Y%m%d-%H%M)

iptables日志经验

例:Jul 22 15:42:51 vh0025 kernel: IN=kvmbr0 OUT=kvmbr0 PHYSIN=vnet3 PHYSOUT=eth0 MAC=ff:ff:ff:ff:ff:ff:52:54:00:e5:74:8f:08:00 SRC=0.0.0.0 DST=255.255.255.255 LEN=325 TOS=0x00 PREC=0xC0 TTL=64 ID=0 PROTO=UDP SPT=68 DPT=67 LEN=305

MAC前面ff:ff:ff:ff:ff:ff部分是广播地址,是源地址,后面是目标地址,08:00可能是保留用的,暂不用关心。

命令行方式创建虚拟机

bash 复制代码
virt-install \
    --name kvm0001-Ubuntu20.04 \
    --memory memory=4096,currentMemory=2048 \
    --vcpus 1,maxvcpus=4,cpuset=1 \
    --disk path=/var/lib/libvirt/images/ubuntu-20.04.qcow2,size=15,format=qcow2,bus=virtio,sparse=true \
    --os-variant ubuntu20.04 \
    --hvm \
    --network bridge=kvmbr0,model=virtio \
    --graphics vnc,listen=0.0.0.0,port=5901,password=kvmpass \
    --console pty,target_type=serial \
    --cdrom /opt/isos/ubuntu-22.04.2-live-server-amd64.iso

virt-install工具命令详解

一般选项

-n NAME, --name=NAME:虚拟机名称,需全局唯一

-r memory, --ram=MEMORY:虚拟机内存大小,单位MB

--vcpus=CPU: CPU模式及特性,如coreduo等;可以使用 qemu-kvm -cpu 来获取支持CPU模式

安装方法

-c CDROM, --cdrom=CDROM: 光盘安装介质

-l LOCATION, --location=LOCATION: 安装源URL,支持FTP、HTTP及NFS等

--pxe: 基于PXE完成安装

--livecd: 把光盘当做LiveCD

--os-type=DISTRO_TYPE: 操作系统类,如linux,unix,windows等

--os-variant=DISTRO_VARIANT: 某类型操作系统的变体,如rhel5, fedora8 可以通过"osinfo-query os"命令查看,该命令是libosinfo包的,A library for managing OS information for virtualization

-x EXTRA, --extra-args=EXTRA: 根据--location指定的方式安装GuestOS时,

用于传递给内核的额外选项,例如指定kickstart文件的位置 --extra-args "ks=http://172.16.0.1/class.cfg"

--boot=BOOTIOTS: 指定安装过程完成后的配置选项,如指定引导设备次序,使用指定的而非安装的kernel/initrd来引导系统启动等

--boot cdrom,hd,network: 指定引导次序

--boot kernel=KERNEL,initrd=INITRD,kernel_args="console=/dev/ttyS0": 指定启动系统的内核及initrd文件

存储配置

--disk=DISKOPTS: 指定存储设备及其属性;格式:--disk /some/storage/path, opt1=val1, opt2=val2等

常用选项:

device: 设备类型,如cdrom,disk,floppy等,默认disk

bus: 磁盘总结类型,其值可以为ide, scsi, usb, virtio, xen等

perms: 访问权限,如rw, ro, sh 默认rw

size: 新建磁盘镜像的大小,单位GB

cache: 缓存类型,其值none, writethrouth(缓存读), writeback(缓存读写)

format: 磁盘镜像格式,如 raw, qcow2, vmdk等,阿里云镜像导入支持RAW、QCOW2、VHD等格式,推荐传输内容更小的QCOW2或者VHD格式,如果考虑和vmware之间迁移,可采用vmdk格式

sparse: 磁盘镜像使用稀疏格式,即不立即分配指定大小的空间,实践中发现,仅采用sparse参数时,其值默认是false,应明确指定,sparse=true。查看实际大小时,用du -sh,而不要用ls -lh

--nodisks: 不使用本地磁盘,在LiveCD模式中常用

网络配置

-w NETWORK, --network=NETWORK opt1=val1, opt2=val2: 将虚拟机连入宿主机的网络中,其中NETWOR值可以为:

bridge=BRIDGE: 连接到名为"BRIDEG"的桥设备

network=NAME: 连接到名为"NAME"网络

其他常用的选项

model: GuestOS中看到的网络设备型号,ru e1000, rtl8139或virtio等

mac: 固定的MAC地址;省略此选项时将使用随机地址,但无论何种方式,对于KVM来说,其前三段必须时52:54:00

--nonetworks: 虚拟机不使用网络功能

图形配置

--graphics TYPE, opt1=val1,opt2=val2: 指定图形显示相关配置,此选项不会配置任何显示硬件(如显卡),而是仅仅指定虚拟机启动后对其进行访问的接口

TYPE: 指定显示类型,可以是vnc, sdl, spice, none,默认vnc

port: TYPE为vnc或spice时其监听的端口

listen: TYPE为vnc或spice时所监听的IP地址,默认为127.0.0.1,可以通过修改/etc/libvirt/qemu.conf定义新的默认值

password: TYPE为vnc或spice时,为远程访问监听的服务进行指定认证密码

--noautoconsole: 禁止自动连接到虚拟机的控制台

设备选项

--serial=CHAROPTS: 附加一个串行设备至当前虚拟机,根据设备类型的不同,可以使用不同的选项,格式为"--serial type, opt1=val1, opt2=val2"

例如:

--serial pty:创建伪终端;

--serial dev,path=HOSTPATH:附加主机设备至此虚拟机;

--video=VIDEO:指定显卡设备模型,可用取值为cirrus、vga、qxl或vmvga;

虚拟化平台

-v, --hvm:当物理机同时支持完全虚拟化和半虚拟化时,指定使用完全虚拟化;

-p, --paravirt:指定使用半虚拟化;

--virt-type:使用的hypervisor,如kvm、qemu、xen等;所有可用值可以使用'virsh capabilities'命令获取;

其它:

--autostart:指定虚拟机是否在物理启动后自动启动;

--print-xml:如果虚拟机不需要安装过程(--import、--boot),则显示生成的XML而不是创建此虚拟机;默认情况下,此选项仍会创建磁盘映像;

--force:禁止命令进入交互式模式,如果有需要回答yes或no选项,则自动回答为yes;

--dry-run:执行创建虚拟机的整个过程,但不真正创建虚拟机、改变主机上的设备配置信息及将其创建的需求通知给libvirt;

-d, --debug:显示debug信息;

问题排查

问题:ubuntu虚机启动时卡在booting from hard disk

进入系统后,检查/det/default/grub配置文件是否有异常。

经大佬排查,是grub中配置的console参数只配置了ttyS0,导致控制台所有的输出都去了串口,而没有在tty0(vnc)上显示,所以在引起系统启动后,vnc就看不到任何输出了。所以对于console参数至少需要配置一个tty0,ttyS0根据需求可选。

修改后,对于ubuntu系统可以执行 update-grub2 命令更新一下grub相关文件,之后重启测试,发现可以通过引导界面进入虚机。

可是按上面的操作后,情况依旧,

分析:推测是卡在grub倒计时,但是又没有显示,修改倒计时后,果然有变化,不过是"booting from hard disk"在倒计时后消失了,直接变成黑屏,还是要等很久。

有网友添加"--virt-type=qemu"的,实践发现,问题依旧,且这已经不是kvm了。

考虑到该问题不明显,暂时搁置。

安装过程经验

安装客户端过程中,发现获取不到IP,网络也不通,查看宿主机防火墙iptables,有关于默认桥接网卡virbr0的配置,但没有自定义桥接网卡的配置。

(想不到libvirtd即使在rhel9上仍然利用的iptables而非firewalld,iptables的FORWARD在有docker环境情况下默认是DROP的,/etc/qemu-kvm/bridge.conf的配置似乎和iptables也没有直接关系。所以在非必要情况下,仍把iptables做为唯一防火墙配置仍然是个不错的选择)

解决办法:改用virbr0做为默认网桥(默认是用户网络,即NAT模式),或为自定义网桥添加iptables的FORWARD链策略。实践中选择了后者,详细参考脚本:/root/sh/iptables_for_kvm.sh

ubuntu20.04最小化安装完成后,最后提示是:final system configuration 或 restoring apt configuration

完整日志是:finish cmd-system-install: success: curtin command system-install

重启即可。

管理kvm虚拟机

列出所有的虚拟机

virsh list --all

虚拟机改名

实践例:

cd /etc/libvirt/qemu

关机,导出xml virsh dumpxml kvm0001-Ubuntu20.04 > kvm0001-ubuntu20.04.xml

修改磁盘文件名(可选) cd /var/lib/libvirt/images

修改xml配置中的名称和磁盘文件名 vi kvm0001-ubuntu20.04.xml

删除老的 virsh undefine kvm0001-Ubuntu20.04

定义新的 virsh define /etc/libvirt/qemu/kvm0001-ubuntu20.04.xml

查看结果 virsh list --all

经过如上方法重命名的kvm机直接启动使用即可,不会影响udev动态管理设备的文件。和之前的虚拟机相比、仅仅就是名字变了而已。

显示虚拟机信息

virsh dominfo kvm0001

显示虚拟机内存和cpu的使用情况

yum install virt-top -y

virt-top

显示虚拟机分区信息

virt-df kvm0001

关闭虚拟机(shutodwn)

virsh shutdown kvm0001

强制关闭KVM虚拟机

virsh destroy kvm0001

启动虚拟机

virsh start kvm0001

设置虚拟机(kvm0001)跟随系统自启

virsh autostart kvm0001

关闭虚拟及自启

virsh autostart --disable kvm0001

删除虚拟机

virsh undefine kvm0001

通过控制窗口登录虚拟机

virsh console kvm0001

将linux客户端的console输出重定向到串口ttyS0(宿主机控制台)

脚本:

bash 复制代码
#!/usr/bin/env bash
set -x
set -e

sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200"/g' /etc/default/grub
sed -i 's/^#GRUB_TERMINAL.*/GRUB_TERMINAL="console serial"/g' /etc/default/grub
sed -i '/GRUB_TERMINAL/aGRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"' /etc/default/grub
cat /etc/default/grub

grub-mkconfig -o /boot/grub/grub.cfg

reboot

改变虚拟机的参数

通过命令行更改创建之后虚拟机的内存,cpu等信息

更改内存

1.查看虚拟机当前内存

[root@sh-kvm0001 ~]# virsh dominfo kvm0001 | grep memory

Max memory: 4194304 KiB

Used memory: 4194304 KiB

2.动态设置内存为512MB,内存减少

virsh setmem kvm0001 524288

#注意单位必须是KB,且不能超过最大内存限定,要超过的话,只能停止后修改

3.查看内存变化

#virsh dominfo kvm0001 | grep memory

Max memory: 14194304 KiB

Used memory: 524288 kiB

4.最大内存增加

virsh shutdown kvm0001

virsh edit kvm0001 # 直接更改memory

virsh create /etc/libvirt/qemu/kvm0001/xml

或 virsh setmaxmem kvm0001 4096M --config

#之后操作1,2,3步骤增加内存

更改CPU

需要修改配置文件,因此需要停止虚拟机

virsh shutdown kvm0001

virsh edit kvm0001

#  <vcpu>2</vcpu>  # 4 > 2

virsh create /etc/libvirt/qemu/kvm0001/xml

硬盘扩容

暂略

修改虚拟机配置

virsh edit kvm0001

删除虚拟机

第一步,停掉虚拟机

virsh shutdown kvm0001

第二步

virsh destroy kvm0001

第三步

virsh undefine kvm0001

第四部

rm /dev/vg_shkvm1/kvm0001 # 不建议删除硬盘

KVM虚拟机网络配置 Bridge方式,NAT方式

KVM 客户机网络连接有两种方式:

用户网络(User Networking)(NAT方式):让虚拟机访问主机、互联网或本地网络上的资源的简单方法,但是不能从网络或其他的客户机访问客户机,性能上也需要大的折扣。

虚拟网桥(Virtual Bridge)(Bridge方式):这种方式要比用户网络复杂一些,但是设置好后客户机与互联网,客户机与主机之间的通信都很容易。

删除默认的NAT网络(不是必要的,也暂不推荐)

virsh net-destroy default

virsh net-undefine default

service libvirtd restart 或 systemctl restart libvirtd

删除桥接网卡

brctl delif kvmbr0 # 未成功

nmcli connection del kvmbr0

Bridge方式

Bridge方式配置出来的接口对NAT方式没有影响,因为NAT方式并没有使用物理网卡。但作为客户机,每张网卡只能选择其中的一种。

快照

我们只能对磁盘格式为 Qcow2 的虚拟机的进行快照,并且 kvm 的 virsh 命令不支持 raw 磁盘格式,可使用以下命令将原始磁盘格式转换为 qcow2。

qemu-img convert -f raw -O qcow2 image-name.img image-name.qcow2

创建快照语法:

virsh snapshot-create-as --domain {vm_name} --name {snapshot_name} --description "enter description here"

实例:

[root@kvm-hypervisor ~]# virsh snapshot-create-as --domain kvm0001-ubuntu20.04 --name kvm0001-ubuntu20.04_snap --description "snap"
Domain snapshot webserver_snap created

查看快照

virsh snapshot-list kvm0001-ubuntu20.04

要列出虚拟机快照的详细信息

virsh snapshot-info --domain kvm0001-ubuntu20.04 --snapshotname kvm0001-ubuntu20.04_snap

查看快照的大小(关机之后才能看)

qemu-img info /var/lib/libvirt/images/kvm0001-ubuntu-20.04.qcow2

还原 KVM 虚拟机快照

语法:virsh snapshot-revert {vm_name} {snapshot_name}

实践

[root@kvm-hypervisor ~]# virsh snapshot-revert kvm0001-ubuntu20.04 kvm0001-ubuntu20.04_snap

删除 KVM 虚拟机指定的快照

virsh snapshot-delete --domain kvm0001-ubuntu20.04 --snapshotname kvm0001-ubuntu20.04_snap

克隆

直接克隆虚拟机

先关机

语法:virt-clone -o 原虚拟机 -n 新虚拟机 -f 新虚拟机存放的路径

实践:

virt-clone -o kvm0001-ubuntu20.04 -n kvm0003-ubuntu20.04 -f /var/lib/libvirt/images/kvm0003-ubuntu-20.04.qcow2

完成

实践发现,vnc端口,mac地址都会自动变,但主机名和IP地址需要手动去改。

相关推荐
龙鸣丿35 分钟前
Linux基础学习笔记
linux·笔记·学习
耶啵奶膘2 小时前
uniapp-是否删除
linux·前端·uni-app
_.Switch3 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
2401_850410833 小时前
文件系统和日志管理
linux·运维·服务器
JokerSZ.3 小时前
【基于LSM的ELF文件安全模块设计】参考
运维·网络·安全
XMYX-04 小时前
使用 SSH 蜜罐提升安全性和记录攻击活动
linux·ssh
芯盾时代4 小时前
数字身份发展趋势前瞻:身份韧性与安全
运维·安全·网络安全·密码学·信息与通信
IT规划师4 小时前
开源 - Ideal库 - 常用时间转换扩展方法(二)
开源·.net core·时间转换·ideal库
心灵彼岸-诗和远方5 小时前
DevOps业务价值流:架构设计最佳实践
运维·产品经理·devops
一只哒布刘5 小时前
NFS服务器
运维·服务器