文章目录
系统环境:debian12虚拟机
libvirt版本:v9.0.0
检查是否支持虚拟化
检查cpu是否支持虚拟化
egrep --color 'vmx|svm' /proc/cpuinfo
# 结果高亮显示vmx或svm则支持
检查cpu是否支持嵌套虚拟化
因为我是在pve的虚拟机中使用libvirt,因此需要检查此项
# intel处理器,结果为Y表示已启用
cat /sys/module/kvm_intel/parameters/nested
# amd处理器,结果为1表示已启用
cat /sys/module/kvm_amd/parameters/nested
如果要支持嵌套虚拟化
第一层虚拟机cpu类型要设置为host
或者修改pve虚拟机配置文件/etc/pve/qemu-server/[虚拟机id].conf
,最后增加args: -cpu kvm64,+svm
(AMD)
安装libvirt
# 安装包
apt install libvirt-daemon-system qemu-kvm
# 启动默认的虚拟网卡
virsh net-start default
virsh net-autostart default
# 查看默认网卡信息,我这里bridge名称是virbr0
virsh net-info default
自定义qcow2镜像
下载qcow2镜像
我这里下载了debian12的qcow2镜像
mkdir /data && cd /data
wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2
cp debian-12-genericcloud-amd64.qcow2 vm1.qcow2
调整qcow2磁盘大小和文件系统
# 这里设置为20G
qemu-img resize /data/vm1.qcow2 20G
# 加载 nbd 模块
modprobe nbd max_part=16
# 挂载磁盘到/dev/nbd0
qemu-nbd -c /dev/nbd0 /data/vm1.qcow2
# 安装growpart工具(redhat系安装cloud-utils-growpart)
apt install -y cloud-guest-utils
# 查看系统盘分区是第几个,我这里是第1个
fdisk -l
# 扩容系统盘分区
LC_ALL=en_US.UTF-8 growpart /dev/nbd0 1
# 断开磁盘挂载
qemu-nbd -d /dev/nbd0
# 卸载nbd模块
rmmod nbd
自定义系统(root密码、时区、软件源等)
# 先使用openssl生成个root用户的密码,备用
openssl passwd -1 123456
# 安装guestfish工具
apt install guestfish
# 使用guestfish编辑qcow2镜像内的文件
guestfish --rw -a /data/vm1.qcow2
进入guestfish执行
Welcome to guestfish, the guest filesystem shell for
editing virtual machine filesystems and disk images.
Type: ‘help’ for help on commands
‘man’ to read the manual
‘quit’ to quit the shell
# 执行run
><fs> run
# 列出文件系统
><fs> list-filesystems
/dev/sda1: ext4
/dev/sda14: unknown
/dev/sda15: vfat
# 挂载系统分区,我这里是第一个sda1
><fs> mount /dev/sda1 /
# 修改root密码, 把第一行root:*:19724:0:99999:7:::中的星号*(可能是其他字符)改为上面openssl生成的密码
><fs> vi /etc/shadow
# 修改sshd配置开启密码登录,把PasswordAuthentication值改为yes
><fs> vi /etc/ssh/sshd_config
# 添加dhcp网络配置(这个debian镜像默认用systemd-networkd来管理网络,其他镜像要看用的哪个网络管理工具,也可以进入虚机后修改)
><fs> vi /etc/systemd/network/20-dhcp.network
# 内容如下
[Match]
Name=enp*
[Network]
DHCP=yes
# 修改时区为Shanghai
><fs> rm /etc/localtime
><fs> ln /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 修改apt软件源,不同debian版本的配置路径可能不一样,这里忽略
><fs> vi /etc/apt/mirrors/****
# 退出编辑qcow2文件
><fs> quit
创建虚拟机
定义xml
新建文件/data/vm1.xml
,内容如下:
<domain type='kvm'>
<name>vm1</name>
<memory unit='GiB'>1</memory> <!-- 1G内存-->
<vcpu>1</vcpu> <!-- 1个CPU -->
<os>
<type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>
<boot dev='hd'/>
</os>
<features> <!-- 开启处理器特性 -->
<acpi/>
<apic/>
<pae/>
</features>
<devices>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/data/vm1.qcow2'/> <!-- qcow2镜像文件路径 -->
<target dev='vda' bus='virtio'/>
</disk>
<interface type='bridge'>
<mac address='11:11:11:11:11:11'/> <!-- 定义一个mac地址,不要重复,可以删除这行,自动会生成 -->
<source bridge='virbr0'/> <!-- default网卡的bridge名称 -->
<model type='virtio'/>
</interface>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' passwd='123456'>
</graphics>
</devices>
</domain>
启动虚拟机
# 定义虚拟机vm1
virsh define vm1.xml
# 查看所有
virsh list --all
# 启动vm1
virsh start vm1
连接虚拟机
- virsh console连接
# 连接后敲回车,会提示输入root和密码
virsh console vm1
- vnc连接,先查看自动分配的vnc端口号,然后使用vnc工具连接
宿主机ip:vnc端口号
virsh dumpxml vm1
输出内容中看到端口号为5900
...
<graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
</graphics>
...
- ssh连接,获取ip后,可执行ssh命令连接
ssh root@x.x.x.x
其他操作
添加磁盘
创建一个10G的qcow2文件
qemu-img create -f qcow2 /data/disk1.qcow2 10G
把磁盘disk1.qcow2连接到虚拟机vm1
virsh attach-disk vm1 /data/disk1.qcow2 vdb --subdriver qcow2 --persistent
# vdb 指定的设备名
# --subdriver qcow2 不填的话默认是raw格式
# --persistent 持久生效(更新了配置文件)
注意:定义xml文件时,需要开启以下处理器特性,才能支持热插拔,否则执行attach-disk会报错
...
<features>
<acpi/>
<apic/>
</features>
...
查看vm1的blk列表中多了vdb
virsh domblklist vm1
# 结果
Target Source
-----------------------------
vda /data/vm1.qcow2
vdb /data/disk1.qcow2
接着进入虚拟机,创建分区并挂载磁盘
# 连接vm1,输入用户密码后进入
virsh console vm1
# 查看磁盘信息,有一块`/dev/vdb`
fdisk -l
# 对vdb进行分区
fdisk /dev/vdb
# 输入p,回车,查看分区情况
# 输入n,回车,开始分区
# 无特殊情况的话,后面都是回车,用默认值即可
# 最后输入w,回车,写入分区表,分区完成
#创建ext4文件系统
mkfs -t ext4 /dev/vdb1
# 新建目录/data
mkdir /data
# 挂载目录
mount /dev/vdb1 /data
移除磁盘
# 取消挂载目录(虚拟机执行)
umount /data1
# 分离磁盘vdb(宿主机执行)
virsh detach-disk vm1 vdb --persistent
修改vnc密码
把虚拟机vm1的vnc密码改为456789
virsh qemu-monitor-command vm1 --cmd '{"execute": "change-vnc-password", "arguments": {"password": "456789"}}'
执行命令后,会直接生效
使用cloud-init初始化系统
新建文件/data/user-data,内容如下:
#cloud-config
hostname: vm1
local_hostname: vm1
preserve_hostname: false
users:
- name: dev
sudo: ['ALL=(ALL) NOPASSWD:ALL']
lock_passwd: false
plain_text_passwd: 123456
shell: /bin/bash
ssh_pwauth: True
network:
version: 2
ethernets:
eth0:
dhcp4: true
注意,一般root用户不允许直接登录,所以最好新加个用户,我这里加了dev用户
生成初始化镜像/data/init.iso
cloud-localds /data/init.iso user-data
修改/data/vm1.xml
# 添加disk
...
<disk type='file' device='cdrom'>
<source file='/data/init.iso'/>
<target dev='hda' bus='ide'/>
<readonly/>
</disk>
...
销毁vm1虚机,并重新创建
virsh destroy vm1
virsh undefine vm1
rm /data/vm1.qcow2
开启libvirtd的TCP监听
开启后,可以使用sdk通过tcp控制libvirt操作
# 修改libvirtd配置文件,增加四行配置
cat << EOF >> /etc/libvirt/libvirtd.conf
listen_tls=0
listen_tcp=1
auth_tcp="none"
listen_addr="0.0.0.0"
EOF
停止并禁用libvirtd 服务:
systemctl stop libvirtd
systemctl disable libvirtd
确保 socket 文件未被屏蔽:
systemctl unmask libvirtd.socket libvirtd-tcp.socket
启用并启动 libvirtd-tcp.socket:
systemctl enable --now libvirtd-tcp.socket
检查状态:
systemctl status libvirtd-tcp.socket
验证是否生效:通过tcp查看其他宿主机虚拟机列表
virsh -c qemu+tcp://192.168.22.100/system list --all
热迁移
- 首先开启目标宿主机的TCP监听
- 在目标宿主机创建虚拟机vm1.qcow2相同路径文件
qemu-img create -f qcow2 vm_disk.qcow2 10G
- 执行迁移命令
virsh migrate vm1 qemu+tcp://目标宿主机IP/system --live --unsafe --persistent --copy-storage-all --verbose
- –live 实时迁移
- –unsafe 即使可能存在风险也强制迁移
- –persistent 在目的端持久化虚拟机
- –copy-storage-all 迁移时复制非共享存储的完整磁盘(适用于非共享存储)
- –verbose 显示迁移进度