
注意:本篇篇幅较长,从计算机、虚拟化、网络的概念,到网络、虚拟化工具、LaaS 管理工具等,都逐一介绍,推荐使用左侧目录来快速定位阅览。
一、计算机的构成¶
计算机的五大部件:CPU(运算器、控制器),RAM,IO 设备(输入、输出设备)
什么是程序:指令 + 数据,也就是算法 + 数据结构
- 以算法为核心,数据服务算法,是面向过程的编程
- 以数据为核心,算法服务数据,是面向对象的编程
1. CPU¶
以 32 位 CPU 为例,对内存的前端标识有 32 位的线路标识内存的存储单元,32 根线有电和没电的排列组合共 2 的 32 次方,每个存储单位是 1 字节,所以 32 位 CPU 支持最大的内存数是 4G
2. 内存¶
- 线性地址:4G
- 物理地址:1G
所有程序写数据到内存时,由内核将物理内存分配成页框后,以超供的方式,分配给进程。所有程序认为自己使用了物理机的全部 4G 内存,叫线性地址。写入线性内存数据时,由内核进行转换,再写到映射的物理地址上。
转换过程需要有一定的消耗,会浪费 CPU 的能计算能力,所以使用 MMU 芯片来管理线性内存到物理内存的转换,加速转换过程,再根据数据有热区的效应,将映射关系缓存在 TLB 上。虚拟化时,为了防止内存映射混乱,将使用带标签的 TLB,TaggedTLB
二、虚拟化介绍¶
虚拟化就是将一组物理平台,虚拟化为多组不同的,彼此之间隔离的平台。
CPU 在 OS 安装以后就已经被虚拟化了,每个进程认为自己是独占 CPU,内存的。
实现方式¶
时间复用:
- CPU 通过
时间复用,将时间分片,实现多任务
空间复用:
- 内存通过虚拟内存,以
空间复用的形式,实现多任务
虚拟化技术类型¶
- 主机虚拟化:xen,kvm,vmware,virtualbox,…
- 容器(用户名称空间隔离 NameSpace):
- Net 网络
- Mount 根文件系统
- PID 模拟 PID
- UTS 一个内核配置多个主机名
- IPC 进程间通信机制
- User 用户
实现的管理管理工具:docker,lxc(LinuX Container),openvz, …
- 系统库虚拟化:wine,…
- 应用程序级虚拟化:jvm,pvm,…
主机虚拟化实现方式¶
CPU:
- 模拟:emulation, 虚拟机的 arch 与物理平台的 arch 可以不相同
- 实现:qemu
- 虚拟:virtualization
- 完全虚拟化(full-virt)
- BT(vmware): 二进制转换 (软件)
- HVM:硬件辅助的虚拟化(硬件): “Intel VT” & “AMD AMD-v”
- 半(准)虚拟化 (para-virt):GuestOS 得明确知道自己运行于虚拟化技术
内存:
- MMU virtualization:线性内存和物理内存转换器
- Intel: EPT(Extended Page Table)
- AMD: NPT(Nested Page Table)
- TLB virtualization:缓存模块
- tagged TLB
IO:
- Emulation:模拟
- Para-virtualization:半虚拟化
- IO-through:IO 透传
性能上: IO 透传>半虚拟化>完全虚拟化
虚拟化的两种两种模型¶
Type-I 型:
不需要在硬件安装操作系统,让虚拟化软件(hypervisor 你可以理解它是一个虚拟机监控程序 )直接运行在硬件上,它可以直接接管 CPU,内存等等,所有运行在当前物理硬件上的主机都是虚拟机。
典型代表有:xen,ESX/ESXi.
Type-II 型:
易于管理,方便借助 HOST 的管理工具)
需要在硬件上安装一个操作系统,在操作系统上安装一个虚拟化软件,通过虚拟化软件创建各个虚拟机。
典型代表:kvm,VMware Workstation,Virtualbox
xen 和 kvm 不能很准确定位:
-
xen 需要在操作系统上,安装 xen 软件后重启,但是重启后,xen 就顶替掉原来的内核,摇身一变成了 hypervisor,原来的内核和用户空间就变成了虚拟机叫 dom0。xen 负责管理 cpu 和内存的虚拟化,而 io 虚拟化为了能兼容大量 io 设备的驱动,则由运行着原来内核的 dom0 通过 qemu 来管理 io 设备,所以 dom0 也是个特权域
-
kvm 不是软件,是在原来的操作系统上,通过加载内核模块的方式来启动,启动后内核就直接变成了 hypervisor 来管理 cpu 和内存虚拟化,而原来的用户空间内则运行 qemu 来管理 io 虚拟化
三、网络虚拟化工具¶
虚机机的网络通过软件来模拟真实的物理环境,后文中还会介绍几种常见 网络模型,需要用到的工具如下:
1. 网络名称空间管理工具¶
1 | ip netns |
2. 管理虚拟网卡¶
1 | ip link |
3. 网桥管理工具¶
1 | brctl |
openvswitch 是个非常非常强大的虚拟网络管理工具,本文暂时不做说明,以后 OpenStack 中用到时会再详细说明
四、KVM 介绍¶
kvm:全称 Kernel-based Virtual Machine
Qumranet 公司 --> 后被 RedHat
特性:
(1) 只支持 X86_64
(2) 硬件虚拟化 HVM:Intel VT | AMD AMD-v
KVM 的组件¶
两类组件:
- 1.(kvm.ko)/dev/kvm:工作为 hypervisor,在用户空间可通过系统调用 ioctl() 与内核中的 kvm 模块交互,从而完成虚拟机的创建、启动、停止、删除等各种管理功能;
- 2.qemu-kvm 进程:工作于用户空间,用于实现 IO 设备模拟;用于实现一个虚拟机实例;
KVM 模块加载进内存之后,系统的运行模式:
- 内核模式:GuestOS 执行 IO 类的操作时,或其它的特殊指令操作时的模式;它也被称为“Guest-Kernel”模式;
- 用户模式:Host OS 的用户空间,用于代为 GuestOS 发出 IO 请求;
- 来宾模式:GuestOS 的用户模式;所有的非 IO 类请求;
运行中的一个 kvm 虚拟机就是一个 qemu-kvm 进程,运行 qemu-kvm 程序并传递给它合适的选项及参数即能完成虚拟机启动,终止此进程即能关闭虚拟机;
QEMU 的组件¶
QEMU 主要有以下几个组成部分:
- 处理器模拟器(x86、PowerPC、Sparc 等)
- 仿真设备(显卡、网卡、硬盘等)
- 关联仿真设备至真实设备的通用设备:仿真主机的描述(如 PC、Power Mac 等)
- 调试器:与仿真器交互的用户接口
红帽团队从 QEMU 项目分支出一个项目,只支持 KVM,就叫 qemu-kvm

kvm 工具栈:
- qemu:
- qemu-kvm
- qemu-img
- libvirt:
- GUI: virt-manager, virt-viewer
- CLI: virsh, virt-install
- C/S: libvirtd
五、KVM 管理工具¶
常用管理工具:
- virt-manager 图形的工具
- virsh 命令行的工具
- qemu-kvm 底层命令行工具
使用难度上
qemu-kvm(纯手工) > virsh(半自动化) > virt-manager(图形)
但如果论可定制化和执行效率,却是要将排名颠倒一下的
下面从最简单的开始介绍
1. virt-manager¶
判断 CPU 是否支持硬件虚拟化¶
1 | grep -i -E '(vmx|svm|lm)' /proc/cpuinfo |
加载 kvm 模块¶
(1) 装载内核模块
- kvm:核心模块
- kvm-intel|kvm-amd
1 | modprob kvm |
安装图形界面¶
virt-manager 依赖图形
如果没有安装图形界面,先安装
1 | yum groupinstall "GNOME Desktop" |
安装并启动 virt-manager¶
1 | yum install qemu-kvm libvirt-daemon-kvm virt-manager |
注意:如果是用远程工具,需要远程工具支持 GNOME 图形(或使用 vnc)
- ubuntu 桌面版可以 ssh -X 直接在本地调用远程图形程序
- 而 win 下就比较麻烦,我使用 xshell+xmanager 方案,也可以成功调用
1 | ssh root@192.168.50.11 #先远程到 kvm 服务器 192.168.50.11 |
打开控制台后,点新建虚拟机,选择一个已存在的 qcow2 格式的磁盘映像,就可以开机启动了,由于我下的的 cloud 版的磁盘镜像,开机会自动找 metadata 服务,但是我本地没有,所以会等很久,重试 20 次失败后,进入系统登录界面,过程都是图形化的操作,和 vmware 很相似,就不过多阐述了

创建桥接网络¶
默认 libvirt 安装好后只创建一个 NAT 网络,如果想要使用桥接,需要手动配置,配置方法:
1、更改默认网卡配置文件 ifcfg-ens33,将 IP 地址、MAC、UUID 等信息去掉,添加一项 BRIDGE=br-ex
1 | BRIDGE=br-ex |
2、新建桥配置文件 br-ex,并且把 ip 地址绑定在桥上
1 | DEVICE=br-ex |
如果是 openstack 中使用 openvswitch 管理的话,配置文件有所变化,请参考
RedHat 官方文档
3、重启网络服务,查看网卡配置,可以看到 ip 地址已经配置在桥网卡 be-ex 上了,桥接就配置好了
1 | kvm_server ~]# systemctl restart network |
2. virsh¶
virsh 是什么¶
virsh 属于 libvirt 系的 kvm 管理工具,它可以对虚拟机做全生命周期的命令行管理工具,从创建、启动、以及后续的虚拟机管理的操作都能实现
通过 virsh help 可以查看命令帮助信息,命令按类型分成不同的组,可以通过 virsh help [组名] 来查看单组信息
virsh 常用参数¶
1 | vitsh |
网络配置文件¶
注意:网络配置文件可以从默认的 default.xml 复制然后修改,也可以使用 virt-manager 直接创建
1 | ~]# cp /etc/libvirt/qemu/networks/default.xml /etc/libvirt/qemu/networks/nat.xml |
1. libvirt 网络基本概念¶
libvirt 默认使用了一个名为 default 的 nat 网络,这个网络默认使用 virbr0 作为桥接接口,使用 dnsmasq 来为使用 nat 网络的虚拟机提供 dns 及 dhcp 服务,dnsmasq 生效后的配置文件默认保存在以下路径:
1 | - /var/lib/libvirt/dnsmasq/default.hostsfile # mac&&ip 绑定的配置文件 |
dnsmasq 服务的启动脚本在 /etc/init.d/dnsmasq,但是我们如果手动使用此脚本来启动服务将会导致 dnsmasq 读取其自己的配置文件来启动此服务,因此这么做是不推荐的,因为这个服务完全由 libvirtd 在接管,当 libvirtd 服务启动的时候,它会将它管理的被标记为 autostart 的 network 一并启动起来,而启动 network 的时候就会自动调用 dnsmasq 并赋予其适宜的配置文件来运行服务。
使用 libvirt 管理的网络都会用到 dnsmasq 来产生相应的配置,比如定义了一个名为 route110 的 network,那么这个 route110 将使用一个新的桥接接口 virbr1 来接入网络,并使用 dnsmasq 产生名为 route110.hostsfile 和 route110.leases 的配置文件。其实这里提到的 virbr0 和 virbr1 都是 libvirt 产生的虚拟网卡,其作用就相当于一个虚拟交换机,为虚拟机提供网络转发服务。
2. libvirt 中网络的类型¶
首先分析一下 libvirt 所能提供的网络类型:isolated 和 forwarding,其中,isolated 意为绝对隔离的网络,也就是说处于此网络内的虚拟机对于外界是隔离的,这种模式可以用到一些特殊的场合,比如虚拟机只提供给内部使用,虚拟机只要求能相互通信而不需要与互联网通信。另外一类,forwarding,就是把虚拟机的数据 forward 到物理网络实现与外部网络进行通讯,其中 forwarding 又分为两种:nat 和 routed。
3. nat¶
就是把虚拟机的网络数据在经过物理机网络的时候进行 ip 伪装,这样所有虚拟机出去的网络数据都相当于是物理机出去的数据,也就是说,我们可以分配给使用 nat 网络的虚拟机一个内网 ip,而这个内网 ip 的虚拟机访问出去的时候外部网络看到的是物理机的公网 ip,这样做的用处就是实现多个虚拟机共享物理主机的公网 ip,节省公网 ip 地址;如前所述,默认情况下 libvirt 已经提供了一个名为 default 的 nat 网络,在不需要进行任何配置的情况下使用 default 网络的虚拟机即可访问互联网,但是互联网却无法访问虚拟机提供的服务,这是因为 default 网络只对虚拟机的数据包进行了伪装,而没有进行 dnat 和 snat。
需要注意的是 libvirt 所实现的这种 nat 网络是通过物理机的 iptables 规则来实现的,也即是在虚拟机数据经过 nat 表的 postrouting 链出去的时候对其进行了伪装。
4. routed¶
forwarding 模式的另外一种,routed,就是将虚拟机的数据直接通过物理机 route 出去,和 nat 一样,也是需要一个 virbr 虚拟网卡接口来与外面进行通信,这种模式的不同之处在于虚拟机的数据没有经过伪装便直接交给了外部网络,也就是说,使用 route 模式网络的虚拟机可以使用公网 ip 地址,而物理机却恰恰在这个时候完全可以使用一个内网 ip 而不对外提供访问,这样,虚拟机的网卡仅仅把物理机当作一个 route 数据的工具,此模式应用的场合很多,比如需要让虚拟机运行在一个 dmz 网络中。但是使用 route 模式有诸多限制,例如物理机的网络接口不够用的情况下。
这里需要注意的是,nat 模式和 route 模式的区别仅仅在于前者使用了 iptables 对虚拟机的数据包进行了伪装,而后者没有。
磁盘映像¶
可以通过 qemu 来创建 qcow2 和管理磁盘映像文件
补充:
快照技术分为
- 1.全量快照:
- 镜像分离
- 2.增量快照:
- 写时复制:cow > copy on write
- 写时重定向:row > Redirect on write
常用命令¶
1 | qemu-create -f qcow2 -o preallocation=metadata(稀疏格式),size=10G /PATH/name.img #创建磁盘映像 |
创建虚机¶
virsh 创建虚机需要指定 xml 格式的文件,如果纯手敲很容易写错,可以先使用 virt-manager 图形界面创建一个虚机,然后在目录 /etc/libvirt/qemu 找到刚才创建的虚机的 xml 文件,复制一份作为模板使用,需要注意的是,要把虚机的标识信息删除,比如网卡配置文件等,不然会冲突。然后手动定义比如名字、磁盘文件目录等信息,UUID 的信息可以直接删除,系统会自动创建。
3. qemu-kvm¶
qemu-kvm 是 QEMU 项目的一个分支,只支持 KVM,由红帽团队维护
qemu 都负责什么¶
Qemu:
- 处理器模拟器,虽然对 cpu 的虚拟是由 kvm 负责调度,但是给每个虚拟机拿到一个假的 cpu 可以用,是 qemu 的工作
- 仿真各种 IO 设备
- 将仿真设备连接至主机的物理设备
- 提供用户接口
使用 qemu-kvm 管理 vms,命令放置在 /usr/libexec/qemu-kvm,他是 被 Red-Hat 有意放置在这个目录,如果不想用绝对路径来执行,可以创建一个软连接到 /usr/bin/ 下
1 | ln -sv /usr/libexec/qemu-kvm /usr/bin/ |
qemu 常用参数¶
注意:qemu-kvm 复杂且繁琐,需要耐心查看和使用。
标准选项¶
1 | qemu-kvm |
块设备相关选项¶
1 | - cdrom file # 指定要使用光盘映像文件 |
显示选项¶
1 | - display type # 显示的类型,sdl, curses, none 和 vnc |
网络选项¶
1 | - net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v] # 为虚拟机创建一个网络接口,并将其添加至指定的 VLAN; |
其它选项¶
1 | - daemonize # 以守护进程运行 |
示例,启动一个虚机¶
1 | qemu-kvm -cpu host -smp 8,ockets=2,cores=2,threads=2 \ |
六、各种网络模型的实现¶
虚机机的网络通过软件来模拟真实的物理环境,使用的工具上文中也提到过,下面介绍怎么使用软件来创建各种网络模型
1. 隔离网络¶
创建一个网卡桥,把两个虚拟机的网卡加到桥上,只有连接到桥上的设备才能互相通信,是个隔离的二层网络
开启内核转发
1 | kvm_server ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf |
创建 mybr0 并 up
1 | kvm_server ~]# brctl addbr mybr0 |
创建两个虚拟机 vm1 和 vm2,网卡叫 vm1eth0 和 vm2eth0
1 | kvm_server ~]# qemu-kvm -cpu host -smp 8,ockets=2,cores=2,threads=2 \ |
可以看到两个虚拟机的网卡已经添加到 mybr0 上了
1 | kvm_server ~]# vm1 brctl show |
使用 vncviewer 登录虚拟机
1 | kvm_server ~]# vncviewer 127.0.0.1 :1 & # 1 和 2 是创建虚机时指定的桌面号 |
配置 vm1 和 vm2 的 IP 地址
1 | vm1 ~]# ip addr add 10.0.0.1/24 dev eth0 # vm1 上的 eth0 |
可以互相 ping 通了,隔离网络就做好了,但是 不能和其他任何网络通,连宿主机也 ping 不到
1 | vm1 ~]# ping 10.0.0.2 |
2. 仅主机网络 Host-Only¶
仅主机的网络是在隔离网络的基础上,给 mybr0 的桥上配置一个同网段的地址,宿主机就有 IP,可以与 vm1 和 vm2 连通了
1 | kvm_server ~]# ip addr add 10.0.0.254/24 dev mybr0 # 给桥配上同网段 IP |
仅主机的网络目前只能在宿主机内通信,如果想和外边的网络通信,有两种方法可以实现
3. Route 网络和 NAT¶
第一种是 route,需要开启核心转发,然后把网关指向 mybr0 桥的 ip 就可以了,但是因为外部网络没有私有网络的路由,所以 ip 包是有出无回
另一种是 NAT,将地址转换成宿主机的 ip 发出,ip 包有出有回,下边说 NAT 网络构建方法:
在仅主机的网络上,添加一条 iptables 规则
1 | kvm_server ~]# iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.1/24 -j MASQUERADE |
虚拟机把默认网关路由指向 mybr0 桥的地址 10.0.0.254
1 | vm1 ~]# ip route add default via 10.0.0.254 |
虚机就可以通过 NAT 转发 ping 外网了
1 | vm1 ~]# ping 8.8.8.8 |
4. dnsmasq 服务¶
dnsmasq 是一个 轻量化的程序,可以实现简单的 dns_forword 和 dhcp 功能
使用 dnsmasq 实现在自己创建的 mybr0 网络中,增加 dhcp 功能,让虚机开机就能通过 dhcp 获取到 IP 地址
1 | dnsmasq --listen-address=10.0.0.254 --dhcp-range=10.0.0.1,10.0.0.253,48h --dhcp-option=3,10.0.0.254 |
在虚机内使用 cirros-dhcpc up eth0 就可以自动获得 ip 地址和网关了
以后在 mybr0 这个网络中的虚机,开机就能自动获得 ip 地址了!
七、镜像预生成器¶
这是啥?¶
镜像预生成器可以在不开启虚机的情况下,对磁盘镜像文件进行定制,并且剥离一些独有数据,比如 mac 地址、ssh 秘钥等等,还可以设置 root 密码,安装软件等等等…
两种使用场景:
- 目前流行的社区都提供了开机即用的磁盘镜像文件下载,但是不一定能符合自己的使用要求,这样就可以使用镜像预生成器来进行二次定制
- 克隆的虚机,mac 地址,bash 历史命令,私有文件等,需要去除
安装工具 virt-sysprep¶
1 | yum install libguestfs-tools |
virt-sysprep 语法格式¶
1 | virt-sysprep [--options] -d domname # 可指定一个虚机 |
示例:事先设置好 root 密码,并且安装好 httpd,使用 --network 参数让虚拟机开启网络,默认是关闭的,会影响 yum 安装 httpd
1 | [root@centos_1 templates]# virt-sysprep --root-password password:123qwe \ |
八、LaaS 管理平台¶
以上就是关于 kvm 的各种管理工具,但是生产环境中,这样的管理方式效率还是太低了,目前市面上有很多工具,可以更好的管理 LaaS 这一层的资源,可以参考官方手册
推荐几个各种环境下的开源解决方案:
- kimchi 基础 h5 的管理工具,只能管理单机
- Proxmox VE 可以在小规模企业使用,对节点多、环境复杂的架构管理欠缺
- oVirt 可以管理近百个节点的管理软件
- OpenStack 数百个以上的物理节点,只有 OpenStack 支持的比较好了
kimchi¶
这里主要介绍一下 kimchi:kimchi 通过 web 界面来管理 kvm,配置好模板后,可以根据模板快速创建虚拟机,适合自己做实验,或者公司节点比较少的情况下使用
安装 kimchi¶
1、打开官方项目首页
2、需要下载 wok 和 kimchi 两个软件包,根据自己的平台下载二进制安装程序,我是 centos7 64 位,所以下载
- kimchi-2.5.0-0.el7.centos.noarch.rpm
- wok-2.5.0-0.el7.centos.noarch.rpm
1 | wget https://github.com/kimchi-project/kimchi/releases/download/2.5.0/kimchi-2.5.0-0.el7.centos.noarch.rpm |
3、使用 yum 安装,来解决依赖问题,需要注意因为依赖 vnc,请同时安装 vnc 工具
1 | yum install kimchi-2.5.0-0.el7.centos.noarch.rpm \ |
4、启动 kimchi
1 | systemctl daemon-reload |
访问 web¶
在浏览器输入 https://[address]:8001,就可以访问了,注意是 https 的,用户名密码为 root 系统账号
web 界面一目了然,简单易懂,相信如果对以上知识都了解的话,配置起来不会有一点问题,这里说一下使用流程,就不放图片了
- 在
网络里创建好自己需要的网络模型 - 添加
存储器,就是虚机磁盘镜像文件要保存的地方,自己指定即可 - 创建
模板,配置好文件路径,其实就是这个模板要用的磁盘镜像文件,创建好模板后可以查看并编辑默认的配置信息,如cpu、内存,调整磁盘大小,注意只能扩大,不能缩小 - 然后在
访客就可以根据刚才做好的模板,创建虚拟机啦 - 创建好之后可以通过 web 访问虚拟机的 vnc,还可以通过控制来开机、关机、克隆、快照等操作
使用 qemu-img info 查看刚创建好的虚拟机的磁盘文件,可以看出是以快照的方式创建的,大小只有 1.1M,在有新的文件写入时才会增长。这与 ceph 的 rbd 中,使用 RAW 格式创建的磁盘镜像很相似,应该属于 row(写时重定向)机制的快照,所以依赖源镜像文件,也就是模板中指定的磁盘镜像文件,所以千万不要删除,不然虚拟机就出问题啦
1 | qemu-img info 045b56f8-4a94-420c-aa6e-3bd82deaf295-0.img |