KVM虚拟化管理平台的实现
源码链接:https://github.com/wsjhk/IaaS_admin.git
视频演示链接:https://v.youku.com/v_show/id_XMjg4MTczODU1Ng==.html
(N年前刚开始学习Python时做的第一个自主设计实现项目,代码实在写的烂,不喜勿喷!)
根据KVM虚拟化管理的要求,设计并实现网页操作管理KVM虚拟机。设计原理架构如下图所示:
如上图所示,前台使用python的FLASK框架实现主程序和各个功能网页,通过Redis的发布订阅功能,实现前台和后台的交互,前台网页触发操作,发布操作到Redis的channel中,后台监听到操作之后触发执行对应的shell脚本文件对虚拟机进行操作,包括:创建虚拟机,删除虚拟机,开启虚拟机,关闭虚拟机,重启虚拟机,在线修改虚拟机的内存和CPU参数,在线添加和删除虚拟机磁盘以及虚拟机的在线迁移。其中,KVM宿主机的操作系统制作虚拟机是基于LVM分区的快照功能,实现虚拟机的快速创建和销毁。需要制作好各种操作系统的母盘。母盘的制作包括,安装对应的操作系统,安装VNC服务,安装SSH服务并设置服务开机自启动。其中,linux操作系统支持VNC和SSH两种远程方式,windows操作系统只支持VNC远程,也可以使用windows自带的桌面远程工具进行远程操作。以下是具体的实现:
1.前台具体实现:
根据要求实现如下功能设计图:
前台是基于python的FLASK框架实现的,Flask是一个基于Python的web框架,它的设计目的是提供Web开发所需的最小功能子集。
Flask与别的框架(尤其是采用其他编程语言的框架)的不同之处在于:它没有绑定诸如数据库查询或者表单处理等功能库,以及它们所组成的整个生态系统。它倾向于对这些功能的实现方式不做任何限定。
这种系统带来的主要好处是:开发者能够使用他们想用的任何方式和工具,去设计他们的应用架构。另外,对于一些常见的通用功能,Flask没有以某种特定方式去实现,这意味着在Flask中,对标准库的使用会比其他框架里多,这保证了通用功能的稳定性及针对其他Python程序员的可读性。由于Flask社区十分庞大,所以该社区提供的添加通用功能的方式非常多。所以通过本系列教程,了解它们如何帮助我们避免重复造轮子。这些扩展的妙处在于,如果不需要那些额外的功能,就不用引入它们,这样我们的应用才会保持简洁、轻量。
这种系统的最大弊端是,大部分新的Flask用户不知道如何正确地规划大型应用的结构,最后弄出一大堆让人难以理解和维护的代码。所以本教程另一个重点是如何为Flask应用创建模型/视图/控制器(MVC)架构。
安装flask
安装flassk很简单,使用pip安装.
#pip install flask
本系统使用了FLASK的路由功能实现的,Flask是一个WSGI应用框架,这意味着我们进行Flask开发时,不需要 关注网络方面的操作,Flask应用的入口是封装过的网络请求包,出口是 网络响应,我们仅需要关注这个阶段内的处理逻辑。
WSGI服务器 :Flask虽然内置了简单的WSGI服务器,但其性能仅仅适用于开发期的调试。Flask官网推荐了多种WSGI服务器,实现方式从多进程到多线程到协程, 这方面的选择我们在本课程中将不涉及。
REST适应性 :虽然Flask和Django一样,最初的出发点都是服务端的动态网页应用。但 Flask的设计使之也相当适用于面向资源的REST架构,在越来越移动化 并且单页应用越来越重要的WEB开发领域,这是Flask相对于Django相当 大的优势。
编写一个基于Flask的hello world相当容易:
1)导入Flask类
from flask import Flask
Flask类是Flask框架的核心类,它实现了WSGI应用规范。
2)创建Flask实例
app = Flask(__name__)
Flask构造函数的第一个参数指定一个引入名/importname。Flask框架 使用这个名字进行静态资源、模板、错误信息的定位。除非你清楚的理解它的 作用,通常情况下,我们总应该使用特殊变量_name。
Flask实例是可调用的(具有call方法),这个实例可以直接对接 WSGI服务器。
3)注册路由
@route('/')
def index():
return 'Hello,Flask!'
注册路由就是建立URL规则和处理函数之间的关联。Flask框架依赖于路由 完成HTTP请求的分发。
路由中的函数被称为视图函数,其返回值将作为HTTP响应的正文内容。
4)对接并启动WSGI服务器
Flask封装了一个简单的开发用WSGI服务器,我们可以通过调用run() 启动服务器运行:
app.run(host='0.0.0.0',port=80)
至此,可以使用FLASK的route功能进行开发了。
前台工程框架代码结构,如下图所示:
代码结构:
其中,KVM是主程序,使用FLASK框架的route功能实现url的跳转访问对应的html页面。如登录后跳转到首页的关键代码:
@app.route('/index', methods=['GET','POST'])
def index():
username = request.cookies.get('username')
if not username:
return "please login!!!"
islogin = session.get('islogin')
if request.method == 'POST':
response = make_response(redirect('/vm_create'))
response.set_cookie('username', value=username, max_age=300)
session['islogin'] = '1'
return response
else:
return render_template('index.html',username=username,islogin=islogin)
接下来是前台页面的设计,登录页使用html和CSS实现,如下图所示为login.html的实现:
登录之后跳转到首页index.html页面:
之后就可以使用KVM Cloud系统创建并管理操作虚拟机了。
创建虚拟机页面的功能页面vm_create.html实现:
然后是虚拟机列表vm_list.html的实现,显示虚拟机列表和虚拟机的详细信息:
点击虚拟机名称可以跳转到虚拟机参数调整和操作功能vm_detail.html页面:
如果在vm_list.html页面点击虚拟机的console对应列的远程操作,将可以页面远程并操作虚拟机,如下分别是linux的VNC远程方式界面,SSH远程方式界面,windows的VNC远程方式界面。
Linux的VNC远程:
Linux的SSH远程:
Windows的VNC远程:
然后是磁盘添加的实现,创建虚拟磁盘disk_create.html实现:
输入参数之后点击创建即可创建虚拟磁盘,然后跳转到磁盘列表disk_list.html页面:
如图,可以挂在磁盘到对应的虚拟机,卸载和删除磁盘。挂载之后可以通过fdisk -l命令查看虚拟机磁盘信息:
最后是虚拟机在线迁移功能vm_migrate.html界面的实现:
输入要迁移的虚拟机和要迁移的目标宿主机,点击迁移即可实现虚拟机的在线迁移。迁移成功之后页面会显示类似“迁移虚拟机成功”的字样。
2.1.Redis发布订阅实现原理:
发布订阅中使用到的命令就只有三个:PUBLISH,SUBSCRIBE,PSUBSCRIBE
PUBLISH 用于发布消息
SUBSCRIBE 也叫频道订阅,用于订阅某一特定的频道
PSUBSCRIBE 也叫模式订阅,用于订阅某一组频道,使用glob的方式,比如xxx-*可以匹配xxx-a,和xxx-b,xxx-ddd等等
关联操作:
如果已经存在订阅者,则添加到链表的尾部
如果没有订阅者,那么创建频道,然后添加订阅者
删除操作:
找到对应的链表,进行删除
如果删除后,链表为空,则删除频道
订阅模式:
新建一个pubsubPattern结构
添加到链表的尾部
退订模式:
查找相应的pubsubPattern然后删除
发送消息:
将消息发送给channel频道的所有订阅者
遍历整个pubsub_patterns表,查找匹配的模式,如果有一个或者多个模式与频道匹配,将消息发送给pattern模式的订阅者
相关命令:
查看所有的频道:PUBSUB CHANNELS
查询订阅者的数量:PUBSUB NUMSUB
查询服务器被订阅者的数量:PUBSUB NUMPAT
2.2.Redis安装:
1.)将其下载到/opt目录下解压并进入目录。
2)编译源程序
make
cd src
make install PREFIX=/usr/local/redis
3.)接下来我们看看/usr/local/redis/bin目录下的几个文件是什么
redis-benchmark:redis性能测试工具
redis-check-aof:检查aof日志的工具
redis-check-dump:检查rdb日志的工具
redis-cli:连接用的客户端
redis-server:redis服务进程
4.)Redis的配置
daemonize:如需要在后台运行,把该项的值改为yes
pdifile:把pid文件放在/var/run/redis.pid,可以配置到其他地址
bind:指定redis只接收来自该IP的请求,如果不设置,那么将处理所有请求,在生产环节中最好设置该项
port:监听端口,默认为6379
timeout:设置客户端连接时的超时时间,单位为秒
loglevel:等级分为4级,debug,revbose,notice和warning。生产环境下一般开启notice
logfile:配置log文件地址,默认使用标准输出,即打印在命令行终端的端口上
database:设置数据库的个数,默认使用的数据库是0
save:设置redis进行数据库镜像的频率
rdbcompression:在进行镜像备份时,是否进行压缩
dbfilename:镜像备份文件的文件名
dir:数据库镜像备份的文件放置的路径
slaveof:设置该数据库为其他数据库的从数据库
masterauth:当主数据库连接需要密码验证时,在这里设定
requirepass:设置客户端连接后进行任何其他指定前需要使用的密码
maxclients:限制同时连接的客户端数量
maxmemory:设置redis能够使用的最大内存
appendonly:开启appendonly模式后,redis会把每一次所接收到的写操作都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态
appendfsync:设置appendonly.aof文件进行同步的频率
vm_enabled:是否开启虚拟内存支持
vm_swap_file:设置虚拟内存的交换文件的路径
vm_max_momery:设置开启虚拟内存后,redis将使用的最大物理内存的大小,默认为0
vm_page_size:设置虚拟内存页的大小
vm_pages:设置交换文件的总的page数量
vm_max_thrrads:设置vm IO同时使用的线程数量
5)启动redis:#redis-server redis.conf
6)停止redis实例
/usr/local/redis/bin/redis-cli shutdown
或者
pkill redis-server
7)让redis开机自启
vim /etc/rc.local
加入
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis-conf
3.接下来是后台的具体实现:
后台实现包括两部分,一部分是KVM宿主机环境的搭建,另一部分是后台程序代码的功能实现。
一、 KVM宿主机环境的搭建:
KVM安装配置
1、准备工作
1.1 关闭iptables防火墙
[root@localhost ~]# service iptables stop //停止iptables
1.2 CPU开通支持虚拟化
需要在BIOS中开启虚拟化,一般是默认开启的
2、安装kvm虚拟机
2.1) 查看CPU是否支持kvm完全虚拟机
[root@localhost ~]# cat /proc/cpuinfo | grep 'vmx' //Intel CPU判断方法
[root@localhost ~]# cat /proc/cpuinfo | grep 'svm' //AMD CPU判断方法
根据对应的CPU型号进行选择判断方法,如果能出现信息 ,就说明CPU支持KVM完全虚拟机
2.2) 安装kvm和其它虚拟化所需管理软件包
[root@localhost ~]# yum install -y kvm virt-* libvirts bridge-utils qemu-img
软件包名称介绍:
kvm:软件包中含有KVM内核模块,它在默认linux内核中提供kvm管理程序
libvirts:安装虚拟机管理工具,使用virsh等命令来管理和控制虚拟机
bridge-utils:设置网络网卡桥接
virt-*:创建、克隆虚拟机命令,使用qemu命令来创建磁盘等。
qemu-img:安装qemu组件,使用qemu命令来创建磁盘等。
2.3) 加载kvm模块,查看kvm模块是否被加载
[root@localhost ~]# modprobe kvm-intel //加载kvm模块
[root@localhost ~]# lsmod | grep kvm //查看kvm模块是否被加载
2.4) 重启确认kvm是否被加载
[root@localhost ~]# reboot //重启
[root@localhost ~]# lsmod | grep kvm //查看kvm模块是否被加载
2.5) 查看已打开虚拟机列表
[root@localhost ~]# virsh list //查看虚拟机列表,如果有的话,就会显示出来
2.6) 配置eth0、br0网卡
[eth0网卡]
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
HWADDR=74:D4:35:87:71:02
TYPE=Ethernet
UUID=723095b7-27d1-4f88-aa5f-5aa6b0472fbc
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=none
BRIDGE=br0
[br0网卡]
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
NM_CONTROLLED=no
BOOTPROTO=static
IPADDR=172.16.10.23
NETMASK=255.255.255.0
GATEWAY=172.16.10.254
DNS1=202.96.128.86
大家可以看着我的配置来进行修改,
2.7) 查看目前所有的网桥接口
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.74d435877102 no eth0
virbr0 8000.5254005ce327 yes virbr0-nic
(如果eth0没有挂载br0上就要使用命令:#brctl addif br0 eth0 将其挂上去即可)
2.8 修改VNC服务器的配置文件
[root@localhost ~]# vim /etc/libvirt/qemu.conf
将 vnc_listen = "0.0.0.0" 前面的#号注释去掉 //在文件的第12行
2.9) 重启libvirtd和messagebus服务
[root@localhost ~]# /etc/init.d/libvirtd restart //重启libvirtd服务
Stopping libvirtd daemon: [ OK ]
Starting libvirtd daemon: [ OK ]
(若出现重启libvirtd服务失败,libvirtd: relocation error: libvirtd: symbol dm_task_get_info_with_deferred_remove, version Base not defined in file libdevmapper.so.1.02 with link time reference,则执行:yum -y upgrade device-mapper-libs之后重启libvirtd服务即可)
[root@localhost ~]# /etc/init.d/messagebus restart //重启messagebus服务
Stopping system message bus: [ OK ]
Starting system message bus: [ OK ]
3、 在宿主机上创建、安装kvm虚拟机
使用lvm安装虚拟机,制作镜像系统。然后创建快照来备份和快速复制启动虚拟机。
#vgrename /dev/kvm /dev/vg01
#lvcreate -L 8G -n s_centos01 vg01
#virt-install -n centos_mupan -r 2048 -vcpus=1 -s 10 -c /data/iso/centos.iso --hvm --os-type=linux -f /dev/vg01/centos_mupan --bridge=br0 --graphics vnc --force --autostart &
#lvcreate -s -L 2G -n s_centos01 /dev/vg01/centos_mupan
创建虚拟机快照之后,编写kvm启动的s_centos01.xml文件指定source设备是s_centos01,修改uuid,mac和name。然后
#virsh define s_ubuntu01.xml来启动虚拟机。
#virsh start s_ubuntu01
二、后台功能实现:
如图是代码的结构图:
目录结构是:
以下是各Shell脚本的功能说明:
1) create_linux_vm_xml.sh:
创建linux虚拟机xml配置信息脚本,将前台参数传递给给脚本,脚本根据参数修改配置文件的name,cpu,memory,mac地址,启动分区等等信息。并将生产的信息写入以虚拟机名称命名的xml文件中保存到指定的文件中。
2) create_window_vm_xml.sh:
创建windows虚拟机xml配置信息脚本,将前台参数传递给给脚本,脚本根据参数修改配置文件的name,cpu,memory,mac地址,启动分区等等信息。并将生产的信息写入以虚拟机名称命名的xml文件中保存到指定的文件中。
3) get_running_vm_info.sh:
获取虚拟机当前状态列表写vm_list文件中的脚本,通过系统命令和virsh命令获取虚拟机的状态,然后使用awk,sed,grep,wc和sort等工具分析提取需要的虚拟机信息组合成虚拟机前台展示的信息保存到vm_list文件中。
4) start_vm_vnc.sh:
创建虚拟机IP的noVNC代理监听进程脚本,根据vm_list文件的虚拟机信息,提取出ip地址,根据IP地址启动VNC的代理连接进程并后台运行,改脚本每5秒钟执行一次,以保证每个ip都能及时建立连接。
5) delete_vm.sh:
删除虚拟机脚本,删除虚拟机时触发的操作,删除该虚拟机的状态,xml配置文件和lvm快照分区的一切信息。无法恢复,需谨慎操作。
6) create_disk.sh:
创建磁盘脚本,根据名称和大小的参数在系统中创建虚拟磁盘,生成img镜像磁盘文件和xml磁盘配置信息,将其保存到指定的文件夹中供虚拟机挂载时调用。
7) get_disk_info.sh:
获取磁盘状态列表并写到disk_list文件中的脚本,通过系统命令和virsh命令获取磁盘的状态,然后使用awk,sed,grep,wc和sort等工具分析提取需要的磁盘信息组合成磁盘前台展示的信息保存到disk_list文件中。
8) mount_disk.sh
挂载磁盘到虚拟机脚本,通过触发参数挂载指定的磁盘到指定的虚拟机中,并且改写disk_list列表文件的信息,将该磁盘的状态改为挂载的虚拟机名称,表示该磁盘当前正在被哪个虚拟机使用,需要卸载之后才能分配给其他虚拟机使用。
9) umount_disk.sh:
卸载磁盘脚本,触发操作从指定的虚拟机中卸载该磁盘,卸载之后改写disk_list文件中的信息为unuse表示未被使用的状态,可以被其他虚拟机挂载使用。
10)delete_disk.sh:
删除磁盘脚本,触发操作,将该磁盘删除。如果没有被挂载是未使用的状态则直接删除该磁盘的xml配置文件和img镜像文件,并改写disk_list文件将其从中删除;否则,将磁盘从虚拟机中卸载掉之后删除该磁盘的xml配置文件和img镜像文件,并改写disk_list文件将其从中删除。
11)migrate.sh:
迁移虚拟机脚本,触发操作,传递虚拟机和目标宿主机作为参数执行虚拟机的在线迁移操作,需要在目标宿主机中有同样路径和名称的虚拟机分区磁盘,如果没有,则会使用lvm命令创建指定的分区之后再做迁移操作。
12)RedisHelper.py:
redis连接python脚本,创建python程序和redis的连接并创建channel监听,通过该连接进行信息的发布和订阅,实现前后台的信息交互,实时性强。
13)KVM.py:
后台python主监听进程脚本,监听redis,订阅前台发布的信息之后判断执行脚本触发操作,并将操作的结果通过redis发布信息到chaneel中,反馈给前台,是实现信息的交互。
其中,主程序文件是KVM.py文件,实现监听Redis并执行shell脚本返回结果发布到Redis中。vm_info.list文件记录了创建虚拟机时的状态信息列表,vm_list文件记录了虚拟机当前在KVM宿主机的状态列表。Disk_list文件记录了磁盘的状态信息列表。如下:
#cat vm_info.list
xp01 1 2048000 10 Windows_xp running
centos 1 2048000 10 Linux_CentOS running
#cat vm_list
centos|192.168.0.105|1|2048000|centos|running
xp01|192.168.0.133|1|2048000|winxp|running
#cat vm_list
sdb|10|unuse
其次,前台页面VNC远程虚拟机需要在宿主机安装noVNC程序做代理,建立连接代理到虚拟机的VNC服务端口,才可以在页面实现websockity的访问。以下是建立连接代理的监听脚本start_vm_vnc.sh,虚拟机母盘制作都默认使用5901作为VNC服务的监听端口:
页面的SSH远程访问Linux使用了shellinabox开源工具实现,在linux母盘中安装并设置开机启动即可,基于母盘创建的虚拟也会有了。Shellinabox安装如下:
部署shellinabox:
1) 安装依赖:
#yum install git openssl-devel pam-devel zlib-devel autoconf automake libtool
2)获取源代码:
#git clone https://github.com/shellinabox/shellinabox.git && cd shellinabox
3)生成编译配置信息:
#autoreconf -i
4)配置和编译:
#./configure && make
5)安装:
#make install
6)配置生成安全证书:
#openssl genrsa -des3 -out my.key 1024
#openssl req -new -key my.key -out my.csr
#cp my.key my.key.org
#openssl rsa -in my.key.org -out my.key
#openssl x509 -req -days 3650 -in my.csr -signkey my.key -out my.crt
#cat my.crt my.key > certificate.pem
7)启动:
#/usr/local/bin/shellinaboxd -c /root -u root -b
#/usr/local/bin/shellinaboxd --disable-ssl -c /root -u root -b(不使用https)
8)查看监听端口:
#netstat -ntpl |grep 4200
9)查看监听进程:
#ps -ef |grep shell
10)浏览器访问:
https://ip:4200
至此,KVM虚拟化管理系统前后台实现完成。