【我的Linux,我做主!】Docker容器技術基礎入門

今天Docker容器技術已經非常普及了,其中容器是一種基礎工具,泛指任何可以用於容納其它物品的工具,可以部分或完全封閉,被用於容納、存儲、運輸物品;物體可以被放置在容器中,而容器則可以保護內容物,人類使用容器的歷史至少有十萬年,甚至可能有數百萬年的歷史。
(1)虛擬化技術類型
我們在虛擬化的技術當中,目前虛擬化的常見形式有兩種。第一種我們稱之爲主機級虛擬化,虛擬的是整個完整的硬件平臺,例如我們常用的VMware Workstation就可以讓我們自由的在平臺上安裝操作系統,安裝的操作系統甚至和我們底層的宿主機可以是不同的操作系統。其中主機級虛擬化有兩種實現形式,Type-I型的虛擬化技術是直接在硬件平臺上裝一個Hyper Banner,在硬件之上不用再安裝宿主機操作系統,而在Hyper Banner之上直接安裝虛擬機,也就意味着沒有操作系統直接跑在硬件之上,所有操作系統都是在虛擬機內部;針對Type-II型的虛擬化首先我們會有宿主機,在宿主機設備上會安裝主機操作系統,在宿主機之上會安裝VMM即虛擬機管理器,在軟件之上會創建一個個的虛擬機。
對於主機級虛擬化,我們發現如果一個進程需要調度,首先它需要虛擬機之上的內核進行調度、磁盤IO管理等,虛擬機本身也是被宿主機內核管理的抽象層而已,因此我們運行的進程還會被宿主機的Hyper Banner管理一次,這中間資源的額外開銷也就不言而喻了,因此傳統的主機虛擬化技術的確能夠讓一組硬件環境在跨系統環境的資源隔離、調試等可以高效應用,但是對我們資源的消耗也是不容忽視的。
【我的Linux,我做主!】Docker容器技術基礎入門
第二種我們稱之爲容器級虛擬化,首先我們有一個硬件平臺,在硬件平臺之上我們有一層虛擬的隔離環境管理器,在上面創建一個用戶空間的隔離環境,而我們期望將用戶空間隔離成多組互相不干擾,且一個用戶空間內只運行一個或部分進程的狀態。一般來說第一個用戶空間是有特權的可以通過它來管理其他的用戶空間。雖然在衆多的用戶空間都是公用底層同一個內核,但是在自己運行時所能夠看到的邊界只是自己所屬用戶空間的邊界,這樣彼此間也就實現了隔離,但是大家需要明白這樣的隔離遠沒有主機級虛擬化那樣隔離的徹底。我們發現隔離出來的用戶空間拿來放進程,給進程提供運行環境,並且還能夠保護內部的進程不受其他進程的干擾,這就是我們所熟知的容器。
(2)chroot
容器技術並不是新概念,最早是出現在FreeBSD系統中,當年在系統中名爲jail(監獄),作用是不受其他進程的干擾,並且可以提供一個沙箱環境,讓進程在其中運行,就算進程出現Bug或故障,也不會影響到自己所屬容器外圍的進程,這樣可以給我們帶來一個安全的運行環境。後來人們把這樣的技術復刻到Linux平臺上,這個產品名爲vserver,可以實現和jail同樣的效果,而實現vserver功能的核心技術就是我們熟知的chroot。
【我的Linux,我做主!】Docker容器技術基礎入門
(3)namespaces
對於容器級虛擬化技術,表面上看是使用了chroot,但背後是一堆技術的支撐,一個單獨的用戶空間,它的主要目標是進行用戶隔離環境的,而後任何進程運行在用戶空間當中會以爲自己是唯一運行在當前內核之上用戶空間中的進程,而且自己所能看到的進程也都是當前系統之上的所有進程,一個用戶空間應該包含以下組件:主機名和域名,根文件系統,每個用戶空間自己獨有的IPC等,各個用戶空間進程數自己的PID號,被隔離的用戶和組,以及每個用戶空間自己的Network網絡。到今天爲止Linux內核級已經對這6種需要被隔離的資源已經通過名稱空間namespaces的機制原生支持。所以到今天爲止Linux領域的容器化技術就是靠6個內核級的namespaces和chroot來實現的。
【我的Linux,我做主!】Docker容器技術基礎入門
(4)Control Groups(cgroups)
名稱空間是工作在同一組內核之上的,如果裏面有的進程出現了異常而導致內存泄露,不斷吞噬內存,最終內存全部被喫掉;同樣CPU資源也因爲這個異常進程而導致其他進程無法得到CPU資源,CPU屬於可壓縮型資源,如果其他進程無法得到資源那麼就會一直掛在那裏等待,但是內存屬於非可壓縮型資源,申請就必須得有,沒有就會出現OOM內存溢出的異常。所以內核級必須實現功能來限制每一個用戶空間的進程所有可用資源總量,第一種方式例如我們可以按CPU來進行分配,一共有3個用戶空間,我們指定CPU的比例是1:2:1,這樣分配後,如果2和3號不用,那麼1號如果需要大量計算可以喫掉整個CPU的計算量,如果2和3號都會使用,那麼它們就會按照比例分配,確保CPU按照25%,50%,25%的百分比分配資源;第二種方式是可以限制一個用戶空間的進程在整個系統資源如32核CPU中,最多使用2核CPU。這種功能必須要在內核上對每個名稱空間來實現,而這個功能在內核級靠的是Control Groups即cgroups的機制來實現的。
對cgroups來說就是把系統資源分成多個組,把每個組內的資源量指派到特定的用戶空間的進程上去(圖1-4)。容器級的虛擬化由於使用的是同一個內核,在內核級強行設置了邊界,而主機級虛擬化本身使用的就不是同一個內核,內核就是天然隔離的平臺,所以容器級的虛擬化的隔離性遠不如主機級虛擬化隔離性那麼好,因此爲了加強隔離性防止用戶空間的進程繞過漏洞去劫持其他用戶空間中的資源,所有後來通過SELinux等安全機制來加強系統的安全性,所以我們爲了能夠支撐容器技術更加完善,所以我們在使用容器技術的時候同樣要啓用SELinux功能
【我的Linux,我做主!】Docker容器技術基礎入門
(5)LXC
爲了使容器技術更加易用,把使用容器技術的功能做成一組工具可以極大的簡化用戶的使用難度,所以就有了LXC的解決方案,LXC即LinuX Container。LXC是最早使用一組簡易使用的工具和模板來極大的簡化容器技術使用的方案,我們可以使用lxc-create來快速創建用戶空間,創建完用戶空間後還需要裝上基本的應用程序,此時需要基於template模板腳本,指向一個安裝過程,這個安裝過程包含了你所打算創建的系統發行版所屬的倉庫,從倉庫中把各個程序包下載下來並安裝,生成這個名稱空間,這個名稱空間的使用效果就類似於虛擬機或者KVM一樣。雖然LXC極大的簡化了容器技術的使用,使得系統的資源開銷極大的降低,但是在容器分發、遷移、快速創建等大規模使用的場景中和傳統的虛擬機相比,複雜程度並沒有降低,且隔離用戶空間的安全性也並不是那麼完善。
(6)Docker
於是在這樣的背景下就出現了docker,它是LXC的增強版,是容器技術的前端易用工具,容器是Linux內核當中的技術,而docker則是將容器技術得以普及的一個工具。Docker在早期使用的是LXC作爲容器管理引擎,但是在創建用戶空間時不是用template來現場安裝,而是使用了鏡像技術,類似於把一個操作系統打包成一個鏡像,然後把這個鏡像文件下載下來,創建成一個虛擬機,然後基於這個虛擬機來啓動,Docker就是使用類似這樣的方式來操作。在互聯網中有一個專門的倉庫,倉庫中有已經打包好的最小化的CentOS操作系統,最小化的CentOS+Nginx的鏡像等,後續使用docker啓動容器,運行容器時,它會自動連到服務器上下載一個匹配你所要創建的容器的鏡像,把鏡像拖到本地,並基於鏡像啓動容器。所以docker極大的簡化了容器的使用難度,你所用到的大多數的鏡像都可以在docker倉庫中找到。
爲了使容器更加易於管理,docker規定在一個用戶空間中只運行一個進程,即nginx在nginx的容器中,Tomcat在Tomcat的容器中,二者使用容器間的通信邏輯進行通信。如此一來使用的調試工具等需要在每個容器中都存放一份,好處是如果刪除了容器自身中的文件並不會影響其他容器的,壞處是所需要使用的空間更大了,每個容器中所使用的調試工具都需要準備一份,且使用進程查看命令如ps、top等時需要突破各個容器的邊界纔可以查看。
【我的Linux,我做主!】Docker容器技術基礎入門
docker在鏡像的構建底層使用的是所謂分層構建,聯合掛載的機制來實現的。我們首先創建一個純淨版的CentOS的鏡像,隨後基於這個CentOS鏡像之上構建一個nginx鏡像,且這個鏡像只包含nginx鏡像本身,一個功能只在一層上構建並實現,然後把它們疊在一起形成一個統一的視圖,這樣的好處是以後我們的鏡像分發沒有那麼龐大了。比如我們在一個系統上需要運行3個容器:nginx、tomcat、MySQL都是基於底層CentOS構建的,當我們需要運行nginx鏡像時,我們把nginx和CentOS進行聯合掛載,同時每一層鏡像都是隻讀的,當我們需要運行2個nginx服務的時候,使用同一個CentOS鏡像和同一個nginx鏡像,然後都通過聯合掛載的方式創建2個容器,並在每一層聯合掛載的鏡像棧的最頂層額外添加一個新層,這個層可讀可寫,且是容器自身專有的層,這樣就實現了容器運行的環境。但是如果我們希望將容器遷移到其他宿主機的環境中去,在可讀可寫層是寫有數據的,因此現在生產環境真正使用容器時並不會在容器本地保存有效數據,我們會在文件系統的外部掛載一個共享的持久存儲,如iSCSI,Ceph等,這樣如果出現MySQL容器運行故障或者出現宕機也沒有關係,我們在一個新的主機上重新啓動一個MySQL容器,然後把持久存儲的數據掛載過來,繼續使用就可以了(圖1-6)。這樣一來,我們就可以把一個容器當做一個進程來使用,啓動一個容器就是爲了運行一個進程,進程一終止,把對應的容器刪除即可,這樣容器就像進程一樣有了生命週期,而且容器運行的環境和我們的宿主機也沒有密切關聯了,可以運行在任意一臺宿主機上。
【我的Linux,我做主!】Docker容器技術基礎入門
(7)容器編排工具
當我們有多個容器需要運行的時候,我們需要一個在docker基礎之上能夠把這種應用程序之間的依賴關係,從屬關係、反映在啓動關閉時的次序和管理邏輯之中,這種功能就是容器編排。Docker出現之後迅速出現了很多的容器編排工具,docker公司自己的machine+swarm+compose的工具組合,其中compose是單機編排,swarm是將多個主機作爲一個整體進行編排;另一個是ASF的,ASF有一個著名的數據中心操作系統mesos,這不是專門編排容器的,它是實現統一資源調度和分配的,如果我們想實現統一編排容器還需要加一箇中間層marathon;第三個就是谷歌公司推廣的kubernetes(k8s),k8s是由谷歌公司自己公司運行了十幾年的博格系統經驗改編而來,谷歌公司主導成立了CNCF基金會,這個基金會是有很多組織和公司共同組成的公共組織,是由微軟、谷歌、IBM、Redhat等公司組成的容器標準委員會,使得kubernetes已經成爲了事實上的容器編排工具的主流。
Docker公司的容器引擎經歷了由最初的LXC再到libcontainer引擎的過程,但是CNCF基金會要求Docker公司創建一個容器引擎的標準,並把它開源出來,所以目前最新的容器引擎名爲runC,這也是目前容器運行時的環境標準。

























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章