玩转 OpenStack(二)虚拟化原理简介
上节 玩转OpenStack(一)基本概念和安装KVM 中介绍了虚拟化分为两种类型,1型虚拟化和2型虚拟化。
介绍了KVM的安装和图形管理工具virt-manager。
本节讲介绍KVM的虚拟化原理。
一、CPU虚拟化
一个KVM虚拟机在宿主机中其实是一个qemu-kvm进程,与其他Linux进程一样被调度。
可以查看上节中创建的kvm虚拟机。
# virsh list
Id Name State
----------------------------------------------------
2 kvm running
# ps -elf | grep kvm
1 S root 769 2 0 60 -20 - 0 rescue Feb11 ? 00:00:00 [kvm-irqfd-clean]
6 S libvirt+ 7145 1 0 80 0 - 156077 poll_s Feb11 ? 00:01:15 qemu-system-x86_64 -enable-kvm -name kvm -S -machine
pc-i440fx-trusty,accel=kvm,usb=off -m 100 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid d9b635c8-f92c-baa4-f013-6a8c2aeb8cab
-no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/kvm.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control
-rtc base=utc -no-shutdown -boot strict=on -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2
-drive file=/var/lib/libvirt/images/cirros-0.3.3-x86_64-disk.img,if=none,id=drive-ide0-0-0,format=qcow2
-device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 -netdev tap,fd=24,id=hostnet0
-device rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:72:6e:0d,bus=pci.0,addr=0x3 -chardev pty,id=charserial0
-device isa-serial,chardev=charserial0,id=serial0 -vnc 127.0.0.1:0 -device cirrus-vga,id=video0,bus=pci.0,addr=0x2
-device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
虚拟机中的每一个虚拟vCPU对应qemu-kvm进程中的一个线程,如下图
cpu虚拟化
在这个图中有两个虚拟机,每个虚拟机分别有2个和4个线程在两个物理CPU上调度。
当前vCPU总数量是超过了物理CPU的数量,这是CPU overcommit (超配)
二、内存虚拟化
KVM 通过内存虚拟化共享物理系统内存,动态分配给虚拟机。
如下图,两台虚拟机的情况
为了在一台机器上运行多个虚拟机,KVM需要实现 VA(虚拟内存) -> PA(物理内存) -> MA(机器内存) 之间的地址转换。虚拟机操作系统控制虚拟地址到客户内存物理地址的映射 (VA -> PA),但是虚拟机操作系统不能直接访问实际机器内存,因此KVM需要负责映射客户物理内存到实际机器内存 (PA -> MA)。
内存虚拟化的实现方式:
- 软件方式:通过软件实现内存地址的翻译,比如 Shadow page table (影子页表)技术
- 硬件实现:基于 CPU 的辅助虚拟化功能,比如 AMD 的 NPT 和 Intel 的 EPT 技术
三、存储虚拟化
KVM 的存储虚拟化通过存储池(Storage Pool)和卷(Volume)来管理的。Volume 是在 Storage Pool 中划分出来的一块空间,物理机将 Volume 分配给虚拟机,Volume在虚拟机中看到的就是一块硬盘。
存储池(Storage Pool)类型
1. 目录类型的 Storage Pool
KVM 将物理机目录 /var/lib/libvirt/images/
作为默认的 Storage Pool。在这个目录下的一个文件就是一个 Volume。
- Storage Pool 的默认设置在
/etc/libvirt/storage/default.xml
文件中,内容如下:
<pool type='dir'>
<name>default</name>
<uuid>bd7c76a4-2ec0-d7a0-dfc4-ff0cb9332ca0</uuid>
<capacity unit='bytes'>0</capacity>
<allocation unit='bytes'>0</allocation>
<available unit='bytes'>0</available>
<source>
</source>
<target>
<path>/var/lib/libvirt/images</path>
<permissions>
<mode>0711</mode>
<owner>-1</owner>
<group>-1</group>
</permissions>
</target>
</pool>
其中:
<pool type='dir'>
是 Storage Pool 的类型
<path>/var/lib/libvirt/images</path>
是目录的路径。
-
使用文件做 Volume 优点:存储方便、移植性好、可复制、可远程访问(远程文件系统,如NFS,分布式文件系统,GlusterFs)。
-
Volume 文件格式:
- raw 默认格式,移植性好,性能好,但是固定大小,不能节省磁盘空间。
- qcow2 推荐的格式,cow 表示 copy on write。能够节省磁盘空间。支持AES加密,支持zlib压缩,支持多快照等。
- vmdk 是VMWare的磁盘格式,也就是VMWare虚拟机可以直接在KVM上运行。
- qed 增强型磁盘
- vdi 是VirtualBox的磁盘格式
2. LVM 类型的 Storage Pool
a. LVM概念和安装
LVM 是逻辑盘卷管理(Logical Volume Manager)的简称。
他是磁盘管理的另一种工具,就目前基本上所有操作系统均支持,LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘分区管理的灵活性。通过LVM系统管理员可以轻松管理磁盘分区。
如:将若干个磁盘分区连接为一个整块的卷组(volume group),形成一个存储池。管理员可以在卷组上随意创建逻辑卷组(logical volumes),并进一步在逻辑卷组上创建文件系统。
-
物理卷(Physical Volume)
物理卷就是指硬盘分区或从逻辑上与磁盘分区具有同样功能的设备(如RAID),是LVM的基本存储逻辑块,但和基本的物理存储介质(如分区、磁盘等)比较,却包含有与LVM相关的管理参数。 -
卷组(Volume Group)
LVM卷组类似于非LVM系统中的物理硬盘,其由物理卷组成。可以在卷组上创建一个或多个“LVM分区”(逻辑卷),LVM卷组由一个或多个物理卷组成。 -
逻辑卷(Logical Volume)
LVM的逻辑卷类似于非LVM系统中的硬盘分区,在逻辑卷之上可以建立文件系统(比如/home或者/usr等)。
b. LVM安装和简单操作
- 安装
# apt-get install lvm2
- LVM 创建VG
# vgcreate testvg /dev/sda5
- 查看VG信息
# vgdisplay
--- Volume group ---
VG Name testvg
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 1
Act PV 1
VG Size 5.00 GiB
PE Size 4.00 MiB
Total PE 1279
Alloc PE / Size 0 / 0
Free PE / Size 1279 / 5.00 GiB
VG UUID UxCUXQ-dlev-Omp0-DhMf-epf8-aGjF-FNLLP7
- 删除VG
# vgremove testvg
c. LVM 类型的 Storage Pool
物理机上 VG 中的 LV 也可以作为虚拟磁盘分配给虚拟机使用。
不过,LV 由于没有磁盘的 MBR 引导记录,不能作为虚拟机的启动磁盘,只能作为数据盘使用。
LVM 类型的配置下,物理机上的 VG 就是一个 Storage Pool,VG 中的 LV 就是 Volume。
LV 的优点是由较好的性能;不足的地方是管理和移动性方面不如镜像文件,而且不能通过网络远程使用。
在目录/etc/libvirt/storage/
中的配置文件 如下
文件名 HostVG.xml
<pool type='logical' >
<name>HostVG</name>
<source>
<name>HostVG</name>
<format type='lvm2' />
</source>
<target>
<path>/dev/HostVg</path>
</target>
</pool>
四、网络虚拟化
网络虚拟化是虚拟化技术中最复杂的部分,本节从最基本的 Linux Bridge 和 VLan 开始介绍。
1. Linux Bridge
Linux Bridge 是 Linux 上用来做TCP/IP 二层协议交换的设备,功能可以简单的理解为一个二层交换机或者 Hub。
-
当虚拟机要连接外网时,有两个方法:
- 将物理机网卡直接分配给虚拟机。但是,物理机就没有网卡了,其他虚拟机也没有网卡了。
-
给虚拟机创建一个虚拟网卡 vnet0,通过Linux Bridge -> br0 将 eth0 和 vent0 连接。如下图:
-
配置Linux bridge br0
编辑 /etc/network/interfaces
文件。
源文件如下
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
修改如下
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
auto br0
iface br0 inet dhcp
bridge_stp off
bridge_waitport 0
bridge_fd 0
bridge_ports eth0
- 物理机原来的网卡 eth0 配置是自动获取 ip
dhcp
,创建 Linux Bridge 后, IP 必须放到 br0 上了。 - 在 br0 的配置信息中注意
bridge_ports eth0
,作用是将 eth0 挂到 br0 上。
重启后执行ifconfig
,可以看到 IP 已经在 br0 上面了。
root@openstack:~# ifconfig
br0 Link encap:Ethernet HWaddr 00:0c:29:45:5d:cb
inet addr:172.16.245.134 Bcast:172.16.245.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe45:5dcb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:96 errors:0 dropped:0 overruns:0 frame:0
TX packets:127 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:10632 (10.6 KB) TX bytes:17550 (17.5 KB)
eth0 Link encap:Ethernet HWaddr 00:0c:29:45:5d:cb
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:104 errors:0 dropped:0 overruns:0 frame:0
TX packets:142 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:12504 (12.5 KB) TX bytes:21389 (21.3 KB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:16 errors:0 dropped:0 overruns:0 frame:0
TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1184 (1.1 KB) TX bytes:1184 (1.1 KB)
virbr0 Link encap:Ethernet HWaddr f2:19:a3:76:51:6f
inet addr:192.168.122.1 Bcast:192.168.122.255 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
执行brctl show
,可以看到 eth0 已经挂到 br0 上。
root@openstack:~# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.000c29455dcb no eth0
virbr0 8000.000000000000 yes
-
启动之前创建的虚拟机
- 修改虚拟机网卡配置
- 启动虚拟机
# virsh start kvm
- 查看 Linux Bridge。 会发下br0下面添加了一个设备 vnet0。
root@openstack:~# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.000c29455dcb no eth0
vnet0
virbr0 8000.000000000000
- 查看虚拟机网卡
root@openstack:~# virsh domiflist kvm
Interface Type Source Model MAC
-------------------------------------------------------
vnet0 bridge br0 rtl8139 52:54:00:c0:73:a2
-
通过 virt-manager 登录kvm。查看ip信息。
虚拟机kvm 网卡信息
可以看到 IP 地址为 172.16.245.136 与物理机 172.16.245.134 在同一个网段。
-
ping外网
ping外网
-
virbr0 网桥
在第一次执行
brctl show
时,会发现一个叫做 virbr0 的网桥。
virbr0 是 KVM 默认创建的,是为让连接在 virbr0 上的虚拟机网卡提供网络地址转换(Network Address Translation,缩写为NAT 访问)
virbr0 默认分配的 IP 是 192.168.122.1。为让连接在 virbr0 上的虚拟机网卡提供 DHCP 服务。
-
首先将虚拟机的网卡连接改为 NAT 。如下图
配置NAT -
启动虚拟机
# virsh start kvm
- 查看网桥。 vent0 已经挂到 birbr0 上。
root@openstack:~# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.000c29455dcb no eth0
virbr0 8000.fe5400c073a2 yes vnet0
- virbr0 使用 dnsmasq 提供的 DHCP 服务,可以在物理机进程中查到
root@openstack:~# ps -elf | grep dnsmasq
5 S libvirt+ 2235 1 0 80 0 - 7053 poll_s 14:03 ? 00:00:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf
在目录 /var/lib/libvirt/dnsmasq/
下有一个 default.leases
文件。当 虚拟机 kvm 成功获取 DHCP 的 IP 后,文件可以查到相应信息。
root@openstack:~# cat /var/lib/libvirt/dnsmasq/default.leases
1550388636 52:54:00:c0:73:a2 192.168.122.204 cirros 01:52:54:00:c0:73:a2
上面说 IP 192.168.122.204 已经分配给 MAC 地址为 52:54:00:c0:73:a2 的网卡。
-
登录 kvm 虚拟机,ping 外网
说明:
使用 NAT 的虚拟机 kvm 可以访问外网,但外网无法直接访问 kvm。
因为 kvm 发出的网络包源地址并不是 192.168.122.204, 而是被 NAT 替换为宿主机的 IP 地址了。
五、VLAN
有关 LAN 和 VLAN的概念查看 Lan和Vlan的区别和原理。
-
KVM 虚拟化环境下的 VLAN
上图中:
eth0 是物理机上的物理网卡,有一个命名为 eth0.10 的子设备于之相连。
eth0.10 就是 VLAN 设备。他的 VLAN ID 是 VLAN 10。
eth0.10 挂在命名为 brvlan10 的 Linux Bridge 上,虚拟机 kvm 的虚拟网卡 vent0 也挂在 brvlan10 上。
最终效果:
- 物理机用软件实现了一个交换机(虚拟交换机),上面定义了一个 VLAN10。
- eth0.10,brvlan10 和 vnet0 都分别接到 VLAN10 的 Access(Access类型端口:只能属于 1 个 VLAN,一般用于连接计算机端口) 口。而 eth0 就是一个 Trunk(Trunk类型端口:可以允许多个 VLAN 通过,可以接收和发送多个 VLAN 报文,一般用于交换机与交换机相关的接口) 口。
- kvm 通过 vent0 发出来的数据包被打上 VLAN10 的标签。
eth0.10 作用是:定义 VLAN10。
brvlan10 作用是:Bridge 上的其他网络设备自动加入到 VLAN10 中。
-
配置 VLAN
- 编辑
/etc/network/interfaces
编辑前
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
编辑后
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
auto eth0.10
iface eth0.10 inet manual
vlan-raw-device eth0
auto brvlan10
iface brvlan10 inet manual
bridge_stp off
bridge_waitport 0
bridge_fd 0
bridge_ports eth0.10
auto eth0.20
iface eth0.20 inet manual
vlan-raw-device eth0
auto brvlan20
iface brvlan20 inet manual
bridge_stp off
bridge_waitport 0
bridge_fd 0
bridge_ports eth0.20
-
重启系统
-
ifconfig
查看
root@openstack:~# ifconfig
brvlan10 Link encap:Ethernet HWaddr 00:0c:29:45:5d:cb
inet6 addr: fe80::20c:29ff:fe45:5dcb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:24 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:3896 (3.8 KB)
brvlan20 Link encap:Ethernet HWaddr 00:0c:29:45:5d:cb
inet6 addr: fe80::20c:29ff:fe45:5dcb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:24 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:3896 (3.8 KB)
eth0 Link encap:Ethernet HWaddr 00:0c:29:45:5d:cb
inet addr:172.16.245.134 Bcast:172.16.245.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe45:5dcb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:114 errors:0 dropped:0 overruns:0 frame:0
TX packets:239 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:13040 (13.0 KB) TX bytes:36646 (36.6 KB)
eth0.10 Link encap:Ethernet HWaddr 00:0c:29:45:5d:cb
inet6 addr: fe80::20c:29ff:fe45:5dcb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:48 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:7792 (7.7 KB)
eth0.20 Link encap:Ethernet HWaddr 00:0c:29:45:5d:cb
inet6 addr: fe80::20c:29ff:fe45:5dcb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:48 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:7792 (7.7 KB)
-
brctl show
查看网桥配置信息
root@openstack:~# brctl show
bridge name bridge id STP enabled interfaces
brvlan10 8000.000c29455dcb no eth0.10
brvlan20 8000.000c29455dcb no eth0.20
virbr0 8000.000000000000 yes
- 配置虚拟机网卡
启动虚拟机
-
brctl show
查看结果
root@openstack:~# brctl show
bridge name bridge id STP enabled interfaces
brvlan10 8000.000c29455dcb no eth0.10
vnet0
brvlan20 8000.000c29455dcb no eth0.20
virbr0 8000.000000000000 yes
不同VLan 之间是相互隔离的。虚拟机kvm2 接入 brvlan20。将两台虚拟机的ip配置在同一个网段,相互是不能通讯的。