淺談虛擬機、Docker和Hyper技術

操做系統

咱們知道:html

完整的操做系統=內核+apps

內核負責管理底層硬件資源,包括CPU、內存、磁盤等等,並向上爲apps提供系統調用接口,上層apps應用必須經過系統調用方式使用硬件資源,一般並不能直接訪問資源。apps就是用戶直接接觸的應用,好比命令行工具、圖形界面工具等(linux的圖形界面也是做爲可選應用之一,而不像windows是集成到內核中的)。同一個內核加上不一樣的apps,就構成了不一樣的操做系統發行版,好比ubuntu、rethat、android(固然內核一般針對不一樣的發行版會有修改)等等。所以咱們能夠認爲,不一樣的操做系統發行版本其實就是由應用apps構成的環境的差異(好比默認安裝的軟件以及連接庫、軟件包管理、圖形界面應用等等)。咱們把全部這些apps環境打成一個包,就能夠稱之爲鏡像。問題來了,假如咱們同時有多個apps環境,可否在同一個內核上運行呢?由於操做系統只負責提供服務,而並無論爲誰服務,所以同一個內核之上能夠同時運行多個apps環境。好比假設咱們如今有ubuntu和fedora的apps環境,即兩個發行版鏡像,分別位於/home/int32bit/ubuntu/home/int32bit/fedora,咱們最簡單的方式,採用chroot工具便可快速切換到指定的應用環境中,至關於同時有多個apps環境在運行。linux

容器技術

咱們以上經過chroot方式,好像就已經實現了容器的功能,但其實容器並無那麼簡單,工做其實還差得遠。首先要做爲雲資源管理還必須知足:android

1.資源隔離

由於雲計算本質就是集中資源再分配(社會主義),再分配過程就是資源的邏輯劃分,提供資源抽象的實現方式好比咱們熟悉的虛擬機等,咱們把資源抽象一次劃分稱爲單元。單元必須知足隔離性,包括用戶隔離(或者說權限隔離)進程隔離、網絡隔離、文件系統隔離等,即單元內部只能感知其內部的資源,而不能感知單元之外的資源(包括宿主資源以及其餘單元的資源)。git

2.資源控制

即爲單元分配資源量,能控制單元的資源最大使用量。單元不能使用超過度配的資源量。github

固然還包括其餘不少條件,本文主要基於這兩個基本條件進行研究。docker

顯然知足以上兩個條件,虛擬機是一種實現方式,這是由於:shell

  • 隔離毋容置疑,由於不一樣的虛擬機運行在不一樣的內核,虛擬機內部是一個獨立的隔離環境
  • hypervisor可以對虛擬機分配指定的資源

基於虛擬機快速構建應用環境好比vagrant等。ubuntu

可是虛擬機也帶來不少問題,好比:windows

  • 鏡像臃腫龐大,不只包括apps,還必須包括一個龐大的內核
  • 建立和啓動時間開銷大,不利於快速構建重組
  • 額外資源開銷大,部署密度小
  • 性能損耗
  • ...

有沒有其餘實現方式能符合以上兩個條件呢?容器技術即是另外一種實現方式。表面上和咱們使用chroot方式類似,即全部的容器實例內部的應用是直接運行在宿主機中,全部實例共享宿主機的內核,而虛擬機實例內部的進程是運行在GuestOS中。由以上原理可知,容器相對於虛擬機有以上好處:api

  • 鏡像體積更小,只包括應用以及所依賴的環境,沒有內核。
  • 建立和啓動快,不須要啓動GuestOS,應用啓動開銷基本就是應用自己啓動的時間開銷。
  • 無GuestOS,無hypervisor,無額外資源開銷,資源控制粒度更小,部署密度大。
  • 使用的是真實物理資源,所以不存在性能損耗。
  • 輕量級
  • ...

但如何實現資源隔離和控制呢?

1. 隔離性

主要經過內核提供namespace技術實現隔離性,如下參考酷殼:

Linux Namespace是Linux提供的一種內核級別環境隔離的方法。不知道你是否還記得很早之前的Unix有一個叫chroot的系統調用(經過修改根目錄把用戶jail到一個特定目錄下),chroot提供了一種簡單的隔離模式:chroot內部的文件系統沒法訪問外部的內容。Linux Namespace在此基礎上,提供了對UTS、IPC、mount、PID、network、User等的隔離機制。

Linux Namespace 有以下種類,官方文檔在這裏《Namespace in Operation》

分類 系統調用參數 相關內核版本
Mount namespaces CLONE_NEWNS Linux 2.4.19
UTS namespaces CLONE_NEWUTS Linux 2.6.19
IPC namespaces CLONE_NEWIPC Linux 2.6.19
PID namespaces CLONE_NEWPID Linux 2.6.24
Network namespaces CLONE_NEWNET 始於Linux 2.6.24 完成於 Linux 2.6.29
User namespaces CLONE_NEWUSER 始於 Linux 2.6.23 完成於 Linux 3.8)

由上表可知,經過Namespaces技術能夠實現隔離性,好比網絡隔離,咱們能夠經過sudo ip netns ls查看網絡命名空間,經過ip netns add NAME增長網絡命名等。

2.資源控制

內核實現了對進程組的資源控制,即Linux Control Group,簡稱cgoup,它能爲系統中運行進程組根據用戶自定義組分配資源。簡單來講,能夠實現把多個進程合成一個組,而後對這個組的資源進行控制,好比CPU使用時間,內存大小、網絡帶寬、磁盤讀寫等,linux把cgroup抽象成一個虛擬文件系統,能夠掛載到指定的目錄下,ubuntu14.04默認自動掛載在/sys/fs/cgroup下,用戶也能夠手動掛載,好比掛載memory子系統(子系統一類資源的控制,好比cpu、memory,blkio等)到/mnt下:

sudo mount  -t cgroup -o memory  memory /mnt

掛載後就能像查看文件同樣方便瀏覽進程組以及資源控制狀況,控制組並非孤立的,而是組織成樹狀結構構成進程組樹,控制組的子節點會繼承父節點。下面以memory子系統爲例,

ls /sys/fs/cgroup/memory/

輸出:

cgroup.clone_children  memory.kmem.failcnt                 memory.kmem.tcp.usage_in_bytes   memory.memsw.usage_in_bytes      memory.swappiness
cgroup.event_control   memory.kmem.limit_in_bytes          memory.kmem.usage_in_bytes       memory.move_charge_at_immigrate  memory.usage_in_bytes
cgroup.procs           memory.kmem.max_usage_in_bytes      memory.limit_in_bytes            memory.numa_stat                 memory.use_hierarchy
cgroup.sane_behavior   memory.kmem.slabinfo                memory.max_usage_in_bytes        memory.oom_control               notify_on_release
docker                 memory.kmem.tcp.failcnt             memory.memsw.failcnt             memory.pressure_level            release_agent
memory.failcnt         memory.kmem.tcp.limit_in_bytes      memory.memsw.limit_in_bytes      memory.soft_limit_in_bytes       tasks
memory.force_empty     memory.kmem.tcp.max_usage_in_bytes  memory.memsw.max_usage_in_bytes  memory.stat                      user

以上是根控制組的資源限制狀況,咱們以建立控制內存爲4MB的Docker容器爲例:

docker run  -m 4MB -d busybox ping localhost

返回id爲0532d4f4af67,自動會建立以docker實例id爲爲名的控制組,位於/sys/fs/cgroup/memory/docker/0532d4f4af67...,咱們查看該目錄下的memory.limit_in_bytes文件內容爲:

cat memory.limit_in_bytes
4194304

即最大的可以使用的內存爲4MB,正好是咱們啓動Docker所設定的。

由以上可知,容器實現了資源的隔離性以及控制性。容器的具體實現如LXC、LXD等。

Docker技術

Docker是PaaS提供商dotCloud開源的一個基於LXC的高級容器引擎,簡單說Docker提供了一個可以方便管理容器的工具。使用Docker可以:

  • 快速構建基於容器的分佈式應用
  • 具備容器的全部優勢
  • 提供原生的資源監控
  • ...

Docker與虛擬機原理對比:

Docker與虛擬機原理對比

因爲容器技術很早就有,Docker最核心的創新在於它的鏡像管理,所以有人說:

Docker = 容器 + Docker鏡像

Docker鏡像的創新之處在於使用了相似層次的文件系統AUFS,簡單說就是一個鏡像是由多個鏡像層層疊加的,從一個base鏡像中經過加入一些軟件構成一個新層的鏡像,依次構成最後的鏡像,如圖

Docker鏡像分層

知乎:docker的幾點疑問:

Image的分層,能夠想象成photoshop中不一樣的layer。每一層中包含特定的文件,當container運行時,這些疊加在一塊兒的層就構成了container的運行環境(包括相應的文件,運行庫等,不包括內核)。Image經過依賴的關係,來肯定整個鏡像內到底包含那些文件。以後的版本的docker,會推出squash的功能,把不一樣的層壓縮成爲一個,和Photoshop中合併層的感受差很少。
做者:Honglin Feng
連接:https://www.zhihu.com/question/25394149/answer/30671258
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

這樣的好處是:

  • 節省存儲空間 - 多個鏡像共享base image存儲
  • 節省網絡帶寬 - 拉取鏡像時,只須要拉取本地沒有的鏡像層,本地已經存在的能夠共享,避免屢次傳輸拷貝
  • 節省內存空間 - 多個實例可共享base image, 多個實例的進程命中緩存內容的概率大大增長。若是基於某個鏡像啓動一個虛擬機須要資源k,則啓動n個同一個鏡像的虛擬機須要佔用資源kn,但若是基於某個鏡像啓動一個Docker容器須要資源k,不管啓動多少個實例,資源都是k。
  • 維護升級方便 - 相比於 copy-on-write 類型的FS,base-image也是能夠掛載爲可writeable的,能夠經過更新base image而一次性更新其之上的container
  • 容許在不更改base-image的同時修改其目錄中的文件 - 全部寫操做都發生在最上層的writeable層中,這樣能夠大大增長base image能共享的文件內容。

使用容器技術,帶來了不少優勢,但同時也存在一些問題:

  • 隔離性相對虛擬機弱-因爲和宿主機共享內核,帶來很大的安全隱患,容易發生逃逸。
  • 若是某些應用須要特定的內核特性,使用容器不得不更換宿主機內核。
  • ...

更多關於AUFS參考酷殼:Docker基礎技術-AUFS

Hyper

上文提到容器也存在問題,而且Docker的核心創新在於鏡像管理,即:

Docker = 容器 + Docker鏡像

有人提出把容器替換成最初的hypervisor,即接下來介紹的Hyper,官方定義:

Hyper - a Hypervisor-based Containerization solution

Hyper = Hypervisor + Docker鏡像

Hyper是一個基於虛擬化技術(hypervisor)的Docker引擎。官方認爲

雖然Hyper一樣經過VM來運行Docker應用,但HyperVM裏並無GuestOS,相反的,一個HyperVM內部只有一個極簡的HyperKernel,以及要運行的Docker鏡像。這種Kernel+Image的"固態"組合使得HyperVM和Docker容器同樣,實現了Immutable Infrastructure的效果。藉助VM自然的隔離性,Hyper可以徹底避免LXC共享內核的安全隱患.

建立一個基於Hyper的ubuntu:

sudo hyper run -t ubuntu:latest bash

建立時間小於1秒,確實達到啓動容器的效率。
查看內核版本:

root@ubuntu-latest-7939453236:/# uname -a
Linux ubuntu-latest-7939453236 4.4.0-hyper+ #0 SMP Mon Jan 25 01:10:46 CST 2016 x86_64 x86_64 x86_64 GNU/Linux

宿主機內核版本:

$ uname  -a
Linux lenovo 3.13.0-77-generic #121-Ubuntu SMP Wed Jan 20 10:50:42 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

啓動基於Docker的ubuntu並查看內核版本:

$ docker run -t -i ubuntu:14.04 uname -a
Linux 73a88ca16d94 3.13.0-77-generic #121-Ubuntu SMP Wed Jan 20 10:50:42 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

咱們發現Docker和宿主機的內核版本是同樣的,即3.13.0-77-generic,而Hyper內核不同,版本爲4.4.0-hyper

如下爲官方數據

Hyper combines the best from both world: VM and Container.

- Container VM Hyper
Isolation Weak, shared kernel Strong, HW-enforced Strong, HW-enforced
Portable Yes, but kernel dependent sometimes No, hypervisor dependent Yes, hypervisor agnostic and portable image
Boot Fast, sub-second Slow, tens of seconds Fast, sub-second
Performance Great OK Good, minimal resource footprint and overhead
Immutable Yes No, configuration management required Yes, only kernel+image
Image Size Small, MBs Big, GBs Small, MBs
Compatibility No, need new tools Great, everything just works Good, it is still a "Machine", much less changes
Mature Not yet Production ready, SDN, SDS, LiveMigration, etc. Yes, just plug-&-play
ROI Rebuild everything with container - Reuse your virtual infrastructure

Hyper確實是容器和虛擬機的一種很好的折衷技術,將來可能前景廣大,但須要進一步觀察,我我的主要存在如下疑問:

  • 使用極簡的內核,會不會致使某些功能丟失?
  • 是否是須要爲每個應用維護一個微內核?
  • 有些應用須要特定內核,這些應用實際多麼?能夠經過其餘方式避免麼?
  • Hyper引擎可否提供和Docker引擎同樣的api,可否在生態圈中相互替代?
  • 隔離性增強的同時也犧牲了部分性能,這如何權衡?

總結

本文首先介紹了操做系統,而後引出容器技術以及虛擬機技術,最後介紹了Docker和Hyper技術。經過本文能夠清楚地對三者有了感性認識。 近年來容器技術以及微服務架構很是火熱,CaaS有取代傳統IaaS的勢頭,將來雲計算市場誰成爲主流值得期待。

相關文章
相關標籤/搜索