本節書摘來自異步社群《docker容器:利用kubernetes、flannel、cockpit和atomic建構和部署》一書中的第1章,第1.1節,作者: 【美】christopher negus(克裡斯托弗•尼格斯)著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
docker為應用程式的打包和運作提供了一種優雅的方式。使用喜歡的linux系統,幾分鐘之内就能将docker安裝好并作為服務運作起來。建構、運作、停止、啟動、調查、修改或者用其他的方式操作容器非常容易,說實話,很棒。
docker的簡單易用使其成為當今最流行的開源項目之一。但是作為資料中心容器化核心的docker卻引起了極大的震動,其潛力無異于重新發明了個人和公司(或大或小)建立、測試、部署和管理其最關鍵應用程式的方式。
使用容器化技術也可以讓應用程式向雲環境的部署變得更為高效。就像容器本身一樣,運作容器的作業系統也能夠被瘦身。因為容器已經持有應用程式運作所需的大部分依賴,是以這些用于容器的新型主控端作業系統就不再需要包含所有依賴了。
本書不僅介紹什麼是docker以及docker的工作方式,還揭示了特定用途下擴充docker的若幹方法。盡管一個容器的建立和部署是很簡單的,但要讓多個容器協同工作、通路其他容器的資源,以及通路運作容器的主控端的資源,則需要更高的複雜性。本書給出了幾種建立和部署這些複雜容器集的不同方法。
本書并不隻停留在理論層面,其探讨的容器及容器相關工具的各個方面都備有說明這些特性工作方式的實際例子。讀者可以自己先嘗試一下,然後按照自己使用docker的方式修改和擴充這些執行個體。
然而,在開始本書的學習之前,讀者需要弄清楚關注容器的原因。
docker提供了一種建立和運作已經在容器中進行了配置的應用程式的方法。想要真正了解它,先了解容器化應用不是什麼是很有幫助的。
1.1.1 容器化應用不是直接在主控端上運作的應用
運作應用程式的傳統方法會将應用程式直接安裝到宿主計算機的檔案系統上并從那裡運作它。從應用程式的視角看來,其環境包含主控端的程序表、檔案系統、ipc設施、網絡接口、端口及裝置。
要讓應用程式運作起來,通常需要安裝與應用程式搭配的額外軟體包。一般來說,這不是問題。但有些情況下,可能想在同一個系統上運作相同軟體包的不同版本,這就可能會引起沖突。
應用程式與應用程式之間也會以某種方式發生沖突。如果應用程式是服務,它可能會預設綁定特定的網絡端口。在服務啟動時,它可能還會讀取公共配置檔案。這會導緻無法在同一主控端上運作該服務的多個執行個體,或者至少非常棘手;這還讓那些想要綁定到同一端口的其他服務難以運作。
直接在主控端上運作應用程式還有一個缺點,那就是難以遷移應用程式。如果主控端需要關機或者應用程式需要更多計算能力——超出主控端所能提供的,那麼從宿主計算機上擷取所有依賴并将其遷移到另一台主控端上絕非易事。
1.1.2 容器化應用不是直接在虛拟機上運作的應用
建立虛拟機來運作應用程式能夠克服直接在主控端作業系統上運作應用程式所具有的缺點。雖然虛拟機位于主控端上,但它作為獨立的作業系統運作,它包括自己的核心、檔案系統、網絡接口等。這樣可以很容易将幾乎所有東西儲存在獨立于主控端的作業系統中。
因為虛拟機是獨立的實體,是以不會出現那種直接在硬體上運作應用程式所産生的缺乏靈活性的弊端。可以在主控端上啟動10個不同的虛拟機來運作應用程式10次。雖然每個虛拟機上的服務監聽了同一個端口号,但是因為每個虛拟機擁有不同的ip位址,是以并不會引起沖突。
同樣地,如果需要關閉宿主計算機,可以将虛拟機遷移到其他主控端上(如果虛拟化環境支援遷移)或者直接關閉虛拟機并在新主控端上再次啟動它。
一個虛拟機運作一個應用程式的執行個體的缺點是耗費資源。你的應用程式可能隻需要幾兆位元組磁盤空間來運作,但是整個虛拟機卻要耗費許多gb的空間。再者,虛拟機的啟動時間和cpu占用幾乎肯定會比應用程式自身消耗的高得多。
容器提供了另一種在主控端上或虛拟機内直接運作應用程式的方式,這種方式能使應用程式更快、可移植性更好,并且更具可擴充性。
1.1.3 了解容器的優點
就運作應用程式而言,容器有望靈活高效地使用資源。
靈活性來自容器可以包含其所需的全部檔案。如同運作于虛拟機中的應用程式,其可以擁有自己的配置檔案和依賴庫,還可以擁有自己的網絡接口——這些網絡接口不同于主控端上配置的那些網絡接口。是以,與在虛拟機上運作應用程式一樣,容器化應用比直接安裝的應用程式更容易遷移,而且因為應用程式運作所栖身的每個容器均擁有獨立的網絡接口,是以也不會争用同一端口号。
就啟動時間、磁盤空間占用和處理能力而言,容器既沒有運作獨立的作業系統,也沒有包含運作整個作業系統所需的大量軟體。這是因為容器隻包含運作應用程式所需的軟體,以及其他想随容器一起運作的工具和少量描述容器的中繼資料。
與虛拟機不同,docker容器并不包含獨立的核心(kernel)。docker容器中運作的指令會出現在主控端的程序表中,多數情況下,看起來非常像系統中運作的其他程序。然而,這兩種環境中應用程式運作的差異與這兩個應用程式所看到的不同世界有着極大的關系。
檔案系統:容器擁有自己的檔案系統,預設情況下,它無法看到主控端系統的檔案系統。該規則的一個例外是,有些檔案(如/etc/hosts和/etc/resolv.conf)可能會被自動挂載到容器中。另一個例外是,當運作容器鏡像時,可以顯式地将主控端的目錄挂載到容器中。
程序表:linux主控端上可能運作着成百上千的程序。然而,預設情況下,容器内的程序無法看到主控端的程序表,容器擁有自己的程序表。是以,你啟動容器時所運作的應用程式,其程序在容器内被配置設定的pid為1。從容器内,程序無法看到主控端上運作的其他程序——如果這些程序沒有在容器内啟動的話。
網絡接口:預設情況下,docker守護程序通過dhcp從一組私有ip位址集中确定ip位址。除了使用dhcp,docker也支援其他網絡模式,例如,允許容器使用其他容器的網絡接口,直接使用主控端的網絡接口,或者不使用網絡接口。依據你的選擇,你可以将容器内的端口暴露給主控端的同一端口或不同端口。
ipc設施:容器内運作的程序不能與主控端系統上運作的程序間通信(ipc)設施直接互動。你可以将主控端上的ipc設施暴露給容器,但這不是預設的。每個容器都有自己的ipc設施。
裝置:容器内的程序無法直接看到主控端系統上的裝置。不過,當容器啟動時可以設定一個特殊權限選項來授予該項權限。
如你所見,docker容器可以在主控端的視線内運作,但其運作方式限制了容器越過邊界所能看到的主控端内容(除非明确地開放了那些視圖)。
1.1.4 了解容器化應用面臨的挑戰
容器化應用面臨的挑戰在于它們不同于那些不在容器中的應用程式。每個linux系統中,用于啟動和停止服務以及檢視出錯消息的設施已就位。linux還提供了監控服務和輪換日志檔案的方法。
對于運作虛拟機而言,整個虛拟化平台(如openstack和red hat企業虛拟化)被建構來啟動、停止和使用虛拟機。雖然管理容器組的工具已在努力建構中,但大多數尚處于萌芽階段。諸如kubernetes和openshift這樣的項目正在完成部署和管理容器組的架構。
docker容器被打包為容器鏡像。為了能将容器鏡像儲存在registry中并用docker指令管理它們,人們已經進行了大量的工作。然而,用于管理docker鏡像的工具遠未像用來管理linux軟體包(如基于linux rpm或deb的系統)的工具那樣成熟。
能夠驗證鏡像來自何處的工具、确定鏡像是否被篡改的工具以及檢視容器中具體安裝了哪些軟體包和這些軟體包的版本的工具才剛剛開發。目前,要意識到,多數情況下很難完全保證從docker hub registry上随便擷取的鏡像可以安全使用。
使用容器的另一個挑戰來自這樣一個事實:就其本質而言,容器預設情況下無法看到其他容器。是以,要是你想讓自己的容器與其他容器緊密配合要怎麼辦呢?例如,你可能有一個web伺服器,你想讓這個伺服器通路你的資料庫伺服器。
讓容器看到彼此的一些解決方案是docker中能讓你将容器連接配接到一起的特性,以及讓你在pod的容器之間識别出服務的使用方和提供方的kubernetes的特性。更多容器管理工具正被推出來解決這些問題。但切記,它們尚處于早期開發階段,而且容器管理的幾乎各個領域都有多個工具在開發,有時還互相沖突。