KVM虚拟化技术深度解析

KVM虚拟化解决方案

++虚拟化使云计算得以发展, 云计算使虚拟化得以进步, 两者相互成就了当今丰富多彩的服务端资源结构++

文章目录

    • KVM虚拟化解决方案
      • [1.1 云计算概述](#1.1 云计算概述)
        • [1.1.1 什么是云计算?](#1.1.1 什么是云计算?)
        • [1.1.2 云计算的几种服务模型](#1.1.2 云计算的几种服务模型)
      • [1.2 虚拟化技术](#1.2 虚拟化技术)
        • [1.2.1 什么是虚拟化](#1.2.1 什么是虚拟化)
        • [1.2.2 半虚拟化和全虚拟化](#1.2.2 半虚拟化和全虚拟化)
      • [1.3 KVM详解](#1.3 KVM详解)
        • [1.3.1 KVM简介](#1.3.1 KVM简介)
        • [1.3.2 KVM虚机创建](#1.3.2 KVM虚机创建)
        • [1.3.3 KVM虚机生命周期管理](#1.3.3 KVM虚机生命周期管理)
      • [1.4 KVM虚拟化web管理端](#1.4 KVM虚拟化web管理端)
        • [1.4.1 webvirtualcloud部署](#1.4.1 webvirtualcloud部署)
        • [1.4.2 配置调整](#1.4.2 配置调整)
        • [1.4.3 虚拟机创建](#1.4.3 虚拟机创建)

1.1 云计算概述

1.1.1 什么是云计算?

在维基百科中是这样定义云计算的: 是一种基于互联网的计算方式, 通过这种方式, 共享的软硬件资源和信息可以按需求提供给计算机各种终端和其他设备;

以前要完成信息处理, 是需要在一个客观存在的计算机上完成的, 它看得见摸得到。后来随着计算机硬件、网络技术、存储技术的飞速发展, 计算机硬件性能过剩, 因为足够高的性能在大部分时间是被浪费掉的, 并没有参与客观运算; 那如果将资源集中起来, 计算任务去共享、复用集中起来的资源, 将是对资源的极大节省和效率的极大提升; 这就是云计算产生的背景, 它就是将庞大的计算资源集中在某个地方或是某些地方, 而不再是放在身边的计算机了, 用户的每一次计算, 都发生在那个被称为"☁️云"的地方

1.1.2 云计算的几种服务模型

云计算的模型是以服务为导向的, 根据提供的服务层次不同, 可分为:IaaS(Infrastructure as a Service, 基础架构即服务)、PaaS(Platform as a Service, 平台即服务)、SaaS(Software as a Service, 软件即服务)。它们提供的服务越来越抽象, 用户实际控制的范围也越来越小, 如图所示:

SaaS: 云服务提供商提供给客户直接使用软件服务, 如Google Docs、Microsoft CRM、Salesforce.com等。用户不必自己维护软件本身, 只管使用软件提供的服务。用户为该软件提供的服务付费

PaaS: 云服务提供商提供给客户开发、运维应用程序的运行环境, 用户负责维护自己的应用程序, 但并不掌控操作系统、硬件以及运作的网络基础架构。如aliyun的RDS-MySQL、RDS-Redis等。平台是指应用程序运行环境(图中的Runtime)。通常, 这类用户在云环境中运维的应用程序会再提供软件服务给他的下级客户。用户为自己的程序的运行环境付费

IaaS: 用户有更大的自主权, 能控制自己的操作系统、网络连接(虚拟的)、硬件(虚拟的)环境等, 云服务提供商提供的是一个虚拟的主机环境。如aliyun的ECS、腾讯的CMS等。用户为一个主机环境付费

1.2 虚拟化技术

1.2.1 什么是虚拟化

在维基百科中是这样定义虚拟化的: 在计算机领域, 虚拟化指创建某事物的虚拟版本, 包括虚拟的计算机硬件平台、存储设备以及计算机网络资源;

虚拟化是一种资源管理技术, 它将计算机的各种实体资源予以抽象和转化, 并提供分割、重新组合, 以达到最大化利用物理资源的目的; 广义上来说, 我们一直以来对物理硬盘所做的逻辑分区、以及后来的LVM, 都可以纳入虚拟化的范畴; 在没有虚拟化之前, 一个物理主机上面只能运行一个操作系统及其之上的一系列运行环境和应用程序, 有了虚拟化技术, 一个物理主机可以被抽象、分割成多个虚拟的逻辑意义上的主机, 向上支撑多个操作系统及其之上的运行环境和应用程序, 则其资源就可以被最大化的利用

如上图所示的Virtual Machine Monitor(VMM, 虚拟机监控器, 也称为Hypervisor)层, 就是为了达到虚拟化而引入的一个软件层。它向下掌控实际的物理资源(相当于原本的操作系统); 向上呈现给虚拟机N份逻辑的资源。为了做到这一点, 就需要将虚拟机对物理资源的访问"偷梁换柱"------截取并重定向, 让虚拟机误以为自己是在独享物理资源。虚拟机监控器运行的实际物理环境, 称为宿主机; 其上虚拟出来的逻辑主机, 称为客户机(Guest Machine)

1.2.2 半虚拟化和全虚拟化

最理想的虚拟化的两个目标如下:

  • 客户机完全不知道自己运行在虚拟化环境中, 还以为自己运行在原生环境里。

  • 完全不需要VMM介入客户机的运行过程。

++半虚拟化:++

纯软件的虚拟化可以做到第一个目标, 但性能不是很好, 而且软件设计的复杂度大大增加。

那么如果放弃第一个目标呢?让客户机意识到自己是运行在虚拟化环境里, 并做相应修改以配合VMM, 这就是半虚拟化(Para-Virtualization)。一方面, 可以提升性能和简化VMM软件复杂度;另一方面, 也不需要太依赖硬件虚拟化的支持, 从而使得其软件设计(至少是VMM这一侧)可以跨平台且是优雅的。"本质上, 准虚拟化弱化了对虚拟机特殊指令的被动截获要求, 将其转化成客户机操作系统的主动通知。但是, 准虚拟化需要修改客户机操作系统的源代码来实现主动通知。"典型的半虚拟化技术就是virtio, 使用virtio需要在宿主机/VMM和客户机里都相应地装上驱动。

++全虚拟化:++

与半虚拟化相反的, 全虚拟化(Full Virtualization)坚持第一个理想化目标:客户机的操作系统完全不需要改动。敏感指令在操作系统和硬件之间被VMM捕捉处理, 客户操作系统无须修改, 所有软件都能在虚拟机中运行。因此, 全虚拟化需要模拟出完整的、和物理平台一模一样的平台给客户机, 这在达到了第一个目标的同时也增加了虚拟化层(VMM)的复杂度。

性能上, 2005年硬件虚拟化兴起之前, 软件实现的全虚拟化完败于VMM和客户机操作系统协同运作的半虚拟化, 这种情况一直延续到2006年。之后以Intel VT-x、VT-d为代表的硬件虚拟化技术的兴起, 让由硬件虚拟化辅助的全虚拟化全面超过了半虚拟化。但是, 以virtio为代表的半虚拟化技术也一直在演进发展, 性能上只是略逊于全虚拟化, 加之其较少的平台依赖性, 依然受到广泛的欢迎。

1.3 KVM详解

1.3.1 KVM简介

KVM全称是Kernel-based Virtual Machine, 即基于内核的虚拟机, 是采用硬件虚拟化技术的全虚拟化解决方案

KVM最初是由Qumranet公司的Avi Kivity开发的, 作为他们的VDI产品的后台虚拟化解决方案。为了简化开发, Avi Kivity并没有选择从底层开始新写一个Hypervisor, 而是选择了基于Linux kernel, 通过加载模块使Linux kernel本身变成一个Hypervisor。2006年10月, 在先后完成了基本功能、动态迁移以及主要的性能优化之后, Qumranet正式对外宣布了KVM的诞生。同月, KVM模块的源代码被正式纳入Linux kernel, 成为内核源代码的一部分。它以内核模块的形式加载之后, 就将Linux内核变成了一个Hypervisor, 但硬件管理等还是通过Linux kernel来完成的

一个KVM客户机对应于一个Linux进程, 每个vCPU则是这个进程下的一个线程, 还有单独的处理IO的线程, 也在一个线程组内。所以, 宿主机上各个客户机是由宿主机内核像调度普通进程一样调度的, 即可以通过Linux的各种进程调度的手段来实现不同客户机的权限限定、优先级等功能。

客户机所看到的硬件设备是QEMU模拟出来的(不包括VT-d透传的设备), 当客户机对模拟设备进行操作时, 由QEMU截获并转换为对实际的物理设备(可能设置都不实际物理的存在)的驱动操作来完成

1.3.2 KVM虚机创建

由于KVM已经是kernel源代码的一部分, 所以不需要另外安装, 主要是安装QEMU 虚拟化工具; 这里安装不会进行过多介绍, 可以将安装所需要的库克隆到安装主机中即可; 项目地址: https://gitee.com/mirschao/kvmvirtual

bash 复制代码
$ git clone https://gitee.com/mirschao/kvmvirtual.git
$ bash kvmvirtual/installer/deploy.sh

KVM中支持三种网络模式, 分别为NAT模式、bridge桥接模式、host-only仅主机模式; NAT模式通常用来在个人虚拟化桌面中应用广泛, 桥接模式在服务器端虚拟化使用广泛, host-only一般在超级大的服务厂商内部使用; 本课程中的重点内容是桥接网络;

在创建虚拟机之前需要先将网络配置搞定, 由于公司/IDC机房中网络大多采用 255.255.0.0 为掩码的网段划分, 所以为了保证不同宿主机中的虚拟机能够正常通信, 此处采用 桥接 模式网络;

bash 复制代码
$ vim /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE="br0"
NAME="br0"
BOOTPROTO="static"
ONBOOT="yes"
TYPE="Bridge"
IPADDR="x.x.x.x"
GATEWAY="x.x.x.1"
NETMASK="255.255.0.0"
DNS1="8.8.8.8"
DEFROUTE="yes"

$ vim /etc/sysconfig/network-scripts/ifcfg-ens33
DEVICE="ens33"
NAME="ens33"
BOOTPROTO="none"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
BRIDGE="br0"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="yes"

$ systemctl restart network

基础环境部署完成后, 就是创建模版虚拟机的阶段了, 新创建的KVM宿主机中是没有虚拟机的, 要想创建虚拟机需要使用 virt-install 工具进行虚拟机的创建; 模版虚拟机创建分为四步: 创建磁盘 -> 安装操作系统 -> 初始化模版机 -> 配置相关agent

bash 复制代码
$ qemu-img create -f raw /kvm/vdisks/template.raw 40G

$ virt-install --name=template \
 --vcpus=2 --memory=2048 --disk=/kvm/vdisks/template.raw \
 --cdrom=/kvm/isos/CentOS-7-x86_64-Minimal-2009.iso --os-variant=rhel7 \
 --noautoconsole --autostart \
 --network bridge=br0 \
 --graphics vnc,listen=0.0.0.0,port=5900

模版主机创建成功后, 需要在机器中内置好, 监控agent、堡垒机注册程序、创建虚拟机时固定IP地址, 满足以上三点设置的话, 就需要良好的设计逻辑, 从镜像、脚本、系统三层配合实现;

bash 复制代码
$ cp kvmvirtual/virtual_create/createvm.sh /usr/local/bin/createvm
$ chmod a+x /usr/local/bin/createvm

要想在虚拟机被创建时, 自动的注册到对应的jumpserver中, 需要提前明确jumpserver的url地址、特权用户的id、永久有效的token三项内容, 从而在虚拟机启动的过程中通过 /etc/rc.local.d/registry_to_jumper.py 向jumpserver注册; 但值得说明的一点是下方脚本需要python3的开发环境;

bash 复制代码
1. 创建出jumpserver堡垒机平台 https://jumpserver.org -> 文档 -> 安装部署 -> 一键部署

2. 在模版主机中, 创建特权用户、对特权用户设置密码、将特权用户设置为sudo免密; 安装python3的环境包; 将jumpserver注册脚本中的信息进行修改; 对/etc/rc.d/rc.local文件增加执行权限

3. 开始测试jumpserver的注册功能
python 复制代码
$ sed -i -e 's/JUMPERURL/192.168.121.14/g' \
      -e 's/JUMPERADMINID/a2d36c60-3ba6-4d24-b059-2b8783d75446/g' \
      -e 's/JUMPERPTOKEN/9176612fb2277801314b97f416d32912db765cea/g' \
      kvmvirtual/virtual_create/registry_to_jumper.py
$ cp kvmvirtual/virtual_create/registry_to_jumper.py /tasks/registry_to_jumper.py
$ echo "python3 /tasks/registry_to_jumper.py" >>/etc/rc.d/rc.local
$ chmod a+x /etc/rc.d/rc.local

在模版主机中, 安装好zabbix-agent, 并配置agent配置文件指向对应的zabbix-server; 设置好开机自启动, 在新建的虚拟机启动时, 会自动向zabbix-server注册监控;

bash 复制代码
$ sed -i 's/SERVERIP/x.y.z.n/' kvmvirtual/virtual_create/deploy_zabbix_agent.sh
$ bash kvmvirtual/virtual_create/deploy_zabbix_agent.sh
1.3.3 KVM虚机生命周期管理

对于虚拟化层之上的虚拟机是具备生命周期的进程, 对于进程而言就会具备运行、重启、停止等基本生命周期, 由于其进程的特殊性还会有cpu、内存、磁盘的添加和移除以及快照、克隆等操作; 以上所提到的所有操作都需要使用libvirtd包中所包含的 virsh 指令;

bash 复制代码
#> 关机指令
$ virsh shutdown VMACHINE_NAME

#> 断电指令
$ virsh destroy VMACHINE_NAME

#> 开机指令
$ virsh start VMACHINE_NAME

#> 重启指令
$ virsh reboot VMACHINE_NAME

#> 连接指令
$ virsh console VMACHINE_NAME
Connected to domain VMACHINE_NAME
Escape character is ^]

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

localhost login: root
Password: 
Last login: Wed Jun 14 17:06:02 on ttyS0
[root@VMACHINE_NAME ~]# 

##> [ERROR CHECK]如果console连接卡住不动, 则通过vnc进入到对应的虚拟机中在以下文件中添加内容
$ cat /etc/securetty | tail -n 1
ttyS0

$ [root@ungeolinux ~]# cat /etc/grub2.cfg | grep ttyS0
linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet console=ttyS0

将虚拟机的cpu、memory、disk进行调整, 模拟公有云中的服务器, 可以对cpu、内存以及磁盘进行调整, 依据于此来完成对虚拟机配置的调整;

bash 复制代码
#> cpu及memory的调整(须关机调整)
$ virsh edit VIRTUAL_MACHINES_NAME
<domain type='kvm'>
  <name>VIRTUAL_MACHINES_NAME</name>
  <uuid>752b7fc7-3446-40d3-9868-d46acf9a8b78</uuid>
  <memory unit='KiB'>16777216</memory>
  <currentMemory unit='KiB'>16777216</currentMemory>
  <vcpu placement='static'>4</vcpu>
  <os>
    <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
    <boot dev='hd'/>
  </os>
  ......
  ......
  ......

#> disk磁盘增加
$ qemu-img create -f [raw/qcow2] /kvm/vdisks/VMACHINE_NAME_DATA_NUMBER.[raw/qcow2] size
$ virsh attach-disk VMACHINE_NAME /kvm/vdisks/VMACHINE_NAME_DATA_NUMBER.[raw/qcow2] vdx
$ virsh edit VMACHINE_NAME
......
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/ROOT/kvm/images/k8s-master-01.qcow2'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw/qcow2'/>
      <source file='/kvm/vdisks/VMACHINE_NAME.raw/qcow2'/>
      <target dev='vdx' bus='virtio'/>
    </disk>
......
#> disk磁盘移除
$ virsh detach-disk VMACHINE_NAME vdx

生产中对虚拟机进行配置以及相关重大变更的时候, 通常需要对虚拟机进行快照的创建; 以及在业务激素扩容的过程中, 将已存在的且符合生产要求的虚拟机进行克隆, 可以最快速的增加服务负载;

bash 复制代码
#> 快照的创建 -> 恢复 -> 删除
$ virsh snapshot-create-as VMACHINE_NAME VMACHINE_NAME-snapshot-$(date +%Y%m%d%H%M%S)
$ vrish snapshot-revert VMACHINE_NAME VMACHINE_NAME-snapshot-xxxxxxxxxxxxxx
$ virsh snapshot-delete VMACHINE_NAME VMACHINE_NAME-snapshot-xxxxxxxxxxxxxx

#> 克隆(需要对OLD_VMACHINE_NAME机器关机)
$ virt-clone -o OLD_VMACHINE_NAME -n NEW_VMACHINE_NAME -f /kvm/vdisks/NEW_VMACHINE_NAME.qcow2

通常情况下, 当宿主机需要生产维护or宕机灾难时, 需要我们快速的对其上的虚拟机进行迁移, 考虑到这种情况, 就需要在KVM环境实施之前将虚拟磁盘存储目录变更为NFS/GFS的集群文件系统, 让多台KVM宿主机均可访问同一个地方的虚拟磁盘, 这也方便了我们进行迁移操作; 当然宿主机与宿主机之间也要保证网络等基础环境资源的一致性, 相互之间也一定要做好免密认证;

bash 复制代码
$ virsh migrate --live hiops_test_migrate qemu+ssh://root@192.168.121.12/system --verbose --unsafe

1.4 KVM虚拟化web管理端

对于企业中大部分应用场景而言, 使用命令行控制虚拟机带来的人员技术成本门槛较高, 且不容易进行后续审计, 这时就需要一个可以支持多平台的管理工具囊括创建、迁移、快照、生命周期管理等基础操作, 来帮助系统运维人员对所有虚拟机进行管理; webvirtcloud就可以满足以上所述功能, 且采用web UI管理界面更好的支持全平台进行管理操作;

1.4.1 webvirtualcloud部署
bash 复制代码
$ cat /etc/redhat-release
CentOS Stream release 8

$ sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
$ systemctl disable --now firewalld

$ yum -y install epel-release
$ yum -y install python3-virtualenv python3-devel libvirt-devel glibc gcc \
    nginx supervisor python3-lxml git python3-libguestfs iproute-tc \
    cyrus-sasl-md5 python3-libguestfs

$ cd /srv/
$ git clone https://github.com/retspen/webvirtcloud && cd webvirtcloud
Cloning into 'webvirtcloud'...
remote: Enumerating objects: 8955, done.
remote: Counting objects: 100% (927/927), done.
remote: Compressing objects: 100% (457/457), done.
remote: Total 8955 (delta 474), reused 864 (delta 451), pack-reused 8028
Receiving objects: 100% (8955/8955), 8.25 MiB | 649.00 KiB/s, done.
Resolving deltas: 100% (5965/5965), done.

$ pip3 install -i https://mirrors.ustc.edu.cn/pypi/web/simple pip -U
$ pip config set global.index-url https://mirrors.ustc.edu.cn/pypi/web/simple
$ pip install -U setuptools virtualenv

$ cp webvirtcloud/settings.py.template webvirtcloud/settings.py
$ virtualenv -p $(which python3) /srv/envs/webvirtcloud
$ source /srv/envs/webvirtcloud/bin/activate
(webvirtcloud) $ python /srv/webvirtcloud/conf/runit/secret_generator.py
X^*tIo&S|GhwygIp3}X)qs{wkcAy=vay~.%4^kU#,iKZs*\`&V
$ vim /srv/webvirtcloud/webvirtcloud/settings.py
SECRET_KEY = "X^*tIo&S|GhwygIp3}X)qs{wkcAy=vay~.%4^kU#,iKZs*\`&V"

$ cd /srv/webvirtcloud/
$ pip install -r conf/requirements.txt
$ python manage.py makemigrations
$ python manage.py migrate

$ vim /etc/supervisord.d/webvirtcloud.ini
[program:webvirtcloud]
command=/srv/envs/webvirtcloud/bin/gunicorn webvirtcloud.wsgi:application -c /srv/webvirtcloud/gunicorn.conf.py
directory=/srv/webvirtcloud
user=root
autostart=true
autorestart=true
redirect_stderr=true

[program:novncd]
command=/srv/envs/webvirtcloud/bin/python /srv/webvirtcloud/console/novncd
directory=/srv/webvirtcloud
user=root
autostart=true
autorestart=true
redirect_stderr=true

$ systemctl enable --now supervisord
$ supervisorctl reload
$ supervisorctl update
$ supervisorctl restart all
$ supervisorctl status
novncd                           RUNNING   pid 15774, uptime 0:00:06
webvirtcloud                     RUNNING   pid 15775, uptime 0:00:06

$ cp conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/
$ systemctl enable --now nginx
1.4.2 配置调整
bash 复制代码
#>>> 避免支持USB设备时报错
$ vim /srv/webvirtcloud/vrtManager/create.py
352			if "usb" in dom_caps["disk_bus"]:
353         xml += """<input type='mouse' bus='{}'/>""".format("virtio" if virtio else "usb")
354         xml += """<input type='keyboard' bus='{}'/>""".format("virtio" if virtio else "usb")
355         xml += """<input type='tablet' bus='{}'/>""".format("virtio" if virtio else "usb")
356     else:
357         xml += """<input type='mouse'/>"""
358         xml += """<input type='keyboard'/>"""
359         xml += """<input type='tablet'/>"""

>>> 修改为以下配置

352      if "usb" in dom_caps["disk_bus"]:
353          pass
354      else:
355          pass
1.4.3 虚拟机创建
  • 配置计算节点

  • 设置虚拟机模版

  • 创建虚拟机

相关推荐
weixin_6495556711 分钟前
C语言程序设计第四版(何钦铭、颜晖)第十一章指针进阶之奇数值结点链表
c语言·开发语言·链表
书到用时方恨少!26 分钟前
Python os 模块使用指南:系统交互的瑞士军刀
开发语言·python
我是大猴子27 分钟前
事务失效的几种情况以及是为什么(详解)
java·开发语言
武藤一雄1 小时前
C#:nameof 运算符全指南
开发语言·microsoft·c#·.net·.netcore
带娃的IT创业者1 小时前
WeClaw_40_系统监控与日志体系:多层次日志架构与Trace追踪
java·开发语言·python·架构·系统监控·日志系统·链路追踪
Y001112361 小时前
JDBC原理
java·开发语言·数据库·jdbc
wertyuytrewm2 小时前
Java 异常|Java Exceptions
java·开发语言
雪碧聊技术2 小时前
深入理解 Java GC:从“房间清洁工”到解决系统卡顿实战
java·开发语言
大鹏说大话2 小时前
Java并发编程核心:线程安全、synchronized与volatile的深度剖析
java·开发语言
JAVA+C语言2 小时前
Java IO 流
java·开发语言