常常有朋友问我,你是作什么的呢?html
我回答说,云计算。node
不回答还好,一回答,他们更加疑惑了。听着挺高大上,挺牛b的,就是不知道是什么。在大多数Pythonista的认知里,学会了Python,不从事爬虫,就是作Web开发,否则就是数据分析/挖掘,人工智能的。linux
想想,这也是合理的,大部分培训班为你让你交学费,通常都会把你的职业路线给规划好,什么Web开发,什么爬虫工程师,什么数据分析师等等,却没人告诉你,学会了Python,也能够去作一名云计算工程师(准确地说应该是OpenStack工程师,由于云计算涉及的范围更广,须要的技术栈更多,而不仅仅是一门编程语言)。ios
为了让你多了解一些云计算的内容,我想着写这么一篇文章,介绍一下我从事的领域,同时也对云计算和虚拟化这块入门级知识作一个梳理,若是恰好你也想进入这个领域,这份入门通识指南,应该挺适合你的。shell
维基百科上定义的云计算(英语:cloud computing),是一种基于互联网的计算方式,经过这种方式,共享的软硬件资源和信息能够按需求提供给计算机各类终端和其余设备。编程
枯燥的定义,听起来仍是不太好理解,我尝试用本身的语言来解释下。windows
计算,即计算资源,包括咱们熟悉的 CPU,内存,磁盘,带宽等。centos
云,就是将这些零散实体资源变成一个巨大无比的资源池子,有了这个池子,作为我的用户,你再也不须要本身你买一个电脑放在家里,作为小型公司,你不须要本身整一个机房,花不少的人力和设备成本去运营这些基础设施。一旦你须要,你就向池子拥有者申请便可。这极大的提升了资源的利用率,以及分配的灵活性。api
还有人说,云就像是天上的云同样,聚焦的水汽多了就会下雨,落到地面的雨水又会蒸发到天上,继续等待下一次下雨。云计算里的云,正如大天然里的云同样,能够实现资源的循环利用。你在公有云提供商那里,购买了一年的云主机,一年后资源被回收,能够再分配给其余人使用。bash
云计算的模型,是以服务为导向的。根据服务层次的不一样,能够分为三类:
以上三种模型,面向的群体各不相同,从上到下,用户的自主权愈来愈小,需关注的细节也愈来愈少。
另外根据部署方式的不一样,能够将云计算分为三类:公有云、私有云和混合云。
私有云由专供一个企业或组织使用的云计算资源构成。私有云可在物理上位于组织的现场数据中心,也可由第三方服务提供商托管。而混合云,就是两者皆有。
云计算,是为了提升资源的利用率,分配的灵活性而提出的一种解决方案。
而这个解决方案的底层,须要有技术支撑,目前主要是虚拟化技术和容器技术。
此次主要讲的是虚拟化。
你是否是又要蒙圈了,什么是虚拟化?
它是一种能够将计算机的实体资源(CPU,内存,存储,网络等)进行抽象转化,并提供分割,从新组合,以达到最大化利用资源的一种技术。
虚拟机使用过吧?
当你只有一个电脑装了windows系统,而你也想体验一下linux系统,若是不想折腾去装个双系统,最简单的方法就是用 VMWare 或者 VirtualBox 在你的电脑里用linux的镜像建立个虚拟机。
你有没有想过,这虚拟机是如何建立出来,怎么这么神奇,一台电脑上居然能够同时运行着两个操做系统。
其实你后建立的这个虚拟机只是原物理机上的一个进程而已。只不过它从外观上、使用上看起来和你原来宿主机上的系统没有什么区别。这个虚拟机里有本身的内存,cpu,磁盘,网卡,这些都依赖虚拟化技术才得以实现的。
在虚拟机内部,若是要使用物理机上设备,除了虚拟化技术让其能够间接地使用物理设备,也可使用设备的直通让虚拟机直接使用物理设备,这种直通技术,不须要通过VMM(虚拟机监控器,后面会介绍),因此性能会比虚拟化好。常见的有GPU直通。还有直通与虚拟化的结合,如SR-IOV,即单根IO虚拟化(Single-root I/O virtualization),将一个物理网卡(PF)虚拟化成多个虚拟网卡(VF),再将虚拟网卡直给挂给虚拟机使用。
VMM,一般叫作 Hypervisor(下面咱们也将以Hypervisor指代VMM),中文名:虚拟机监控器,英文全称:Virtual Machine Monitor。
Hypervisor 是为了实现虚拟化而引入的一个介于虚拟机操做系统和物理资源的软件层。
须要注意的是,Hypervisor并非一款具体的软件,而是一类软件的统称。
当虚拟机要对物理资源进行操做时,Hypervisor将对其指令进行截取而且重定向,让虚拟机无感知地像物理操做系统同样使用物理资源。
常见的Hypervisor,有
1. KVM
KVM(Kernel-based Virtual Machine),意思是基于内核的虚拟机。
KVM是集成到Linux内核的Hypervisor,是X86架构且硬件支持虚拟化技术(Intel VT或AMD-V)的Linux的全虚拟化解决方案。它是Linux的一个很小的模块,利用Linux作大量的事,如任务调度、内存管理与硬件设备交互等。
2. Xen
Xen是第一类运行在裸机上的虚拟化管理程序。它支持全虚拟化和半虚拟化,Xen支持hypervisor和虚拟机互相通信,并且提供在全部Linux版本上的免费产品,包括Red Hat Enterprise Linux和SUSE Linux Enterprise Server。Xen最重要的优点在于半虚拟化,此外未经修改的操做系统也能够直接在xen上运行(如Windows),能让虚拟机有效运行而不须要仿真,所以虚拟机能感知到hypervisor,而不须要模拟虚拟硬件,从而能实现高性能。
3. QEMU
QEMU是一套由Fabrice Bellard所编写的模拟处理器的自由软件。Qemu,其中关键字emu,全称emulator,模拟器,因此单纯使用qemu是采用的彻底虚拟化的模式。
那QEMU有什么用?它和KVM是什么关系呢?
准确来讲,KVM是Linux kernel的一个模块。能够用命令modprobe去加载KVM模块。加载了模块后,才能进一步经过其余工具建立虚拟机。
但仅有KVM模块是 远远不够的,KVM是最底层的hypervisor,它仅用来模拟CPU的运行,缺乏了对network和周边I/O的支持,因此咱们是无法直接用它的。
而QEMU-KVM就是一个完整的模拟器,它是基于KVM构建的,提供了完整的网络和I/O支持。
说到了QEMU,其实它也是一个虚拟化软件。做用是什么呢,它至关于一个路由器,当Guest OS的内核想要操做物理硬件时,必须先经由Qemu转发,将操做指令转给真实的硬件。因为全部的指令都要从Qemu里面过一手,于是性能比较差。
总结
4. libvirt
要解释libvirt是什么,只要知道为何会须要libvirt就行了。
这些都是在内核空间层作的事情,而咱们用户建立、销毁虚拟机都是在用户空间层操做,这就尴尬了,咱们没有权限。
这下该 libvirt 出场了,libvirt分为服务端各客户端。
服务端是libvirtd,而你所熟悉的virt,virt-install,virt-manager,virt-viewer 等都是libvirt的客户端。
目前,libvirt 已经成为使用最为普遍的对各类虚拟机进行管理的工具和应用程序接口(API),并且一些经常使用的虚拟机管理工具(如virsh、virt-install、virt-manager等)和云计算框架平台(如OpenStack、OpenNebula、Eucalyptus等)都在底层使用libvirt的应用程序接口。
根据客户机系统是否须要修改定制能够分为 全虚拟化 和 半虚拟化。
1. 全虚拟化
全虚拟化(英语:Full virtualization),是须要依托于硬件虚拟化的。
在全虚拟化模式下,虚拟机的全部操做(CPU,内存,网络等)都须要通过一个运行在物理机上的虚拟化软件转发给物理机内核。而这个虚拟化软件,在windows上你常见且熟悉的有vmware,virtualbox。
容许未经修改的客操做系统(英语:Guest OS)隔离运行。在全虚拟化环境中,任何能够运行在裸机上的软件(一般是操做系统)均可以未经修改地运行在虚拟机中。
表明:VMWare(1998年),KVM
2. 半虚拟化
半虚拟化(英语:Paravirtualization)是另外一种相似于全虚拟化的热门技术。
半虚拟化对比全虚拟化,就是有一些能够直接操做物理内核空间,而不须要所有通过虚拟化软件。这就大大提升了虚拟机的性能。
它在HOST上使用Hpervisor(虚拟机管理程序)提供便利的接口,使得Guest OS可以调用接口访问虚拟硬件。而条件是,Guest OS 内部须要部署安装相应的驱动和软件逻辑,须要对操做系统进行修改。
表明:Xen(2006)
根据虚拟化层是直接位于硬件之上仍是位于操做系统之上,能够分为 Type 1 虚拟化和 Type 2 虚拟化。
Type 1:Xen,VMWare ESX
Type 2:KVM,WMWare Workstation
1. 软件虚拟化
在硬件虚拟化出现以前,市场上都是使用的软件虚拟化。
软件虚拟化,就是经过软件来实现虚拟化,原理是把从虚拟机传来的操做指令进行截取翻译,并传递给真实的物理硬件。
因为每条指令都须要通过“截取” -> “翻译” -> “转发”,因此其虚拟化性能会差一点。
哪些属于虚拟化软件呢?
2. 硬件虚拟化
硬件虚拟化,是指计算机硬件自己提供能力让客户机指令独立运行,而不须要Hypervisor 截获重定向。直接从硬件层面开始支持虚拟化。由硬件支持并提供多个虚拟硬件设备接口,这些设备由虚拟机内核驱动传递给虚拟机使用。使用这种方式,虚拟机能得到和宿主机同样的硬件功能,性能也和宿主机相近,同时原生操做系统原本就支持这项技术,所以无需对操做系统进行修改。
Intel 从2005年开始在 x86 cpu 上支持硬件虚拟化,大大推动了虚拟化的发展。
缺点就是,硬件要支持虚拟化功能,在之前这多是缺点,可是如今随着虚拟化技术的发展,愈来愈多的硬件都已经支持虚拟化,成本也愈来愈低,因此硬件辅助虚拟化是目前最流行,使用最普遍的虚拟化技术。
KVM这种流行的虚拟化技术里,既有软件虚拟化,也有硬件虚拟化,软件虚拟化要基于硬件的虚拟化,两者是相辅的关系,而不是互斥。
有了虚拟化,就有了虚拟机,那如何对这些虚拟机进行管理呢。
在 Linux 下有许多的工具可使用:
Virsh:基于 libvirt 的 命令行工具 (CLI)
Virt-Manager:基于 libvirt 的 GUI 工具
virt-v2v:虚机格式迁移工具
virt-* 工具:包括 Virt-install (建立KVM虚机的命令行工具), Virt-viewer (链接到虚机屏幕的工具),Virt-clone(虚机克隆工具),virt-top 等
libguestfs-tools:一组 Linux 下的 C 语言的 API ,用来访问/修改虚拟机的磁盘映像文件。
虚拟机的本质是宿主机上的一个进程,当你用OpenStack在界面,或者使用virsg 建立了一个虚拟机时。你可使用ps -ef|grep kvm
看下这个虚拟机的进程,是下面这样子的。
参数多得让人头皮发麻。意思是,你可使用这样一串命令才能建立一台虚拟机。
$ /usr/libexec/qemu-kvm \
-name guest=instance-00000035, debug-threads=on \
-S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-216-instance-00000035/master-key.aes \
-machine pc-i440fx-rhel7.5.0,accel=kvm,usb=off,dump-guest-core=off \
-cpu host \
-m 16384 \
-realtime mlock=off \
-smp 2,maxcpus=32,sockets=2,cores=16,threads=1 \
-uuid 31d70882-194f-469b-855e-fcfa6736550d \
-smbios type=1,manufacturer=RDO,product=OpenStack Compute,version=0.0.1-1.el7.centos,serial=bc147bfe8a204d06a09f98387e46b890,uuid=31d70882-194f-469b-855e-fcfa6736550d,family=Virtual Machine \
-display none \
-no-user-config -nodefaults \
-chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-216-instance-00000035/monitor.sock,server,nowait \
-mon chardev=charmonitor,id=monitor,mode=control \
-rtc base=utc,driftfix=slew \
-global kvm-pit.lost_tick_policy=delay \
-no-hpet -no-shutdown -boot strict=on \
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/dev/hdd-volumes/31d70882-194f-469b-855e-fcfa6736550d_disk,format=raw,if=none,id=drive-virtio-disk0,cache=none,aio=native -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -drive file=/var/lib/nova/instances/31d70882-194f-469b-855e-fcfa6736550d/disk.config,format=raw,if=none,id=drive-ide0-0-0,readonly=on,cache=writeback \
-device ide-cd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
-netdev tap,fds=28:35,id=hostnet0,vhost=on,vhostfds=36:37 \
-device virtio-net-pci,mq=on,vectors=6,netdev=hostnet0,id=net0,mac=fa:16:3e:69:63:18,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=16,max_outputs=1,bus=pci.0,addr=0x2 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 -msg timestamp=on
复制代码
前面咱们看到,建立一台虚拟机须要诸多的参数。
若是一个一个去指定,很是不易于管理及复用。
若是能够在建立时,指定一个配置文件,这个配置文件里包含上述全部的参数,不就大大简化了虚拟机建立过程。
这时候就出现了virsh这个基于 libvirt 的 命令行工具 (CLI)。经过它咱们能够指定一个 xml 配置文件来很轻松的建立一台虚拟机。
virsh define vm.xml
virsh start guest_vm
复制代码
其中xml的内容以下
<domain type='kvm' id='200'>
<name>guest_vm</name>
<memory unit='KiB'>12582912</memory>
<currentMemory unit='KiB'>12582912</currentMemory>
<vcpu placement='static'>6</vcpu>
<numatune>
<memory mode='strict' nodeset='0-1'/>
<memnode cellid='0' mode='strict' nodeset='0'/>
<memnode cellid='1' mode='strict' nodeset='1'/>
</numatune>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
<boot dev='hd'/>
<boot dev='cdrom'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<clock offset='utc'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/path/to/test.qcow2'/>
<backingStore/>
<target dev='hda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
</disk>
<controller type='pci' index='0' model='pci-root'>
<alias name='pci.0'/>
</controller>
<controller type='ide' index='0'>
<alias name='ide'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='virtio-serial' index='0'>
<alias name='virtio-serial0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</controller>
<controller type='usb' index='0' model='piix3-uhci'>
<alias name='usb'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<interface type='bridge'>
<mac address='52:54:00:d2:81:b0'/>
<source bridge='br0-ovs'/>
<virtualport type='openvswitch'>
<parameters interfaceid='abc10709-ebff-4d0f-8761-4b7fdaba0dc0'/>
</virtualport>
<target dev='vnet0'/>
<model type='virtio'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<interface type='bridge'>
<mac address='52:54:00:5e:91:38'/>
<source bridge='br0-ovs'/>
<virtualport type='openvswitch'>
<parameters interfaceid='cceb5703-185a-4f6f-b2ce-a7e273e52bdc'/>
</virtualport>
<bandwidth>
<inbound average='50000'/>
<outbound average='50000'/>
</bandwidth>
<target dev='vnet1'/>
<model type='virtio'/>
<alias name='net1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</interface>
<interface type='bridge'>
<mac address='52:54:00:b2:77:07'/>
<source bridge='br0-ovs'/>
<virtualport type='openvswitch'>
<parameters interfaceid='674716ab-243d-4137-bc01-aa2c33cca21a'/>
</virtualport>
<target dev='vnet6'/>
<model type='virtio'/>
<alias name='net2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</interface>
<console type='pty' tty='/dev/pts/4'>
<source path='/dev/pts/4'/>
<target type='virtio' port='0'/>
<alias name='console0'/>
</console>
<input type='mouse' bus='ps2'>
<alias name='input0'/>
</input>
<input type='keyboard' bus='ps2'>
<alias name='input1'/>
</input>
<sound model='ich6'>
<alias name='sound0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</memballoon>
</devices>
<seclabel type='dynamic' model='dac' relabel='yes'>
<label>+0:+0</label>
<imagelabel>+0:+0</imagelabel>
</seclabel>
</domain>
复制代码
使用 virsh 来指定xml进行建立虽然能对虚拟机进行生命周期的管理,可是没法对成百上千台的机器进行集中式的管理。
这时候,OpenStack 这个开源的云计算管理平台就出现了。
有了OpenStack,你可使用 Horizon提供的界面进行虚拟机的管理
也可使用nova 的 cli 命令进行建立。
nova boot <vm_name> \
--flavor <flavor_id> \
--nic net-id=<net_id>,v4-fixed-ip=<ip> \
--image <image_id/name> \
--config-drive True
复制代码
说了半天,线于引出了OpenStack,个人工做基本60%的时间都是围绕着它转,OpenStack 是一个开源框架,是使用Python语言开发的最大的项目,具说有数百万行的代码量,是动态语言的一个优秀典范。
关于 OpenStck,你可能不太明白它是作什么的。这里引用我昨天看到的另外一篇文章的一个说明:它有点像一个商店,负责管理全部的商品(计算资源、存储资源、网络资源等),卖给用户,可是它自己不制造商品(不具有虚拟化能力),它的商品来自KVM(固然也能够用Xen等其余Hypervisor)。