Docker及其相關技術

什麼是Docker

容器技術中,咱們講到了Docker就是一個應用容器引擎,能夠將應用及依賴打包,而後發佈到Linux上。相對於虛擬機,它開銷更小,並且還有必定的隔離性。
image.pnghtml

image.png

Docker基本概念

鏡像image

相似於虛擬機鏡像,是一個只讀的模板,能夠經過它來建立Container。linux

一個鏡像包含操做系統+軟件運行環境+用戶程序。docker

Docker中的鏡像最大的特色在於它們是分層的。以下圖,apache

image.png

每一層就是一個iMage,多個鏡像又能夠打包爲一個image(各個鏡像經過鏈表相連),只有最上層是可寫的,其餘的都只能讀。安全

這樣的好處能夠複用大量的鏡像,便於分發和存儲。並且底層的鏡像是隻讀的,因此容器中的進程沒法對他們進行修改,安全性獲得保證。服務器

Container

容器就是經過鏡像建立的一個實例,也就是運行着的鏡像。每一個容器都是獨立的進程,多個容器之間共享內核,容器沒有IP地址,是一個封閉的沙箱網絡

容器是一個動態的環境,而鏡像文件屬於靜態內容,因此還須要有一個JSON文件來記錄鏡像與容器之間的關係。架構

image.png

Docker架構

介紹了Docker鏡像和容器的概念之後,咱們來看一下怎麼樣將鏡像轉換爲容器實例的。框架

服務器安裝了Docker之後,就會在後臺跑一個Docker daemon後臺程序,用戶不能直接和守護進程打交道,可是能夠經過Docker Client 與其進行交互。運維

Docker Daemon會監聽Docker Client發過來的指令,並進行docker鏡像下載,運行容器等核心操做。

若是本地有鏡像,就直接從本地拉取,若是本地沒有,就會到遠端的倉庫裏面(Docker Hub)裏面去找。Docker Hub將全世界的Docker數據匯聚在一塊兒,是Docker生態的命脈。這也是Docker發展這麼快的重要緣由,由於Docker的技術很容易複製,可是Docker Hub匯聚了全球的數據可複製性幾乎不存在。

image.png

image.png

Docker 的核心技術

Docker 的出現由於開發和運維階段須要一種虛擬化技術解決開發環境和生產環境環境一致的問題,以及資源隔離的問題。

接下來會介紹幾種 Docker 使用的核心技術,若是咱們瞭解它們的使用方法和原理,就能清楚 Docker 的實現原理

image.png

NameSpaces

咱們知道,在一臺Linux主機上運行多個進程其實是會相互影響的,每個進程其實能夠看到另外的進程,也能夠訪問任意的文件。

image.png
風險就在於一個進程被攻入,則入侵者能夠訪問當前服務器的全部服務與文件。這也是咱們以前要引入虛擬機來提升資源利用率的關鍵,由於咱們要保證資源利用率提高的時候,還要保證安全性。

可是虛擬機畢竟過重了,而Docker其實就經過Linux的NameSpaces來實現不一樣容器的隔離。
image.png

使用了Linux 的命名空間實現進程的隔離,它可使Docker 容器內部的任意進程都對宿主機器的進程一無所知。咱們每次運行 docker run 時,都會建立一個用於設置進程間隔離的實例

因此命名空間是Linux自帶的,能夠分離資源的一種方法,它能夠在建立進程的時候,設置新進程於其餘進程之間的隔離、網絡隔離、文件系統隔離。

上面只實現了進程的隔離,一樣使用命名空間能夠建立隔離的網絡環境,保證容器之間的網絡隔離,可是還不妨礙每一個容器訪問外部的網絡。

除了網絡隔離以及進程的隔離以外,咱們還但願容器中的進程不能訪問主機上的其餘目錄,因此若是一個容器須要啓動,那麼它須要提供一個新根文件系統(rootfs)

這樣每一個容器都有本身單獨的命名空間,運行在其上的應用就像在獨立的操做系統上同樣,彼此不影響。

CGroups

經過命名空間,咱們能夠爲新的進程隔離

  • 文件系統
  • 網絡
  • 進程的隔離

可是命名空間不能隔離物理資源,好比CPU和內存。
image.png

若是某個容器在執行CPU密集型任務,那麼勢必會影響其餘容器的任務的執行。因此咱們引入了CGroups(Control Groups)控制組這種控制機制,主要用於隔離主機上的物理資源。一樣這種機制也是由Linux 內核提供的。它將進程管理從 cpuset 中剝離出來

Cgroup能夠將任意進程進行分組化管理,它提供一個CGroup虛擬文件系統,做爲用戶接口,要使用CGoup必須掛載這種文件系統。

啓動一個容器時,Docker 會爲這個容器建立一個與容器標識符相同的 CGroup,在當前的主機上 CGroup 就會有如下的層級關係:

image.png

每一個Cgroup下面都有一個tasks文件,存儲着當前CGroup中進程的pid,若是系統管理員控制某個容器的資源消耗,只須要改變文件中的內容便可。

UnionFS(聯合文件系統)

經過Linux的命名空間能夠解決進程、網絡、文件系統隔離的問題,經過控制組能夠實現CPU、內存的隔離。那麼如何對應用所需的依賴以及代碼進行打包呢?經過鏡像。鏡像本質上就是一個壓縮包,也就是一個文件而已。

咱們以前說過Docker中鏡像是分層的,每個鏡像是由一系列只讀的層組成的,這也符合咱們的認知,打包好的東西固然不容許隨便修改。

可是咱們要在鏡像的基礎上建立新的鏡像,若是不能修改豈不是很尷尬,實際上能夠在原有的鏡像上建立新的邏輯層,每一層都是對當前容器一個小的修改而已。

以下圖所示,新建的層是可讀可寫的。
image.png

容器和鏡像的區別就在於,全部的鏡像都是隻讀的,而每個容器其實等於鏡像加上一個可讀寫的層,也就是同一個鏡像能夠對應多個容器。

這種鏡像層共享的方式,能夠減小磁盤的佔用。

image.png

咱們知道鏡像其實就是一種文件,對鏡像的每一次修改均可以作爲一層疊加在原有的鏡像之上,每一層都是對當前容器一個小的修改而已。這些新增的層級與原有的鏡像經過鏈表的形式相連,而後掛載在同一個虛擬文件系統下,這就是所謂的聯合文件系統(Union FS)

由於基礎的鏡像是沒有修改的,是被全部的容器共享的,容器管理的只有本身改動之後的層,大大提升了存儲效率。

AUFS

UnionFS 其實就是把多個文件系統(容器)聯合到同一個掛載點(鏡像)的服務,而AUFS(AnotherUnionFS)是它的升級版,它能夠將不一樣的目錄掛載在同一個虛擬文件系統下。


每個鏡像層都是創建在另外一個鏡像層之上的,同時全部的鏡像層都是隻讀的,只有每一個容器最頂層的容器層才能夠被用戶直接讀寫。

image.png

全部的容器都創建在一些底層服務(Kernel)上,包括命名空間、控制組、rootfs 等等,這種組裝方式提供了很是大的靈活性

image.png

LXC(Linux Container)

LXC能夠提供操做系統層級的虛擬化,並且由於是共享內核的,執行時不須要重複加載內核,啓動速度很是快,內存消耗更小。

它能夠經過NameSpaces和Cgroup機制能夠用來創建和管理Container。它最大的優點就是整合入了內核。

Docker就是在LXC的基礎上進行了標準化,它提供了標準的打包方案。好比對Apache的相關環境進行打包,最底層是基礎的根目錄image,而後疊加apache以及相關依賴,這些鏡像由AUFS文件系統加載併合並在統一的路徑中,它們都是隻讀。

爲了使容器中的進程能對鏡像進行修改,須要再疊加一層可寫的空白Layer。這樣,經過層級化的image,不一樣的Docker共用底層文件系統、依賴工具。

image.png

Dockerfile是怎麼把鏡像變成容器的?

簡單來說,Dockerfile構建出Docker鏡像,經過Docker鏡像運行Docker容器。它們分別表明軟件開發、交付標準、部署和運維的三個階段。

以下圖所示,經過Dockerfile能夠構建出一個新鏡像。可是鏡像畢竟是靜止的。那怎麼運行起來,也就是怎麼把鏡像變成一個進程的呢?

image.png

鏡像變容器依據的就是每一個鏡像的JSON文件,經過解析它就知道了鏡像之上應運行什麼進程,配置什麼樣的環境變量。

那麼誰來執行鏡像變容器的操做呢?前面已經說過經過Daemon守護進程便可實現。因此Docker容器實質就是一個進程,其父進程就是Docker的守護進程。守護進程 手握Docker鏡像JSON文件,爲容器配置相應的環境,並真正運行Docker鏡像所指定的進程,完成Docker容器的真正建立。而後JSON文件就失去做用了,此時鏡像就只是爲容器提供文件系統,供容器內部進程訪問。

那麼容器內部的進程會對Docker鏡像進行篡改嗎?固然不會,由於鏡像層是隻讀的,因此寫操做沒法做用到鏡像中。Daemon進程會在Docker鏡像最上層之上,再加一個可讀寫層,那麼若是容器要寫底層鏡像中的文件怎麼辦?可使用Copy on Write的方法,也就是說寫以前先複製到可讀寫層,而後再對這個副本進行寫。

總之,對容器進程而言,它只能看到最上層的文件

image.png

Docker究竟是什麼

講了這麼多技術的東西,咱們回過頭來看Docker究竟是什麼。不少人喜歡用集裝箱來比喻Docker。集裝箱來能解決什麼問題?就是能夠把貨物規範化的擺放,並且集裝箱和集裝箱之間不會互相影響。

在集裝箱以前,貨物運輸是沒有統一標準的,因此若是一個貨物在鐵路、公路、海運等多種不一樣運輸方式之間切換的時候,會消耗大量的人力和物力。對應開發和部署來講,有可能程序是在Ubuntu上開發,可是要在CentOS上運行,可能會出現各類亂七八糟的問題。

出現了集裝箱之後,全部的貨物能夠放到統一的箱子(容器)裏面,而後中轉工做由機械搞定(自動化),效率大大提高。

那麼這種改變最重要的就在與標準化

由於規範了集裝箱的大小,因此才能夠在鐵路、公路、海運上自由的切換,自動化工具纔有做用。按照這個思路Docker其實就和集裝箱同樣,開發工程師能夠把開發程序放到「集裝箱」裏面,而後運維人員使用標準化的操做工具去操做。

實際上Docker的發明人根據本身運維PaaS平臺的經驗,對DevOps工做各個階段的進行標準化,將系統底層的cgroup,namespace,aufs等技術集成在鏡像的發佈工具中。

那麼Docker的實質是什麼?就是針對PaaS平臺的自動化運維工具,而自動化運維的前提固然就是標準化,只有標準化了之後才能用腳本進行自動化部署。
那Docker在標準化上是怎麼作的?

  • 標準化文件:定義一系列軟件版本內容。dockerfile就是文檔,並且能夠用來產生鏡像,若是要修改docker鏡像中的環境,先修改dockerfile,這樣就保證了文檔和環境是一致的
  • 統一應用的操做:docker使用docker start做爲統一標準,而不是本身定義啓動腳本,對啓動環境的進程作標準化

可是Docker真的是萬能的嗎?真的能夠解決一切問題?真不是。即便是集裝箱,也沒法解決一切的運輸問題。

因此對任何技術都要辯證的來看。Docker最重要的是標準化,可是如今的雲計算環境裏面羣雄逐鹿,很難說能統一出一個標準。只有等此行業被某幾個大的雲計算廠商瓜分完畢纔可能。由於對用戶而言,他爲了業務的穩定性,可能租用了若干雲計算廠商的雲,他但願一套代碼能夠在各處運行,天然但願雲的環境標準一致。

image.png

Docker , OpenStack , K8s,Mesos對比

Openstack一直在構建開放、私有的上雲的架構,可是由於各家都作各家的,實踐不少,可是沒有定下來業界標準,並且複雜、沒解決業務問題。

13年,Docker異軍突起,橫掃DevOps運維圈,可是應用到平常的業務事務時卻有各類問題。因此Google振臂一呼,推出了Kubernetes,基於容器的集羣管理平臺,把這個矛盾轉成成動力,這個時候開始進入實踐期。

Mesos是Apache的頂級開源項目,是最開發的二級資源調度開發Kernel,經過定製上面的編排工具,能夠快速定製一套自家的PaaS解決方案,很是受開發者喜歡。

Mesos是製做分佈式系統最佳的基礎組件平臺。

Docker與OpenStack的區別

  • OpenStack:雲計算管理平臺,主要管理的對象是虛擬機和物理機,固然也能夠管理存儲和網絡,可是仍是以機器爲中心的。OpenStack 主要針對 Iaas 平臺,

  • Docker Engine 主要是用來建立和管理容器的,它和容器的關係就比如KVM與虛擬機的關係,Docker engine自己的定位不只僅在於單機上容器的管理,因此如今被加入了各類高級功能,如Docker集羣,容器編排、服務發現等。Docker主要針對 Paas 平臺,是以應用爲中心。

image.png

Kubernetes與Docker

Kubernetes(K8S)主要用於管理容器,相似於Openstack與虛擬機的關係,因此K8s通常與Docker配合使用,調用每一個節點上的Docker去建立和管理容器。

Mesos

Mesos:是一個通用資源管理平臺,管理的是各類計算資源(CPU,內存,GPU ),它會蒐集各節點的計算資源提供而後提供給上層的應用框架(Spark,Kubernetes)等。

Mesos也對容器進行深層次的支持,完整的運行了一個容器的運行時(相似Docker),因此能夠把計算任務以容器的方式在集羣中運行。
缺點是門檻高,須要自行編寫代碼進行調用,與K8s相比,更爲靈活,由於不限定是否徹底以容器來運行。

Kubernetes 是面向應用的 PaaS 層,Mesos 也偏向資源管理,但 Mesos 框架設計不錯,基於它很容易構建 PaaS。

Kubernetes 的強項在於容器編排,能夠很好解決應用上雲的問題。Kubernetes 能夠運行在 OpenStack 上

Mesos 牛叉在於數據中心資源統一管理,能夠爲多個框架分配資源,但不負責調度,可視爲分佈式操做系統內核,也能夠部署在 OpenStack 上,也支持物理資源。

若是隻用容器,Kubernetes 是不二之選;若是是運行的不只僅是容器化的應用,Mesos 配合 Marathon 調度框架甚至 Kubernetes 都不錯。

image.png

參考

相關文章
相關標籤/搜索