KVM简介
代码语言:javascript复制KVM(名称来自英语:Kernel-basedVirtual Machine的缩写,即基于内核的虚拟机),是一种用于Linux内核中的虚拟化基础设施,可以将Linux内核转化为一个hypervisor。KVM在2007年2月被导入Linux 2.6.20核心中,以可加载核心模块的方式被移植到FreeBSD及illumos上。 KVM在具备Intel VT或AMD-V功能的x86平台上运行。它也被移植到S/390,PowerPC与IA-64平台上。在Linux内核3.9版中,加入ARM架构的支持。
/*
1).KVM是开源软件,全称是kernel-based virtual machine(基于内核的虚拟机)。
2).是x86架构且硬件支持虚拟化技术(如 intel VT 或 AMD-V)的Linux全虚拟化解决方案。
3).它包含一个为处理器提供底层虚拟化 可加载的核心模块kvm.ko(kvm-intel.ko或kvm-AMD.ko)。
4).KVM还需要一个经过修改的QEMU软件(qemu-kvm),作为虚拟机上层控制和界面。
5).KVM能在不改变linux或windows镜像的情况下同时运行多个虚拟机,(它的意思是多个虚拟机使用同一镜像)并为每一个虚拟机配置个性化硬件环境(网卡、磁盘、图形适配器……)。
6).在主流的Linux内核,如2.6.20以上的内核均已包含了KVM核心。
*/
特点
1).要求cpu 必须支持虚拟化。 2).性能:作为服务器很好,可是图形能力十分的差。即使放电影,图像也是像刷油漆一样,一层一层的。 3).cpu使用率控制很好。 4).控制上比较简洁,功能比较丰富:比如使用“无敌功能”所有更改指向内存,你的镜像永远保持干净。“母镜像”功能让你拥有n个独立快照点。还有很多参数。另外,kvm作为内核级的虚拟机,刚开始发展关注的公司比较多——但是还没有达到商业应用的水平。
KVM内存管理
KVM继承了Linux系统管理内存的诸多特性,比如,分配给虚拟使用的内存可以被交换至交换空间、能够使用大内存页以实现更好的性能,以及对NUMA的支持能够让虚拟机高效访问更大的内存空间等。 KVM基于Intel的EPT(ExtendedPage Table)或AMD的RVI(Rapid Virtualization Indexing)技术可以支持更新的内存虚拟功能,这可以降低CPU的占用率,并提供较好的吞吐量。 此外,KVM还借助于KSM(Kernel Same-pageMerging)这个内核特性实现了内存页面共享。KSM通过扫描每个虚拟机的内存查找各虚拟机间相同的内存页,并将这些内存页合并为一个被各相关虚拟机共享的单独页面。在某虚拟机试图修改此页面中的数据时,KSM会重新为其提供一个新的页面副本。实践中,运行于同一台物理主机上的具有相同GuestOS的虚拟机之间出现相同内存页面的概率是很高的,比如共享库、内核或其它内存对象等都有可能表现为相同的内存页,因此,KSM技术可以降低内存占用进而提高整体性能。
部署KVM
检测是否支持KVM
代码语言:javascript复制KVM 是基于 x86 虚拟化扩展(Intel VT 或者 AMD-V) 技术的虚拟机软件,所以查看 CPU 是否支持 VT 技术,就可以判断是否支持KVM。有返回结果,如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的。
[root@kvm-47 ~]# cat /proc/cpuinfo | egrep 'vmx|svm' |wc -l
4
安装KVM基础环境
kvm相关安装包及其作用:
/*
qemukvm 主要的KVM程序包
pythonvirtinst 创建虚拟机所需要的命令行工具和程序库
virtmanager GUI虚拟机管理工具
virttop 虚拟机统计命令
virtviewer GUI连接程序,连接到已配置好的虚拟机
libvirt C语言工具包,提供libvirt服务
libvirtclient 为虚拟客户机提供的C语言工具包
virtinstall 基于libvirt服务的虚拟机创建命令
bridgeutils 创建和管理桥接设备的工具
*/
安装 kvm
yum -y install qemu-kvm python-virtinst libvirt libvirt-python virt-manager libguestfs-tools bridge-utils virt-install
# 重启宿主机,以便加载 kvm 模块
reboot
# 查看KVM模块是否被正确加载
[root@kvm-47 ~]# lsmod | grep kvm
kvm_intel 170181 4
kvm 554609 1 kvm_intel
irqbypass 13503 3 kvm
启动kvm服务
启动设置其开机自动启动
systemctl start libvirtd && systemctl enable libvirtd
查看状态操作结果,如
Active: active (running),说明运行情况良好
[root@kvm-47 ~]# systemctl status libvirtd
● libvirtd.service - Virtualization daemon
Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2020-11-04 10:41:23 CST; 2h 50min ago
Docs: man:libvirtd(8)
https://libvirt.org
Main PID: 947 (libvirtd)
Tasks: 20 (limit: 32768)
CGroup: /system.slice/libvirtd.service
├─ 947 /usr/sbin/libvirtd
├─1082 /usr/sbin/dnsmasq --conf-file=/var/lib/libv...
└─1083 /usr/sbin/dnsmasq --conf-file=/var/lib/libv...
Nov 04 12:36:40 kvm-47 libvirtd[947]: 2020-11-04 04:36:40.956...
Nov 04 12:40:29 kvm-47 libvirtd[947]: 2020-11-04 04:40:29.654...
Nov 04 12:48:44 kvm-47 dnsmasq-dhcp[1082]: DHCPREQUEST(virbr0...
Nov 04 12:48:44 kvm-47 dnsmasq-dhcp[1082]: DHCPACK(virbr0) 19...
Nov 04 12:52:46 kvm-47 dnsmasq-dhcp[1082]: DHCPREQUEST(virbr0...
Nov 04 12:52:46 kvm-47 dnsmasq-dhcp[1082]: DHCPACK(virbr0) 19...
Nov 04 12:59:56 kvm-47 dnsmasq-dhcp[1082]: DHCPREQUEST(virbr0...
Nov 04 12:59:56 kvm-47 dnsmasq-dhcp[1082]: DHCPACK(virbr0) 19...
Nov 04 13:24:39 kvm-47 dnsmasq-dhcp[1082]: DHCPREQUEST(virbr0...
Nov 04 13:24:39 kvm-47 dnsmasq-dhcp[1082]: DHCPACK(virbr0) 19...
Hint: Some lines were ellipsized, use -l to show in full.
[root@kvm-47 ~]# systemctl is-enabled libvirtd
enabled
安装虚拟机
安装前要设置环境语言为英文
LANG="en_US.UTF-8"
,如果是中文的话某些版本可能会报错。CentOS 7
在这里修改/etc/locale.conf
。 kvm创建虚拟机,特别注意.iso
镜像文件一定放到/home
,/tmp
或者根目录重新创建目录,不然会因为权限报错,无法创建虚拟机。
下载镜像
代码语言:javascript复制wget http://mirrors.aliyun.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2003.iso
mv CentOS-7-x86_64-Minimal-2003.iso /tmp/
安装虚拟机
代码语言:javascript复制mkdir /var/kvm/images/ -p
virt-install
--name test1
--ram 2096
--disk path=/var/kvm/images/test.img,size=8
--vcpus 1
--os-type linux
--os-variant rhel7
--network bridge=virbr0
--graphics none
--console pty,target_type=serial
--location /tmp/CentOS-7-x86_64-Minimal-2003.iso
--extra-args 'console=ttyS0,115200n8 serial'
virt-install
--name test2
--ram 2096
--disk path=/var/kvm/images/test2.img,size=8
--vcpus 1
--os-type linux
--os-variant rhel7
--network bridge=virbr0
--graphics none
--console pty,target_type=serial
--location /tmp/CentOS-7-x86_64-Minimal-2003.iso
--extra-args 'console=ttyS0,115200n8 serial'
参数介绍
命令行配置系统
上面创建虚拟机命令最终需要你配置系统基础设置,带
[!]
基本都是要配置的,按照顺序往下配置,按对用的数字以此进行设置。
命令行操作界面
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]:
1.Time settings设置时区
Installation Destination 安装磁盘
按b进入安装, 等待几分钟安装完成即可
连接虚拟机
通过 virsh console <虚拟机名称>
命令来连接虚拟机
# 查看虚拟机
virsh list # 查看在运行的虚拟机
virsh list --all # 查看所有虚拟机
Id Name State
----------------------------------------------------
7 centos72 running
连接虚拟机
virsh console centos72
退出虚拟机
`exit 退出系统到登录界面`
`快捷键: ctrl ]`
`ctrl 5` `从虚拟机登录页面,退出到宿主机命令行页面`
`control ]`
配置网络
配置虚拟机网络
代码语言:javascript复制[root@kvm-47 ~]# virsh console test2
Connected to domain test2
Escape character is ^]
CentOS Linux 7 (Core)
Kernel 3.10.0-1127.el7.x86_64 on an x86_64
localhost login: root
Password:
Last login: Wed Nov 4 14:20:45 on ttyS0
[root@localhost ~]# dhclient eth0
[root@localhost ~]# 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:40:16:b0 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.59/24 brd 192.168.122.255 scope global dynamic eth0
valid_lft 3522sec preferred_lft 3522sec
[root@localhost ~]# yum install -y net-tools
[root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
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=55bac306-da97-49f8-9838-450002d702dc
DEVICE=eth0
// 此处修改为yes
ONBOOT=yes
[root@localhost ~]# systemctl restart network
代码语言:javascript复制DNS配置,也可以放到
ifcfg-eth0
中,DNS不是随便设置的,你可以通过host、dig、nslookup命令查询DNS,如果这些工具不存在可以通过yum install bind-utils -y
来安装一下。
# 如果没有在网络配置添加DNS可以这种方式添加DNS
echo "nameserver 192.168.188.1" > /etc/resolv.conf
虚拟机其它管理
代码语言:javascript复制virsh start centos72 # 虚拟机开启(启动):
virsh reboot centos72 # 虚拟机重新启动
virsh shutdown centos72 # 虚拟机关机
virsh destroy centos72 # 强制关机(强制断电)
virsh suspend centos72 # 暂停(挂起)KVM 虚拟机
virsh resume centos72 # 恢复被挂起的 KVM 虚拟机
virsh undefine centos72 # 该方法只删除配置文件,磁盘文件未删除
virsh autostart centos72 # 随物理机启动而启动(开机启动)
virsh autostart --disable centos72 # 取消标记为自动开始(取消开机启动)
配置物理机网络
目前我只有一个固定IP,通过配置eno2
,网桥当做路由器,虚拟机共享物理机进出网络。物理机网络配置,网络进出走eno2
编辑vi /etc/sysconfig/network-scripts/ifcfg-eno2
TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eno2
UUID=f66c303e-994a-43cf-bd91-bb897dc2088d
DEVICE=eno2
ONBOOT=yes
IPADDR=<这里固定IP配置的地方> # 设置IP地址
PREFIX=24 # 设置子网掩码
GATEWAY=<这里设置网关> # 设置网关
DNS1=<这里设置DNS> # DNS
ifcfg-br0
桥接网卡配置在同一个目录中。
TYPE=Bridge
BOOTPROTO=static
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=192.168.120.1
PREFIX=24
ifcfg-eno1
物理网卡指定桥接网卡BRIDGE="br0"
TYPE=Ethernet
BOOTPROTO=none
NAME=eno1
DEVICE=eno1
ONBOOT=yes
BRIDGE="br0"
配置路由转发vi /etc/sysctl.conf
# Controls IP packet forwarding
net.ipv4.ip_forward = 0
# 修改为
# Controls IP packet forwarding
net.ipv4.ip_forward = 1 # 允许内置路由
# 再执行 `sysctl -p` 使其生效
端口转发
代码语言:javascript复制现在我们还以上述VM为例,目前该KVM的公网IP为
211.11.61.7
,VM的IP为192.168.188.115
,现在我要求通过访问KVM的2222端口访问VM的22端口。 编辑vi /etc/rc.d/rc.local
添加下面命令,达到开机重启配置网络转发规则。
# 启动网络转发规则
iptables -t nat -A : -s 192.168.188.0/24 -j SNAT --to-source 211.11.61.7
iptables -t nat -A POSTROUTING -s 192.168.188.0/24 -j SNAT --to-source 211.11.61.7
iptables -t nat -A PREROUTING -d 211.11.61.7 -p tcp --dport 2222 -j DNAT --to-dest 192.168.188.115:22
iptables -t nat -A PREROUTING -d 211.11.61.7 -p tcp --dport 2221 -j DNAT --to-dest 192.168.188.115:21
# 实际效果可以通过外网连接虚拟机
ssh -p 2222 root@211.11.61.7
代码语言:javascript复制通过iptables命令来设置转发规则,源SNAT规则,源网络地址转换,SNAT就是重写包的源IP地址。
# 数据包进行 源NAT(SNAT),系统先路由——>再过滤(FORWARD)——>最后才进行POSTROUTING SNAT地址翻译
# -t<表>:指定要操纵的表;
# -A:向规则链中添加条目;
# -s:指定要匹配的数据包源ip地址;
# -j<目标>:指定要跳转的目标;
# -j SNAT:源网络地址转换,SNAT就是重写包的源IP地址
# --to-source ipaddr[-ipaddr][:port-port]
# 它可以指定单个新的源IP地址,IP地址的包含范围,以及可选的端口范围(仅当规则还指定-p tcp或-p udp时才有效)。
# 如果没有指定端口范围,则低于512的源端口将映射到512以下的其他端口:512和1023之间的端口将映射到低于1024的端口,
# 其他端口将被映射到1024或更高。 在可能的情况下,不会发生港口更改。
# 在内核高达2.6.10,您可以添加几个 - 源选项。
# 对于这些内核,如果通过地址范围或多个源选项指定多个源地址,则会在这些地址之间进行简单的循环(循环中循环)。
# 后来的内核(> = 2.6.11-rc1)不再具有NAT到多个范围的能力。
iptables -t nat -A POSTROUTING -s 192.168.120.0/24 -j SNAT --to-source <固定IP>
# cat /etc/sysconfig/iptables
公网访问虚拟机
通过公网ip 192.168.188.222
端口2280
,转发到虚拟机192.168.111.133:80
上面
iptables -t nat -A PREROUTING -d 192.168.188.222 -p tcp --dport 2280 -j DNAT --to-dest 192.168.111.133:80
重启并保存 iptables
配置。
# 保存
service iptables save
# 重启
service iptables restart
配置宿主机网络
- KVM 虚拟机是基于 NAT 的网络配置;
- 只有同一宿主机的虚拟键之间可以互相访问,跨宿主机是不能访问;
- 虚拟机需要和宿主机配置成桥接模式,以便虚拟机可以在局域网内可见;
Bridge模式配置
代码语言:javascript复制Bridge方式即虚拟网桥的网络连接方式,是客户机和子网里面的机器能够互相通信。可以使虚拟机成为网络中具有独立IP的主机。桥接网络(也叫 物理设备共享)被用作把一个物理设备复制到一台虚拟机。网桥多用作高级设置,特别是主机多个网络接口的情况。
┌─────────────────────────┐ ┌─────────────────┐
│ HOST │ │Virtual Machine 1│
│ ┌──────┐ ┌───────┐ │ │ ┌──────┐ │
│ │ br0 │──┬───│ vnet0 │─│─ ─ ─ │ │ br0 │ │
│ └──────┘ │ └───────┘ │ │ └──────┘ │
│ │ │ │ └─────────────────┘
│ │ │ ┌───────┐ │ ┌─────────────────┐
│ ┌──────┐ └───│ vnet1 │─│─ │Virtual Machine 2│
│ │ eno0 │ └───────┘ │ │ │ ┌──────┐ │
│ └──────┘ │ ─ ─ │ │ br0 │ │
│ ┌──────┐ │ │ └──────┘ │
│ │ eno1 │ │ └─────────────────┘
│ └──────┘ │
└─────────────────────────┘
代码语言:javascript复制通过ip命令查看宿主机配置文件的名字
ip addr
6: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 38:63:bb:44:cf:6c brd ff:ff:ff:ff:ff:ff
inet 192.168.188.132/24 brd 192.168.188.255 scope global dynamic eno1
valid_lft 2822sec preferred_lft 2822sec
inet6 fe80::3a63:bbff:fe44:cf6c/64 scope link
valid_lft forever preferred_lft forever
代码语言:javascript复制可以看到上面
eno1
是有获取到ip地址的,相对应的文件在/etc/sysconfig/network-scripts/
目录中,ifcfg-eno1
宿主机的物理网卡配置文件
# cat ifcfg-eno1
TYPE=Ethernet
BOOTPROTO=static
NAME=eno1
DEVICE=eno1
UUID=242b3d4d-37a5-4f46-b072-55554c185ecf
ONBOOT=yes
BRIDGE="br0" # 指定桥接网卡的名称
ifcfg-br0
桥接网卡配置在同一个目录中。
# cat ifcfg-br0
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=br0
UUID=242b3d4d-37a5-4f46-b072-55554c185ecf
DEVICE=br0
ONBOOT=yes
TYPE=bridge # 将制定为桥接类型
IPADDR=192.168.188.133 # 设置IP地址
PREFIX=24 # 设置子网掩码
GATEWAY=192.168.188.1 # 设置网关
配置好之后,通过systemctl 命令重启网卡。
代码语言:javascript复制ifup eno1 # 激活网卡
ifup br0 # 激活桥接网卡
# 两种重启网络的方法
systemctl restart network.service
service network restart
# 校验桥接接口
brctl show
bridge name bridge id STP enabled interfaces
br0 8000.3863bb44cf6c no eno1
vnet0
virbr0 8000.525400193f0f yes virbr0-nic
NAT模式
NAT(Network Address Translation网络地址翻译),NAT方式是kvm安装后的默认方式。它支持主机与虚拟机的互访,同时也支持虚拟机访问互联网,但不支持外界访问虚拟机。
代码语言:javascript复制virsh net-edit default # 如果要创建或者修改NAT网络,要先编辑default.xml:
virsh net-list --all
Name State Autostart Persistent
----------------------------------------------------------
default active no no
default是宿主机安装虚拟机支持模块的时候自动安装的。
代码语言:javascript复制ip a l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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: ens1f0: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 2c:44:fd:8c:43:44 brd ff:ff:ff:ff:ff:ff
3: ens1f1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 2c:44:fd:8c:43:45 brd ff:ff:ff:ff:ff:ff
4: ens1f2: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 2c:44:fd:8c:43:46 brd ff:ff:ff:ff:ff:ff
5: ens1f3: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 2c:44:fd:8c:43:47 brd ff:ff:ff:ff:ff:ff
6: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP qlen 1000
link/ether 38:63:bb:44:cf:6c brd ff:ff:ff:ff:ff:ff
7: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 38:63:bb:44:cf:6d brd ff:ff:ff:ff:ff:ff
8: eno3: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 38:63:bb:44:cf:6e brd ff:ff:ff:ff:ff:ff
9: eno4: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 38:63:bb:44:cf:6f brd ff:ff:ff:ff:ff:ff
10: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 52:54:00:19:3f:0f brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
11: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 500
link/ether 52:54:00:19:3f:0f brd ff:ff:ff:ff:ff:ff
12: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 38:63:bb:44:cf:6c brd ff:ff:ff:ff:ff:ff
inet 192.168.188.132/24 brd 192.168.188.255 scope global dynamic br0
valid_lft 3397sec preferred_lft 3397sec
inet 192.168.188.133/24 brd 192.168.188.255 scope global secondary br0
valid_lft forever preferred_lft forever
inet6 fe80::3a63:bbff:fe44:cf6c/64 scope link
valid_lft forever preferred_lft forever
19: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 500
link/ether fe:54:00:72:12:a8 brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fe72:12a8/64 scope link
valid_lft forever preferred_lft forever
代码语言:javascript复制其中virbr0是由宿主机虚拟机支持模块安装时产生的虚拟网络接口,也是一个switch和bridge,负责把内容分发到各虚拟机。几个虚拟机管理模块产生的接口关系如下图:
┌───────────────────────┐
│ HOST │
│ ┌──────┐ │ ┌─────────────────┐
│ │ br0 │─┬──────┐ │ │Virtual Machine 1│
│ └──────┘ │ │ │ │ ┌──────┐ │
│ │ │ ┌───────┐ │ ─ │ │ br0 │ │
│ │ │ │ vnet0 │─│┘ │ └──────┘ │
│ ┌──────┐ │ └───────┘ │ └─────────────────┘
│ │virbr0│ │ ┌───────┐ │ ┌─────────────────┐
│ │ -nic │ └──│ vnet1 │─│┐ │Virtual Machine 2│
│ └──────┘ └───────┘ │ │ │
│ ┌──────┐ │└ ─│ ┌──────┐ │
│ │ eno0 │ │ │ │ br0 │ │
│ └──────┘ │ │ └──────┘ │
│ ┌──────┐ │ └─────────────────┘
│ │ eno1 │ │
│ └──────┘ │
└───────────────────────┘
代码语言:javascript复制从图上可以看出,虚拟接口和物理接口之间没有连接关系,所以虚拟机只能在通过虚拟的网络访问外部世界,无法从网络上定位和访问虚拟主机。virbr0是一个桥接器,接收所有到网络192.168.122.*的内容。从下面命令可以验证:
brctl show
# 输出结果
# ---------------------
# bridge name bridge id STP enabled interfaces
# br0 8000.3863bb44cf6c no eno1
# vnet0
# virbr0 8000.525400193f0f yes virbr0-nic
ip route
# default via 192.168.188.1 dev br0
# 169.254.0.0/16 dev br0 scope link metric 1012
# 192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
# 192.168.188.0/24 dev br0 proto kernel scope link src 192.168.188.132
代码语言:javascript复制同时,虚拟机支持模块会修改iptables规则,通过命令可以查看:
iptables -t nat -L -nv
iptables -t filter -L -nv
代码语言:javascript复制如果没有default的话,或者需要扩展自己的虚拟网络,可以使用命令重新安装NAT。
virsh net-define /usr/share/libvirt/networks/default.xml
代码语言:javascript复制此命令定义一个虚拟网络,default.xml的内容:
<network>
<name>default</name>
<bridge name="virbr0" />
<forward/>
<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>
代码语言:javascript复制也可以修改xml,创建自己的虚拟网络。 重新加载和激活配置:
virsh net-define /etc/libvirt/qemu/networks/default.xml
代码语言:javascript复制标记为自动启动:
virsh net-autostart default
# Network default marked as autostarted
virsh net-start default
启动网络
virsh net-start default
# Network default started
网络启动后可以用命令brctl show 查看和验证。
修改vi /etc/sysctl.conf
中参数,允许ip转发,CentOS7是在vi /usr/lib/sysctl.d/00-system.conf
这里面修改
net.ipv4.ip_forward=1
通过 sysctl -p
查看修改结果
自定义NAT网络
创建名为management
的NAT网络,vi /usr/share/libvirt/networks/management.xml
<network>
<name>management</name>
<bridge name="virbr1"/>
<forward/>
<ip address="192.168.123.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.123.2" end="192.168.123.254"/>
</dhcp>
</ip>
</network>
启用新建的NAT网络
代码语言:javascript复制virsh net-define /usr/share/libvirt/networks/management.xml
virsh net-start management
virsh net-autostart management
验证
代码语言:javascript复制brctl show
# bridge name bridge id STP enabled interfaces
# br0 8000.3863bb44cf6c no eno1
# vnet0
# virbr0 8000.525400193f0f yes virbr0-nic
# virbr1 8000.52540027f0ba yes virbr1-nic
virsh net-list --all
# Name State Autostart Persistent
# ----------------------------------------------------------
# default active no no
# management active yes yes
修改虚拟机配置信息
直接通过vim命令修改
代码语言:javascript复制vim /etc/libvirt/qemu/centos72.xml
通过virsh命令修改
代码语言:javascript复制virsh edit centos72
克隆虚拟机
代码语言:javascript复制# 暂停原始虚拟机
virsh shutdown centos72
virt-clone -o centos72 -n centos.112 -f /home/vms/centos.112.qcow2 -m 00:00:00:00:00:01
virt-clone -o centos88 -n centos.112 --file /home/vms/centos.112.qcow2 --nonsparse
virt-clone
参数介绍
--version
查看版本。-h,--help
查看帮助信息。--connect=URI
连接到虚拟机管理程序 libvirt 的URI。-o 原始虚拟机名称
原始虚拟机名称,必须为关闭或者暂停状态。-n 新虚拟机名称
--name 新虚拟机名称。--auto-clone
从原来的虚拟机配置自动生成克隆名称和存储路径。-u NEW_UUID, --uuid=NEW_UUID
克隆虚拟机的新的UUID,默认值是一个随机生成的UUID。-m NEW_MAC, --mac=NEW_MAC
设置一个新的mac地址,默认为随机生成 MAC。-f NEW_DISKFILE, --file=NEW_DISKFILE
为新客户机使用新的磁盘镜像文件地址。--force-copy=TARGET
强制复制设备。--nonsparse
不使用稀疏文件复制磁盘映像。
通过镜像创建虚拟机
创建虚拟机镜像文件
代码语言:javascript复制# 复制第一次安装的干净系统镜像,作为基础镜像文件,
# 后面创建虚拟机使用这个基础镜像
cp /home/vms/centos.88.qcow2 /home/vms/centos7.base.qcow2
# 使用基础镜像文件,创建新的虚拟机镜像
cp /home/vms/centos7.base.qcow2 /home/vms/centos7.113.qcow2
创建虚拟机配置文件
代码语言:javascript复制# 复制第一次安装的干净系统镜像,作为基础配置文件。
virsh dumpxml centos.88 > /home/vms/centos7.base.xml
# 使用基础虚拟机镜像配置文件,创建新的虚拟机配置文件
cp /home/vms/centos7.base.xml /home/vms/centos7.113.xml
# 编辑新虚拟机配置文件
vi /home/vms/centos7.113.xml
主要是修改虚拟机文件名,UUID,镜像地址和网卡地址,其中 UUID 在 Linux 下可以使用 uuidgen
命令生成
<domain type='kvm'>
<name>centos7.113</name>
<uuid>1e86167a-33a9-4ce8-929e-58013fbf9122</uuid>
<devices>
<disk type='file' device='disk'>
<source file='/home/vms/centos7.113.img'/>
</disk>
<interface type='bridge'>
<mac address='00:00:00:00:00:04'/>
</interface>
</devices>
</domain>
代码语言:javascript复制virsh define /home/vms/centos7.113.xml
# Domain centos.113 defined from /home/vms/centos7.113.xml
动态更改cpu数量和内存大小
动态调整,如果超过给虚拟机分配的最大内存,需要重启虚拟机。
代码语言:javascript复制virsh list --all
# Id 名称 状态
# ----------------------------------------------------
# 2 working112 running
# 更改CPU
virsh setvcpus working112 --maximum 4 --config
# 更改内存
virsh setmaxmem working112 1048576 --config
# 查看信息
virsh dominfo working112
挂载磁盘
创建磁盘
代码语言:javascript复制mkdir /home/vms
查看镜像信息
代码语言:javascript复制virt-filesystems --long --parts --blkdevs -h -a working112.qcow2
# Name Type Size Parent
# /dev/sda1 partition 200M /dev/sda
# /dev/sda2 partition 9.8G /dev/sda
# /dev/sda device 10G -
qemu-img info working112.qcow2
# image: working112.qcow2
# file format: qcow2
# virtual size: 140G (150323855360 bytes)
# disk size: 33G
# cluster_size: 65536
# Format specific information:
# compat: 1.1
# lazy refcounts: true
代码语言:javascript复制给虚拟机镜像添加
200G
大小,注意需要停止working112
虚拟机
qemu-img resize working112.qcow2 200G
# Image resized.
代码语言:javascript复制首先,我们制作如下所示的磁盘的备份副本。
cp working112.qcow2 working112-orig.qcow2
代码语言:javascript复制然后我们运行下面的命令来增加
/dev/sda
virt-resize --expand /dev/sda1 working112-orig.qcow2 working112.qcow2
查看镜像信息
qemu-img info working112.qcow2
# image: working112.qcow2
# file format: qcow2
# virtual size: 140G (150323855360 bytes)
# disk size: 33G
# cluster_size: 65536
# Format specific information:
# compat: 1.1
# lazy refcounts: true
进入虚拟机
virsh console working112 查看信息
vgdisplay # 显示卷组大小
lvdisplay # 显示逻辑卷大小
卷组大小已增加,下面需要分配容量给逻辑卷
lvextend -L 60G /dev/centos/root
还有最后一步,分配好了需要做系统调整
# ext 系统格式使用:
resize2fs /dev/centos/root
# xfs 系统格式使用下面命令
xfs_growfs /dev/centos/root
常用命令说明
virt-install
常用参数说明
代码语言:javascript复制–name指定虚拟机名称
–memory分配内存大小。
–vcpus分配CPU核心数,最大与实体机CPU核心数相同
–disk指定虚拟机镜像,size指定分配大小单位为G。
–network网络类型,此处用的是默认,一般用的应该是bridge桥接。
–accelerate加速
–cdrom指定安装镜像iso
–vnc启用VNC远程管理,一般安装系统都要启用。
–vncport指定VNC监控端口,默认端口为5900,端口不能重复。
–vnclisten指定VNC绑定IP,默认绑定127.0.0.1,这里改为0.0.0.0。
–os-type=linux,windows
–os-variant=rhel6
--name 指定虚拟机名称
--ram 虚拟机内存大小,以 MB 为单位
--vcpus 分配CPU核心数,最大与实体机CPU核心数相同
–-vnc 启用VNC远程管理,一般安装系统都要启用。
–-vncport 指定VNC监控端口,默认端口为5900,端口不能重复。
–-vnclisten 指定VNC绑定IP,默认绑定127.0.0.1,这里改为0.0.0.0。
--network 虚拟机网络配置
# 其中子选项,bridge=br0 指定桥接网卡的名称。
–os-type=linux,windows
–os-variant=rhel7.2
--disk 指定虚拟机的磁盘存储位置
# size,初始磁盘大小,以 GB 为单位。
--location 指定安装介质路径,如光盘镜像的文件路径。
--graphics 图形化显示配置
# 全新安装虚拟机过程中可能会有很多交互操作,比如设置语言,初始化 root 密码等等。
# graphics 选项的作用就是配置图形化的交互方式,可以使用 vnc(一种远程桌面软件)进行链接。
# 我们这列使用命令行的方式安装,所以这里要设置为 none,但要通过 --extra-args 选项指定终端信息,
# 这样才能将安装过程中的交互信息输出到当前控制台。
--extra-args 根据不同的安装方式设置不同的额外选项
virsh
代码语言:javascript复制virsh list --all # 查看所有运行和没有运行的虚拟机
virsh list # 查看在运行的虚拟机
virsh dumpxml vm-name # 查看kvm虚拟机配置文件
virsh start vm-name # 启动kvm虚拟机
virsh shutdown vm-name # 正常关机
virsh destroy vm-name # 非正常关机,强制关闭虚拟机(相当于物理机直接拔掉电源)
virsh undefine vm-name # 删除vm的配置文件
ls /etc/libvirt/qemu
# 查看删除结果,Centos-6.6的配置文件被删除,但磁盘文件不会被删除
virsh define file-name.xml # 根据配置文件定义虚拟机
virsh suspend vm-name # 挂起,终止
virsh resumed vm-name # 恢复被挂起的虚拟机
virsh autostart vm-name # 开机自启动vm
virsh console <虚拟机名称> # 连接虚拟机
错误解决
代码语言:javascript复制console test
Connected to domain test
Escape character is ^]
如果出现上面字符串使用 CTRL Shift 5 CTRL Shift ]
- ERROR Format cannot be specified for unmanaged storage. virt-manager 没有找到存储池,创建储存池即可
- KVM VNC客户端连接闪退 使用real vnc或者其它vnc客户端连接kvm闪退,把客户端设置中的ColourLevel值设置为rgb222或full即可
- virsh shutdown 无法关闭虚拟机 使用该命令关闭虚拟机时,KVM是向虚拟机发送一个ACPI的指令,需要虚拟机安装acpid服务:
- operation failed: Active console session exists for this domain
# 方案1
$ ps aux | grep console
$ kill -9 <进程号>
# 方案2
$ /etc/init.d/libvirt-bin restart
# 方案3
$ ps aux | grep kvm
$ kill 对应的虚拟机进程