KVM虚拟机的搭建过程

1. KVM安装

1.1 配置确认

首先需要确认服务器的硬件是否支持虚拟化,执行如下命令确认

root@DbackupServer:~# egrep -c '(svm|vmx)' /proc/cpuinfo
4
root@DbackupServer:~# 

如果输出结果大于0,意味着服务器硬件是支持虚拟化的。否则,重启进入BIOS设置中启用VT技术。
执行如下命令安装kvm-ok程序,来确定服务器是否能够运行硬件加速的KVM虚拟机

root@Backup-standby:~# apt install cpu-checker

root@Backup-standby:~# kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used

1.2 安装KVM

安装KVM及依赖项

#执行以下命令安装KVM
sudo apt update
#ubuntu 18
sudo apt install qemu qemu-kvm libvirt-bin  bridge-utils  virt-manager -y

#ubuntu 20
apt install qemu qemu-kvm bridge-utils virt-manager libvirt-daemon-system libvirt-clients virtinst libguestfs-tools cpu-checker -y

启动libvirtd服务,并设置开机自动启动

#将libvirtd添加自启动
sudo systemctl start libvirtd.service
sudo systemctl enable libvirtd.service

执行service libvirtd status
查看libvirtd服务状态,如图

root@DbackupServer:/tmp# service libvirtd status
● libvirtd.service - Virtualization daemon
   Loaded: loaded (/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2021-12-10 17:16:00 CST; 10min ago
     Docs: man:libvirtd(8)
           https://libvirt.org
 Main PID: 3699 (libvirtd)
    Tasks: 19 (limit: 32768)
   CGroup: /system.slice/libvirtd.service
           ├─3699 /usr/sbin/libvirtd
           ├─4479 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/lib/libvirt/libvirt_leaseshelper
           └─4480 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/lib/libvirt/libvirt_leaseshelper

Dec 10 17:16:02 DbackupServer dnsmasq[4479]: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth nettlehash DNSSEC loop-detect inotify
Dec 10 17:16:02 DbackupServer dnsmasq-dhcp[4479]: DHCP, IP range 192.168.122.2 -- 192.168.122.254, lease time 1h
Dec 10 17:16:02 DbackupServer dnsmasq-dhcp[4479]: DHCP, sockets bound exclusively to interface virbr0
Dec 10 17:16:02 DbackupServer dnsmasq[4479]: reading /etc/resolv.conf
Dec 10 17:16:02 DbackupServer dnsmasq[4479]: using nameserver 127.0.0.53#53
Dec 10 17:16:02 DbackupServer dnsmasq[4479]: read /etc/hosts - 5 addresses
Dec 10 17:16:02 DbackupServer dnsmasq[4479]: read /var/lib/libvirt/dnsmasq/default.addnhosts - 0 addresses
Dec 10 17:16:02 DbackupServer dnsmasq-dhcp[4479]: read /var/lib/libvirt/dnsmasq/default.hostsfile
Dec 10 17:16:02 DbackupServer dnsmasq[4479]: reading /etc/resolv.conf
Dec 10 17:16:02 DbackupServer dnsmasq[4479]: using nameserver 127.0.0.53#53

1.3 桥接网络配置

一般虚拟机网络配置有Bridge、NAT等几种模式。NAT模式下,虚拟机不需要配置自己的IP,通过宿主机来访问外部网络;Bridge模式下, 虚拟机需要配置自己的IP,然后虚拟出一个网卡, 与宿主机的网卡一起挂到一个虚拟网桥上(类似于交换机)来访问外部网络,这种模式下,虚拟机拥有独立的IP,局域网其它主机能直接通过IP与其通信。简单理解,就是NAT模式下,虚机隐藏在宿主机后面了,虚机能通过宿主机访问外网,但局域网其它主机访问不到它,Bridge模式下,虚机跟宿主机一样平等地存在,局域网其它主机可直接通过IP与其通信。一般我们创建虚机是用来部署服务供使用的, 所以都是用Bridge模式。

ubuntu 18中,网络配置通过netplan来实现了,如下,更改配置文件 etc/netplan/01-onenet-cfg.yaml

# This file describes the network interfaces available on your system
# For more information, see netplan(5).

network:
  version: 2
  renderer: networkd
  ethernets:

    ens160:
      dhcp4: no
      dhcp6: no
      #addresses: [ 10.1.1.241/24 ]
      #gateway4: 10.1.1.1
      
  bridges:
    br0:
      dhcp4: no
      dhcp6: no
      addresses: [ 10.1.1.241/24 ]
      gateway4: 10.1.1.1
      interfaces: [ ens160 ]

将宿主机原有网卡ens160挂到网桥br0上,并指定IP地址为10.1.1.241,nameservers指定DNS服务器。修改完后,通过sudo netplan apply
重启网络服务生效,然后通过ifconfig
查看,

root@DbackupServer:/tmp# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.1.1.241  netmask 255.255.255.0  broadcast 10.1.1.255
        inet6 fe80::44b8:3dff:fead:79ec  prefixlen 64  scopeid 0x20<link>
        ether 46:b8:3d:ad:79:ec  txqueuelen 1000  (Ethernet)
        RX packets 1126973  bytes 4645823602 (4.6 GB)
        RX errors 0  dropped 1  overruns 0  frame 0
        TX packets 969044  bytes 65818318 (65.8 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 00:0c:29:06:ae:a4  txqueuelen 1000  (Ethernet)
        RX packets 10802871  bytes 15328761510 (15.3 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 969044  bytes 65818318 (65.8 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

原来挂在enp7s0网卡下的IP现在挂到了br0上,宿主机及所有其它虚拟机都通过该网桥来与外部通讯。我们也可以通过brctl show
来直观地查看,

root@DbackupServer:/tmp# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.46b83dad79ec       no              ens160
virbr0          8000.525400e8cece       yes             virbr0-nic

目前因为还没虚机,所以只有宿主机的网卡enp7s0挂在网桥br0上。同时也可以看到docker容器也是通过网桥docker0来通讯的。

2. 虚拟机安装

2.1 安装虚拟机

安装命令

sudo virt-install\
 --name=CentOS-7\    #指定虚机名称
 --memory=4096,maxmemory=4096\        #内存大小,单位Mb
 --vcpus=2,maxvcpus=4\    #分配CPU
 --os-type=linux\    #虚机类型
 --os-variant=centos7.0\    #os版本,可通过osinfo-query os命令查询
 --location=/home/CentOS-7-x86_64-DVD-1810.iso\        #镜像位置
 --disk path=/infokist/centos7/CentOS-7.img,bus=virtio,size=50\        #虚机磁盘路径
 --bridge=br0\    
 --graphics=none \
 --console=pty,target_type=serial\
 --extra-args="console=tty0 console=ttyS0,115200n8"

其中–name指定虚机名称,后面可通过virsh管理;–memory=16384,maxmemory=16384配置了16G内存;–vcpus=4,maxvcpus=4配置了4个CPU内核;centos7需要制定–os-variant=rhel7;–disk path=xx,size=300制定了磁盘路径与大小,这里是300G。

如果执行上述命令出现qemu-kvm: could not open 'xx/CentOS-7-x86_64-DVD-1810.iso': Permission denied
异常退出时,可通过修改/etc/libvirt/qemu.conf
文件将user = "root"
group = "root"
前面的注释去掉解决(https://github.com/jedi4ever/veewee/issues/996

如无问题,安装程序将出现如下配置界面

Starting installer, one moment...
anaconda 21.48.22.147-1 for CentOS 7 started.
 * installation log files are stored in /tmp during the installation
 * shell is available on TTY2
 * when reporting a bug add logs from /tmp as separate text/plain attachments
09:46:30 Not asking for VNC because we don't have a network
================================================================================
================================================================================
Installation

 1) [x] Language settings                 2) [!] Time settings
        (English (United States))                (Timezone is not set.)
 3) [!] Installation source               4) [!] Software selection
        (Processing...)                          (Processing...)
 5) [!] Installation Destination          6) [x] Kdump
        (No disks selected)                      (Kdump is enabled)
 7) [ ] Network configuration             8) [!] Root password
        (Not connected)                          (Password is not set.)
 9) [!] User creation
        (No user will be created)
  Please make your choice from above ['q' to quit | 'b' to begin installation |
  'r' to refresh]: 

可通过输入选项对应的数字来选择不同的配置,依次操作如下步骤完成时区设置:
输入2,回车,选择时区设置;输入1,回车,选择“Set timezone”;输入2,回车,选择“Asia”;回车,输入64,回车,选择“Shanghai”

 1) [x] Language settings                 2) [!] Time settings
        (English (United States))                (Timezone is not set.)
 3) [!] Installation source               4) [!] Software selection
        (Processing...)                          (Processing...)
 5) [!] Installation Destination          6) [x] Kdump
        (No disks selected)                      (Kdump is enabled)
 7) [ ] Network configuration             8) [!] Root password
        (Not connected)                          (Password is not set.)
 9) [!] User creation
        (No user will be created)
  Please make your choice from above ['q' to quit | 'b' to begin installation |
  'r' to refresh]: 2

然后进行安装设置,

依次操作如下:

 1) [x] Language settings                 2) [!] Time settings
        (English (United States))                (Timezone is not set.)
 3) [!] Installation source               4) [!] Software selection
        (Processing...)                          (Processing...)
 5) [!] Installation Destination          6) [x] Kdump
        (No disks selected)                      (Kdump is enabled)
 7) [ ] Network configuration             8) [!] Root password
        (Not connected)                          (Password is not set.)
 9) [!] User creation
        (No user will be created)
  Please make your choice from above ['q' to quit | 'b' to begin installation |
  'r' to refresh]: 5

输入5,回车,进入安装设置;输入c,回车,选择默认的磁盘进行安装;输入c,回车,使用默认的“2) Use All
Space”;输入1,回车,选择“1) Standard Partition”进行标准分区;输入c,回车,完成分区设置

最后进入root密码设置,

 1) [x] Language settings                 2) [!] Time settings
        (English (United States))                (Timezone is not set.)
 3) [!] Installation source               4) [!] Software selection
        (Processing...)                          (Processing...)
 5) [!] Installation Destination          6) [x] Kdump
        (No disks selected)                      (Kdump is enabled)
 7) [ ] Network configuration             8) [!] Root password
        (Not connected)                          (Password is not set.)
 9) [!] User creation
        (No user will be created)
  Please make your choice from above ['q' to quit | 'b' to begin installation |
  'r' to refresh]: 8

操作如下:
输入8,回车,进入root密码设置;输入密码,回车;输入确认密码,回车

 1) [x] Language settings                 2) [!] Time settings
        (English (United States))                (Timezone is not set.)
 3) [!] Installation source               4) [!] Software selection
        (Processing...)                          (Processing...)
 5) [!] Installation Destination          6) [x] Kdump
        (No disks selected)                      (Kdump is enabled)
 7) [ ] Network configuration             8) [!] Root password
        (Not connected)                          (Password is not set.)
 9) [!] User creation
        (No user will be created)
  Please make your choice from above ['q' to quit | 'b' to begin installation |
  'r' to refresh]: b

完成上述设置后,输入b开始进行安装

等待一段时间后,安装程序停在如下界面

Installing iwl6000-firmware (305/306)
Installing iwl135-firmware (306/306)
Performing post-installation setup tasks
Installing boot loader
.
Performing post-installation setup tasks
.

Configuring installed system
.
Writing network configuration
.
Creating users
.
Configuring addons
.
Generating initramfs
.
Running post-installation scripts
.
        Use of this product is subject to the license agreement found at /usr/share/centos-release/EULA

        Installation complete.  Press return to quit
[anaconda] 1:main* 2:shell  3:log  4:storage-lo> Switch tab: Alt+Tab | Help: F1 

按回车继续,最后输入用户名root,及前面设置的密码登录系统

[  OK  ] Started Command Scheduler.
         Starting Terminate Plymouth Boot Screen...
[  OK  ] Started Dump dmesg to /var/log/dmesg.
[  OK  ] Started Login Service.
[    9.644263] ip6_tables: (C) 2000-2006 Netfilter Core Team
[    9.713165] Ebtables v2.0 registered
[    9.732869] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[    9.801317] nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
[    9.906933] bridge: filtering via arp/ip/ip6tables is no longer available by default. Update your scripts to load br_netfilter if you need this.
[    9.929264] Netfilter messages via NETLINK v0.30.
[    9.936897] ip_set: protocol 6
[   14.084047] random: crng init done

CentOS Linux 7 (Core)
Kernel 3.10.0-957.el7.x86_64 on an x86_64

localhost login: 

2.2 虚拟机网络配置

虚拟机安装完后,是没有分配IP的,我们通过ip a
命令查看,

这时候的eth0下面空空如也,什么都没有。在/etc/sysconfig/network-scripts/ifcfg-eth0
文件中添加如下内容

[root@localhost ~]# vi etc/sysconfig/network-scripts/ifcfg-eth0

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=eth0
UUID=67eb190e-8e63-4ffb-9c01-ff8478d17830
DEVICE=eth0
ONBOOT=yes    #开机自启
IPADDR=10.1.1.243
PREFIX=24
GATEWAY=10.1.1.1
DNS1=10.1.1.1

并通过systemctl restart network
重启网络生效,这时候再运行ip a
查看,eth0下面已经有配置的IP了。不出意外的话,局域网其它主机就可以通过该IP来远程SSH连接了。

[root@localhost network-scripts]# ip a
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 pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:e2:49:37 brd ff:ff:ff:ff:ff:ff
    inet 10.1.1.243/24 brd 10.1.1.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::882b:ec67:751b:40a9/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

这时候我们再通过brctl show
来查看网桥挂载情况,br0下面已经多了一个vnet0虚拟网卡了。

root@DbackupServer:~# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.46b83dad79ec       no              ens160
                                                        vnet0
virbr0          8000.525400e8cece       yes             virbr0-nic                                vethfe89039

虚拟机装完后,默认的hostname是localhost,针对centos7,我们可以通过如下命令来修改hostname

[root@localhost ~]# hostnamectl set-hostname dev-server1

然后在/etc/hosts文件中添加127.0.0.1的host映射 dev-server1

[root@localhost ~]# vi etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 dev-server1
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

3. 虚拟机管理

  1. 列出当前运行的虚拟机virsh list

    root@DbackupServer:~# virsh list
     Id    Name                           State
    ----------------------------------------------------
     4     CentOS-7                       running

    如果列出所有的,则virsh list --all

  2. 从宿主机进入虚拟机virsh console,后面接虚拟机ID或名称

    root@DbackupServer:~# virsh console 4
    Connected to domain CentOS-7
    Escape character is ^]
    
    CentOS Linux 7 (Core)
    Kernel 3.10.0-957.el7.x86_64 on an x86_64
    
    localhost login: root
    Password: 
    Last login: Fri Dec 10 18:00:08 on ttyS0
    [root@localhost ~]# 

    输入用户名,密码即可登录虚拟机,按Ctrl+]
    可退出。

  3. 启动与关闭虚拟机virsh start|shutdown

    root@DbackupServer:~# virsh start CentOS-7
    Domain CentOS-7 started
    
    root@DbackupServer:~# virsh shutdown 4
    Domain 4 is being shutdown
  4. libvirtd启动时,自动启动虚拟机

    root@DbackupServer:~# virsh autostart CentOS-7
    Domain CentOS-7 marked as autostarted
  5. 挂起/恢复虚拟机

    devuser@server_01:~$ virsh suspend dev-server1    # 挂起虚拟机
    devuser@server_01:~$ virsh resume dev-server1    # 恢复挂起的虚
  6. 销毁虚拟机

    devuser@server_01:~$ virsh undefine dev-server1   # 彻底销毁虚拟机,会删除虚拟机配置文件,但不会删除虚拟磁盘
  7. 查看虚拟机网卡类型

    root@ubuntu-18:~# virsh domiflist c1
    Interface  Type       Source     Model       MAC
    -------------------------------------------------------
    vnet6      bridge     br0        virtio      52:54:00:6c:bf:9f
    vnet7      network    hostonly1  virtio      52:54:00:90:e9:8b
  8. 添加新网卡

    root@ubuntu-18:~# virsh attach-interface  c1 --type network --source hostonly2 --model virtio 
    Interface attached successfully
    
    root@ubuntu-18:~# virsh domiflist c1
    Interface  Type       Source     Model       MAC
    -------------------------------------------------------
    vnet6      bridge     br0        virtio      52:54:00:6c:bf:9f
    vnet7      network    hostonly1  virtio      52:54:00:90:e9:8b
    vnet25     network    hostonly2  virtio      52:54:00:d3:60:1b
  9. 加载配置文件

    root@ubuntu-18:~# virsh attach-interface  c1 --type network --source hostonly2 --model virtio  --config
    Interface attached successfully
    
    root@ubuntu-18:~# virsh dumpxml c1 > /etc/libvirt/qemu/c1.xml 
    root@ubuntu-18:~# virsh define  /etc/libvirt/qemu/c1.xml
    Domain c1 defined from /etc/libvirt/qemu/c1.xml
  10. 删除网卡

    virsh detach-interface c1 --type network --mac 52:54:00:d3:60:1b --config

首先进入到图形界面

常用virsh指令:

1)virsh list 列出当前虚拟机列表,不包括未启动的

2)virsh list --all 列出所有虚拟机,包括所有已经定义的虚拟机

3)virsh destroy vm-name 关闭虚拟机

4)virsh start vm-name 启动虚拟机

5)virsh edit vm-name 编辑虚拟机xml文件

6)virsh undefine vm-name 删除虚拟机

7)virsh shutdown vm-name 停止虚拟机

8)virsh reboot vm-name 重启虚拟机

9)virsh autostart vm-name 虚拟机随宿主机启动

在完成kvm虚拟机的安装之后,如果想要重装相同名字的虚拟机,是会有错误提示的,就算是删除了虚拟机的xml文件,也会弹出错误提示。如下红色所注

[root@test-R410-4disk qemu]# virt-install --name=convirt --ram=512 --vcpus=2 --cpu=core2duo --pxe --os-type=linux --disk path=/data/vm/convirt.img,size=50 --network bridge=br1,model=virtio --network bridge=br0,model=virtio --graphics vnc,password=123456,port=9903 --hvm –force

ERROR Guest name 'convirt' is already in use.

这点kvm和xen不同,xen的半虚拟化要想重装,只要把创建好的虚拟机配置文件删掉就可以了

kvm如果想要重装相同名字的虚拟机,需要先关闭虚拟机

virsh destroy vm-name 关闭虚拟机

否则会有如下报错:

error:Failed to undefine domain test

error:Requested operationis not valid: cannot undefine transient domain

在虚拟机停止的状态下执行如下命令

[root@test-R410-4disk qemu]# virsh undefine convirt
Domain convirt has been undefined

这样,虚拟机就被干掉了,同样,相应的xml配置文件也干掉了。

然后在执行virt-install安装就不会报错了。