作者:admin,发布日期:2020-01-08
阅读:4798;评论:1

本文将以Centos为基础,详解KVM环境安装,虚拟机的创建,以及NAT服务器的创建管理与端口转发。

KVM的安装

检测CPU是否支持虚拟化

KVM 是基于 x86 虚拟化扩展(Intel VT 或者 AMD-V) 技术的虚拟机软件,所以查看 CPU 是否支持 VT 技术,就可以判断是否支持KVM。有返回结果,如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的。

对于一般的物理服务器,CPU基本上都是支持虚拟化的,如果使用下面指令后发现不支持,可自行进入BIOS开启,对于一般的云服务器或者虚拟服务器,一般都是不支持的,只有少数的云服务器的少数型号支持。作者这里是使用Azure的D2S_v3类型示例进行的操作,其他类型服务器可自行询问服务商或者自行测试。

cat /proc/cpuinfo | egrep 'vmx|svm'
flags   : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm xsaveopt cqm_llc cqm_occup_llc

关闭SELinux

安装之前关闭SELinux,防止出现问题,难以进行定位。

[ -s /etc/selinux/config ] && sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0 >/dev/null 2>&1

安装 KVM 环境

通过 yum 安装 kvm 基础包和管理工具

kvm相关安装包及其作用:

  • qemu-kvm 主要的KVM程序包

  • python-virtinst 创建虚拟机所需要的命令行工具和程序库

  • virt-manager GUI虚拟机管理工具

  • virt-top 虚拟机统计命令

  • virt-viewer GUI连接程序,连接到已配置好的虚拟机

  • libvirt C语言工具包,提供libvirt服务

  • libvirt-client 为虚拟客户机提供的C语言工具包

  • virt-install 基于libvirt服务的虚拟机创建命令

  • bridge-utils 创建和管理桥接设备的工具

yum -y install qemu-kvm libvirt virt-install bridge-utils 

# 重启宿主机,以便加载 kvm 模块
# ------------------------
reboot

# 查看KVM模块是否被正确加载
# ------------------------
lsmod | grep kvm

kvm_intel             162153  0
kvm                   525259  1 kvm_intel

安装完成后开启kvm服务,并且设置其开机自动启动

systemctl enable --now libvirtd.service

查看状态操作结果,如Active: active (running),说明运行情况良好

[root@libvirt-test ~]# systemctl status libvirtd.service 
● libvirtd.service - Virtualization daemon
   Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2020-01-06 10:55:55 UTC; 1 day 22h ago
     Docs: man:libvirtd(8)
           https://libvirt.org
 Main PID: 52742 (libvirtd)
    Tasks: 18 (limit: 32768)
   CGroup: /system.slice/libvirtd.service
           ├─34377 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libv...
           └─52742 /usr/sbin/libvirtd --listen

Jan 06 10:55:55 libvirt-test systemd[1]: Starting Virtualization daemon...
Jan 06 10:55:55 libvirt-test libvirtd[52742]: Could not find keytab file: /etc/libvirt/krb5.tab: No such file or directory
Jan 06 10:55:55 libvirt-test libvirtd[52742]: gssapiv2_client_plug_init() failed in sasl_server_add_plugin(): generic failure
Jan 06 10:55:55 libvirt-test libvirtd[52742]: _sasl_plugin_load failed on sasl_server_plug_init for plugin: gssapiv2
Jan 06 10:55:55 libvirt-test systemd[1]: Started Virtualization daemon.
Jan 06 10:55:55 libvirt-test dnsmasq[34377]: read /etc/hosts - 2 addresses
Jan 06 10:55:55 libvirt-test dnsmasq[34377]: read /var/lib/libvirt/dnsmasq/default.addnhosts - 0 addresses

KVM使用

这里直接引入一个案例,来讲解KVM下开设NAT虚拟机的方法。

实现功能

  1. 创建一个NAT类型的网络

  2. 为NAT网络设置IP,关闭DHCP

  3. 创建虚拟机硬盘

  4. 下载系统安装光盘

  5. 创建一台NAT网络的虚拟机

  6. 为NAT虚拟机安装系统

  7. 配置NAT虚拟机的IP地址

  8. 限制NAT虚拟机可以使用的IP,以及防止MAC地址欺骗

  9. 配置NAT服务器的端口转发

创建一个NAT类型的网络

libvirt在安装完成后,默认已经创建了一个NAT类型的网络,并且已经设置好了NAT的一系列规则,DHCP等,这个网络会给宿主机创建一张virbr0网卡,用于宿主机与虚拟机互通。

[root@libvirt-test ~]# virsh net-list 
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 default              active     yes           yes
[root@libvirt-test ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0d:3a:85:3b:a7 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.4/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20d:3aff:fe85:3ba7/64 scope link 
       valid_lft forever preferred_lft forever
16: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:db:0b:50 brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.1/24 brd 172.16.0.255 scope global virbr0
       valid_lft forever preferred_lft forever
17: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:db:0b:50 brd ff:ff:ff:ff:ff:ff

为NAT网络设置IP,关闭DHCP

这里关闭了DHCP,后续我们将为虚拟机配置固定IP,以实现虚拟机端口的转发。

[root@libvirt-test ~]# virsh net-edit --network default
<network>
  <name>default</name>
  <uuid>cdc0710e-bddf-492a-bb44-bf2f1f60adca</uuid>
  <forward mode='nat'/>
  <bridge name='virbr0' stp='on' delay='0'/>
  <mac address='52:54:00:70:54:4f'/>
  <ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.2' end='192.168.122.254'/>
    </dhcp>
  </ip>
</network>

去掉dhcp块,然后将address改成172.16.0.1

修改完后类似这样

Snipaste_2020-01-08_17-47-18.png

编辑好后,输入:wq!退出

修改完后,需要重启网络,重启完成查看IP,已经修改成功,DHCP也已经关闭。

[root@virt ~]# virsh net-destroy --network default 
Network default destroyed
     
[root@virt ~]# virsh net-start --network default 
Network default started

[root@virt ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0d:3a:a0:8f:e4 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.4/24 brd 10.0.1.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20d:3aff:fea0:8fe4/64 scope link 
       valid_lft forever preferred_lft forever
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:70:54:4f brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.1/24 brd 172.16.0.255 scope global virbr0
       valid_lft forever preferred_lft forever
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:70:54:4f brd ff:ff:ff:ff:ff:ff

创建虚拟机硬盘

创建一块10G的qcow2硬盘,给虚拟机使用。

qemu-img create -f qcow2 /var/lib/libvirt/images/default.qcow2 10G

下载系统安装光盘

下载ISO文件,给虚拟机使用,将其放到/data/isos目录下,以便归档。

[root@virt ~]# wget http://mirrors.163.com/centos/7.7.1908/isos/x86_64/CentOS-7-x86_64-Minimal-1908.iso
[root@virt ~]# mkdir -p /data/isos
[root@virt ~]# mv CentOS-7-x86_64-Minimal-1908.iso /data/isos/

创建虚拟机

创建一个xml文件,用于存放虚拟机配置,这里直接使用模板。

vim /etc/libvirt/qemu/default.xml
# 将下面配置写入到文件内
<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
  virsh edit default
or other application using the libvirt API.
-->

<domain type='kvm'>
  <name>default</name>
  <memory unit='KiB'>1048576</memory>
  <currentMemory unit='KiB'>1048576</currentMemory>
  <vcpu placement='static'>1</vcpu>
  <os>
    <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
    <boot dev='hd'/>
    <boot dev='cdrom'/>
  </os>
  <features>
    <acpi/>
    <apic/>
  </features>
  <cpu mode='custom' match='exact' check='partial'>
    <model fallback='allow'>Westmere</model>
  </cpu>
  <clock offset='utc'>
    <timer name='rtc' tickpolicy='catchup'/>
    <timer name='pit' tickpolicy='delay'/>
    <timer name='hpet' present='no'/>
  </clock>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <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/default.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='/data/isos/CentOS-7-x86_64-Minimal-1908.iso'/>
      <target dev='hda' bus='ide'/>
      <readonly/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <controller type='usb' index='0' model='ich9-ehci1'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x7'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci1'>
      <master startport='0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='on'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci2'>
      <master startport='2'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci3'>
      <master startport='4'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x2'/>
    </controller>
    <controller type='pci' index='0' model='pci-root'/>
    <controller type='ide' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <controller type='virtio-serial' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </controller>
    <interface type='network'>
      <source network='default'/>
      <model type='virtio'/>
      <filterref filter='clean-traffic'>
        <parameter name='IP' value='172.16.0.20'/>
      </filterref>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <target type='isa-serial' port='0'>
        <model name='isa-serial'/>
      </target>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
    <channel type='unix'>
      <target type='virtio' name='org.qemu.guest_agent.0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>
    <input type='tablet' bus='usb'>
      <address type='usb' bus='0' port='1'/>
    </input>
    <input type='mouse' bus='ps2'/>
    <input type='keyboard' bus='ps2'/>
    <graphics type='vnc' port='5910' autoport='no' listen='0.0.0.0' passwd='foobar'>
      <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>
    <memballoon model='virtio'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </memballoon>
    <rng model='virtio'>
      <backend model='random'>/dev/urandom</backend>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </rng>
  </devices>
</domain>

编辑好后:wq!保存,导入到virsh中,并启动

[root@virt qemu]# virsh define --file default.xml 
Domain default defined from default.xml

[root@virt qemu]# virsh start default 
Domain default started

使用VNC连接服务器,地址为 IP:5910,密码为foobar。

Snipaste_2020-01-08_18-05-51.png

按照提示安装系统,配置网络IP,并且开启网络自动加载。

限制NAT虚拟机可以使用的IP,以及防止MAC地址欺骗

配置文件模板中网卡配置中定义了clean-traffic过滤器,里面parameter为虚拟机可以使用的IP。

Snipaste_2020-01-08_18-44-05.png

配置NAT服务器的端口转发

这里使用了官方推荐的python脚本,利用libvirt的hook特性来实现当虚拟机开机关机时修改iptables端口规则。

[root@virt ~]# wget https://github.com/saschpe/libvirt-hook-qemu/archive/master.zip
--2020-01-08 10:46:10--  https://github.com/saschpe/libvirt-hook-qemu/archive/master.zip
Resolving github.com (github.com)... 13.229.188.59
Connecting to github.com (github.com)|13.229.188.59|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/saschpe/libvirt-hook-qemu/zip/master [following]
--2020-01-08 10:46:11--  https://codeload.github.com/saschpe/libvirt-hook-qemu/zip/master
Resolving codeload.github.com (codeload.github.com)... 13.250.162.133
Connecting to codeload.github.com (codeload.github.com)|13.250.162.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘master.zip’

    [ <=>                                                                                           ] 7,674       --.-K/s   in 0.002s  

2020-01-08 10:46:11 (3.98 MB/s) - ‘master.zip’ saved [7674]

[root@virt ~]# unzip master.zip 
Archive:  master.zip
76ae3055c1a2a2b0aa9877da6b6d467a032e4350
   creating: libvirt-hook-qemu-master/
 extracting: libvirt-hook-qemu-master/.gitignore  
  inflating: libvirt-hook-qemu-master/.travis.yml  
  inflating: libvirt-hook-qemu-master/Makefile  
  inflating: libvirt-hook-qemu-master/README.rst  
  inflating: libvirt-hook-qemu-master/hooks  
  inflating: libvirt-hook-qemu-master/hooks.json  
  inflating: libvirt-hook-qemu-master/hooks.schema.json  
  inflating: libvirt-hook-qemu-master/test_qemu.py  
[root@virt ~]# cd libvirt-hook-qemu-master/
[root@virt libvirt-hook-qemu-master]# ls
hooks  hooks.json  hooks.schema.json  Makefile  README.rst  test_qemu.py
[root@virt libvirt-hook-qemu-master]# 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 -s /etc/libvirt/hooks/hooks /etc/libvirt/hooks/qemu
ln -s /etc/libvirt/hooks/hooks /etc/libvirt/hooks/lxc

这里安装完成之后,我们需要重启libvirt,要不然不会生效

systemctl restart libvirtd.service

编辑配置文件,修改端口

[root@virt hooks]# vim /etc/libvirt/hooks/hooks.json
{
    "default": {
        "private_ip": "172.16.0.20",
        "port_map": {
            "tcp": [
                 [1102, 22]
            ]
        }
    }
}

修改完后保存,使用virsh重启虚拟机,就可以看到转发规则已经生存。

virsh destory --domain default
virsh start --domain default
[root@virt hooks]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT-default  all  --  anywhere             virt                

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DNAT-default  all  --  anywhere             virt                

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
SNAT-default  all  --  172.16.0.20          172.16.0.20         
RETURN     all  --  172.16.0.0/24        base-address.mcast.net/24 
RETURN     all  --  172.16.0.0/24        255.255.255.255     
MASQUERADE  tcp  --  172.16.0.0/24       !172.16.0.0/24        masq ports: 1024-65535
MASQUERADE  udp  --  172.16.0.0/24       !172.16.0.0/24        masq ports: 1024-65535
MASQUERADE  all  --  172.16.0.0/24       !172.16.0.0/24       

Chain DNAT-default (2 references)
target     prot opt source               destination         
DNAT       tcp  --  anywhere             virt                 tcp dpt:adobeserver-1 to:172.16.0.20:22

Chain SNAT-default (1 references)
target     prot opt source               destination         
MASQUERADE  tcp  --  172.16.0.20          172.16.0.20          tcp dpt:adobeserver-1

可以看到规则已经生效(最下面一条)

我们现在连接服务器IP的1102端口,就可以进入虚拟机的SSH。

Snipaste_2020-01-08_18-58-18.png

至此,配置完成。

写在结尾

本文讲述了Centos7下面kvm虚拟机的安装,创建,以及一些常用的功能,展示了一个最简单的案例,由于编写比较仓促,不及之处可以群里私聊群主我。