CentOS7部署安装KVM+NAT内网转换
!注意,本文与原文不完全一致。本文已为笔者实际应用场景修改。
以下所有操作请使用root用户,以避免出现权限问题。
检查CPU是否支持虚拟化
KVM 是基于 x86 虚拟化扩展(Intel VT 或者 AMD-V) 技术的虚拟机软件,所以查看 CPU 是否支持 VT 技术,就可以判断是否支持KVM。有返回结果,如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的。
对于一般的物理服务器,CPU基本上都是支持虚拟化的,如果使用下面指令后发现不支持,可自行进入BIOS开启,对于一般的云服务器或者虚拟服务器,一般都是不支持的,只有少数的云服务器的少数型号支持。
原作者使用Azure的D2S_v3类型示例进行操作,其他类型服务器可自行询问服务商或者自行测试。
笔者用的是E5-2420v2。
cat /proc/cpuinfo | egrep 'vmx|svm'
若出现红色字样则说明支持。
关闭SELinux
安装之前关闭SELinux,防止出现问题,难以进行定位。
一键式操作
[ -s /etc/selinux/config ] && sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0 >/dev/null 2>&1
手动配置
vim /etc/selinux/config
SELINUX=disabled
setenforce 0
安装KVM环境
通过 yum 安装 kvm 基础包和管理工具
kvm相关安装包及其作用:
qemu-kvm 主要的KVM程序包
libvirt C语言工具包,提供libvirt服务
virt-install 基于libvirt服务的虚拟机创建命令
virt-top 类似于htop,用于显示kvm虚拟机的数据
bridge-utils 创建和管理桥接设备的工具(由于我不需要使用桥接,所以我不安装,但是在安装以上软件包时也会顺便把这个当依赖安装了,无妨)
libvirt-client 为虚拟客户机提供的C语言工具包(以上软件包的依赖,无需选择)
virt-viewer GUI连接程序,连接到已配置好的虚拟机
virt-manager GUI虚拟机管理工具
yum -y install qemu-kvm libvirt virt-install virt-top
查看KVM模块是否被正确加载
lsmod | grep kvm
kvm_intel 188740 0 kvm 637289 1 kvm_intel irqbypass 13503 1 kvm
若看到kvm_intel类似字样则已正确加载
若未加载,请手动加载并重启然后再次检查
modprobe kvm
reboot
设置kvm服务开机启动,并即时启动kvm服务
systemctl enable --now libvirtd
查看状态操作结果,如Active: active (running),说明运行情况良好
systemctl status libvirtd
● libvirtd.service - Virtualization daemon Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled) Active: active (running) since 二 2021-09-07 23:22:52 CST; 1s ago Docs: man:libvirtd(8) https://libvirt.org Main PID: 4566 (libvirtd) Tasks: 18 (limit: 32768) Memory: 10.1M CGroup: /system.slice/libvirtd.service └─4566 /usr/sbin/libvirtd
9月 07 23:22:52 virttest systemd[1]: Starting Virtualization daemon... 9月 07 23:22:52 virttest systemd[1]: Started Virtualization daemon.
安装NAT转发模块
这里使用了官方推荐的python脚本,利用libvirt的hook特性来实现当虚拟机开机关机时修改iptables端口规则。
git clone https://hub.fastgit.org/saschpe/libvirt-hook-qemu.git
cd libvirt-hook-qemu
make install
[root@owo ~]# git clone https://hub.fastgit.org/saschpe/libvirt-hook-qemu.git 正克隆到 'libvirt-hook-qemu'... remote: Enumerating objects: 208, done. remote: Counting objects: 100% (34/34), done. remote: Compressing objects: 100% (26/26), done. remote: Total 208 (delta 17), reused 22 (delta 8), pack-reused 174 接收对象中: 100% (208/208), 50.14 KiB | 0 bytes/s, done. 处理 delta 中: 100% (113/113), done.
[root@owo ~]# cd libvirt-hook-qemu
[root@owo libvirt-hook-qemu]# make install mkdir -p /etc/libvirt/hooks cp hooks hooks.schema.json /etc/libvirt/hooks if [ ! -f /etc/libvirt/hooks/hooks.json ] ; then cp hooks.json /etc/libvirt/hooks ; fi chmod +x /etc/libvirt/hooks/hooks ln -sf /etc/libvirt/hooks/hooks /etc/libvirt/hooks/qemu ln -sf /etc/libvirt/hooks/hooks /etc/libvirt/hooks/lxc
重启kvm服务
systemctl restart libvirtd
修改虚拟网络
由于我的应用场景是一台只有一个ip的独立服务器,所以我需要让虚拟机使用NAT网络而不是bridge桥接。
而libvirt在安装完成后,默认已经创建了一个NAT网络,并且已经设置好了NAT的一系列规则,DHCP等,这个网络会给宿主机创建一张virbr0网卡,用于宿主机与虚拟机互通。
virsh net-list
名称 状态 自动开始 持久
default 活动 是 是
我们只需要对这个网络配置稍作修改。
virsh net-edit --network default
default 27168d23-ad95-4d77-ae35-9af3a2a2729b
将address为宿主机的虚拟网卡ip,根据自己的场景修改
若不需要dhcp服务,去掉dhcp块即可
修改完类似这样
default 27168d23-ad95-4d77-ae35-9af3a2a2729b
重启default网络
virsh net-destroy --network default
网络 default 被删除
virsh net-start --network default
网络 default 已开始
(这个机翻太淦了)
查看网卡ip
ip address
1929: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:33:3e:44 brd ff:ff:ff:ff:ff:ff
inet 10.0.1.254/24 brd 10.0.1.255 scope global virbr0
valid_lft forever preferred_lft forever
创建虚拟硬盘
默认磁盘镜像存储目录
/var/lib/libvirt/images/
创建一块16G的qcow2格式硬盘,给虚拟机安装系统使用
qemu-img create -f qcow2 /var/lib/libvirt/images/win.qcow2 16G
下载系统安装镜像
我这里是直接创建一个文件夹把iso用sftp丢进去了
mkdir -p /home/kvm/iso
创建虚拟机
创建一个xml文件,用于存放虚拟机配置。
vim /etc/libvirt/qemu/win.xml
xml内容:
- 适用于windows。若需要让win使用半虚拟化驱动,请自行下载virtio-win.iso并使用ide挂载。
<domain type='kvm'>
<name>win</name>
<title>A win10 vm.</title>
<description>这是一台win10的虚拟机</description>
<memory unit='GiB'>8</memory>
<vcpu placement='static'>4</vcpu>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<os>
<type arch='x86_64'>hvm</type>
<boot dev='hd'/>
<boot dev='cdrom'/>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<cpu mode='host-passthrough' match='exact' check='partial'>
<topology sockets='1' cores='4' threads='1'/>
</cpu>
<clock offset='localtime'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
</clock>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/win.qcow2'/>
<target dev='vda' bus='sata'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/home/kvm/iso/win.iso'/>
<target dev='hda' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
<interface type='network'>
<source network='default'/>
<model type='e1000'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5901' autoport='no' listen='0.0.0.0' passwd='ddi'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
</devices>
</domain>
- 适用于ubuntu
<domain type='kvm'>
<name>ubuntu</name>
<memory unit='GiB'>8</memory>
<vcpu placement='static'>4</vcpu>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<os>
<type arch='x86_64'>hvm</type>
<boot dev='hd'/>
<boot dev='cdrom'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<cpu mode='host-passthrough' match='exact' check='partial'>
<topology sockets='1' cores='4' threads='1'/>
</cpu>
<clock offset='localtime'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
</clock>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/ubuntu.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/home/kvm/iso/ubuntu.iso'/>
<target dev='hda' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<interface type='network'>
<source network='default'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5902' autoport='no' listen='0.0.0.0' passwd='ddi'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
</devices>
</domain>
创建(定义)虚拟机
virsh define --file /etc/libvirt/qemu/win.xml
启动虚拟机
virsh start win
设置端口转发
vim /etc/libvirt/hooks/hooks.json
{
"虚拟机名": {
"private_ip": "虚拟机ip",
"port_map": {
"tcp或udp": [
[宿主机端口, 虚拟机端口],
[宿主机端口, 虚拟机端口]
]
}
}
}
保存后要将虚拟机关闭再启动才生效,重启是没用的
virsh destroy win
virsh start win
启动虚拟机后查看防火墙转发
iptables -t nat -L
Chain PREROUTING (policy ACCEPT) target prot opt source destination
DNAT-win all -- anywhere owo.ddio001.funChain INPUT (policy ACCEPT) target prot opt source destination
Chain OUTPUT (policy ACCEPT) target prot opt source destination
DNAT-win all -- anywhere owo.ddio001.funChain POSTROUTING (policy ACCEPT) target prot opt source destination
SNAT-win all -- 10.0.1.1 10.0.1.1
RETURN all -- 10.0.1.0/24 base-address.mcast.net/24 RETURN all -- 10.0.1.0/24 255.255.255.255
MASQUERADE tcp -- 10.0.1.0/24 !10.0.1.0/24 masq ports: 1024-65535 MASQUERADE udp -- 10.0.1.0/24 !10.0.1.0/24 masq ports: 1024-65535 MASQUERADE all -- 10.0.1.0/24 !10.0.1.0/24Chain DNAT-win (2 references) target prot opt source destination
DNAT tcp -- anywhere owo.ddio001.fun tcp dpt:gprs-data to:10.0.1.1:3386 DNAT tcp -- anywhere owo.ddio001.fun tcp dpt:gprs-data to:10.0.1.1:3386Chain SNAT-win (1 references) target prot opt source destination
SNAT tcp -- 10.0.1.1 anywhere tcp dpt:gprs-data to:192.168.1.164 MASQUERADE tcp -- 10.0.1.1 10.0.1.1 tcp dpt:gprs-data SNAT tcp -- 10.0.1.1 anywhere tcp dpt:gprs-data to:192.168.1.164 MASQUERADE tcp -- 10.0.1.1 10.0.1.1 tcp dpt:gprs-data