常常有朋友問我,你是作什麼的呢?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)。