1. 程式人生 > >從「集裝箱」思考Docker風潮

從「集裝箱」思考Docker風潮

在許多革命性轉折裡,經常出現集裝箱的身影;它就像幸運草一般,總是帶來許多幸福和財運。現在Docker風起雲湧,再現集裝箱身影,如果開放視野、大力支援它,持續發揮它的潛能和力量,則幸運草就會出現在我們身旁了。

由於Docker集裝箱帶來的商機,其最直接的受益者是軟體管理者(或稱維運者),例如軟體測試工具業者、測試人員等。因此在今天,不論您是開發者或是維運者,最好是從維運者的角度、擴大視野來支援它,便能站在制高點上擬訂最佳策略,掌握了需求碎片化的潮流,進而成為新世代的領頭羊。

在這新世代裡,除了拿Docker集裝箱來打包微服務(micro-service)來滿足需求碎片之外。我們還要以廣大的視野、創新的思維,將碎片組合出各式各樣、氣象萬千的商業服務。就像飛機設計師一樣,把一群各自<不會飛>的模組(如輪胎、引擎、機翼、油箱等),以創新模式將它們組合起來,竟然整體就<能飛>上天空了。於是,創新組合的介面(interface)的定義權成為兵家必爭之地,唯有掌握接口才有話語權。

1、緣由

自從2014年以來,Docker 的集裝箱(container)技術,可說是紅透半天邊,而且勢如破竹、蔚為風潮,正在強力改變雲(cloud)服務的世界。這跟半世紀前,海上船運業的集裝箱風潮,對整個產業的革命性改變,其力道來源和產生經濟效益,可說具有異曲同工之妙。

圖-1、Docker平臺的標誌(Logo)

這項力道和潮流的直接受益者,是管理者(operator,又稱維運者),而不是開發者(developer)。因此,在本文裡,我將從管理者的視角來說明Docker集裝箱即將帶來的革命性潮流,讓讀者們皆能興奮地迎接這項已經來到身邊的潮流,並且能從中獲利。

2、回顧半世紀前的船運集裝箱風潮

在半世紀之前,集裝箱發揮了巨大的力量,改變了整個運輸產業,也改變了人們的生活。就如Intel公司總裁葛洛夫(Andrew Grove)曾舉集裝箱為例說道:

短短的十年,實際上只是航運史上一個極短促的時間,造船設計即走向標準化,冷凍運輸船也誕生了,最重要的是集裝箱化作業的興起,這種容許船貨更快速裝卸的技術在航運的生產力上引進了『十倍速』的改變,逆轉了節節升高的成本趨勢,..... 有些港口做了改變,有些雖盡力改革,卻無法做到,許多則堅持抗拒這種潮流,結果,這些新技術引發了全世界貨運港口的重新洗牌,.... 沒有采行新技術的港口(如新加坡及西雅圖)可能被重新規畫,成為購物中心、休閒場所或河岸公寓大廈。

圖-2、集裝箱讓運輸費用降低一半(以下摘自百度圖片)

長榮海運公司總裁 張榮發 先生在其回憶錄上寫道:

為了配合集裝箱化運輸時代的來臨,海運事業的整體運作型態也產生了重大的轉變,無論在海上運送、碼頭作業以及陸運轉接上,都有革命性的改變。陸上拖車運輸業應時而興,扮演極為重要的角色,以集裝箱拖車配合集裝箱船運輸,具有簡化包裝、防止竊盜、加速貨物搬運及便利關務檢驗等優點,使集裝箱運輸作業更加靈活。為了能確實掌握海上及陸上的運送服務質量和效率,就率先於1973年9月成立了長榮運輸公司。

圖-3、世界航運巨擘:長榮(Evergreen)

集裝箱的威力是來自於它提供了一致的介面(interface),簡化了運輸業的工具。例如以前,在集裝箱尚未普及之前,在公路上,必須為汽車業而設計特殊的拖車;在港口碼頭,也必須為木材業而設計特殊的卸貨吊車及倉庫等等。這些特殊設計對於運輸管理、港口管理、倉儲管理等都是很麻煩的事。有了集裝箱之後,就出現了專門運集裝箱的輪船,也有專門拖集裝箱的拖車,高速公路的彎曲度也因集裝箱拖車的安全而修正,倉庫的管理也變得很單純。集裝箱不一定帶給汽車業、木材業、玩具業帶來直接的方便,也許反而帶來不方便(如大汽車必須拆解開來才能裝進集裝箱裡)。但是運輸業等獲得好處,所以運輸業會很樂意把集裝箱拱擡起來,促成集裝箱的革命性風潮。

將之對應到Docker風潮,可知道Docker集裝箱的效益在於:讓所有云服務都有一致的操作(operation)介面,包括部署、管理等方式。眾多雲平臺就像眾多碼頭一樣,都使用一致的方式來操作集裝箱,例如卸貨器具、拖車等。Docker公司的Scott Johnston曾說道:

你將不再需要使用各項單獨的IT管理工具來分別進行App的管理、部署、監控和擴容等功能操作,在整個企業內這些操作都可得到一致性、統一性。

3、從<國王的皮鞋>領悟Docker集裝箱的經濟效益

古代有一位國王在它的國境裡視察,因為路面崎嶇不平,還有很多碎石頭,刺得國王的腳又痛又麻。

圖-4、赤腳國王的故事(摘自百度圖片)

回到了王宮後,他下了一道命令,要將國內所有的道路都鋪上一層牛皮。讓他自己和]全國的人走路不再受刺痛之苦。眾大臣聽了國王的話都一籌莫展,知道這很難。即便殺盡國內所有的牛,也湊不到足夠的牛皮來鋪路,而且花費昂貴。這時,一個聰明的僕人向國王建言:可以試著用牛皮將腳包起來,大王的腳就不會忍受痛苦了。國王聽道而頓悟了,便收回命令,採納了建議,於是,皮鞋就這樣發明了出來了。

圖-5、國王的皮鞋

我想,大家一定都聽說過上述的皮鞋故事了。其解決腳痛不方便的方案有二:第1方案是:將所有道路都鋪上一層牛皮(如VMware),實在不經濟實惠。 第2方案是:用兩片牛皮包住腳,這就是皮鞋(Docker集裝箱)。那麼,你領悟到什麼呢? 至少明顯知道第2方案可帶來可觀的經濟效益。

從上述皮鞋故事的比喻,可知道傳統的虛擬化(virtualization)技術就相當於在各道路(實體機器)上鋪一層牛皮(VM, 虛擬機器),然後讓國王的腳(App)在牛皮(VM)上走路(執行)。傳統上雲平臺採取虛擬化手段來滿足使用者個別的資源需求分配,以及確保其可用性和隔離性。然而無論是KVM還是Xen等Guest OS都很浪費資源又難於管理, 都不如Docker集裝箱(皮鞋)來的更加靈活、快速和節省資源。

4、Docker如何運輸(ship)集裝箱?

顧名思義,Docker就是“碼頭搬運工人”之意。而集裝箱的主要用途就是運輸東西。所以,我們把焦點放在Docker集裝箱和如何運輸上,也就是從運輸(shipping)的角度來認識Docker及其集裝箱。

設想在開發平臺上,開發者撰寫一份dockerfile檔,讓Docker(碼頭搬運工人)在此平臺上建立一個Docker集裝箱,此集裝箱運行於開發平臺上的一個使用者程序(process)裡,包含了執行某一特定App程式的所需要的OS、軟體庫、配置檔案和資料,是一個可移植的執行單位。那麼,如何把這個集裝箱運輸(移植)到雲平臺上呢?這時,Docker(碼頭搬運工人)就從這個集裝箱(或其dockerfile)產生出它的映象(image),通稱為Docker(集裝箱)映象;然後把該(集裝箱的)映象傳輸到雲平臺上。雲平臺上的Docker會依據這映象,修改一下配置模組,就在雲平臺上建立一個新的Docker集裝箱了,讓App在此集裝箱裡執行。相對上,一個Docker鏡象是一個模子(template),可用來建立多個Docker集裝箱物件或例項(instance)。

由於Docker集裝箱及其映象,是由dockerfile檔案的指令碼所建立的;所以也可直接將dockerfile檔案傳輸到雲平臺,並依據其指令碼而在雲平臺上建立新的Docker集裝箱。集裝箱的dockerfile檔案和映象兩者都是模子,都可用來(在雲平臺上)建立集裝箱例項,並讓App順暢執行起來。軟體專家波金(Lucas Perkins)在其文章:“ Docker and Shipping Containers: An Imperfect Analogy”裡,就拿一棵樹來比喻一個Docker集裝箱,而不是拿船運集裝箱來比喻。他說道:

  • The shipping container analogy is apt, but for me it completely breaksdown on one crucial point: when shippingcontainers go down, their cargo is lost.(拿船運集裝箱來比喻是可以的,但有一點會失真:當集裝箱沉入大海,貨物就消失了。)

  • Docker containers don't work this way. When they go down, you simplyrebuild the container.(Docker集裝箱並非如此,當它損毀了,只要重建一個就行了。)

  • In this sense, Docker containers are more like plants than shippingcontainers. If a plant dies, you simply plant a seed and replace it. (以此觀之,Docker集裝箱更像樹木。如果一棵樹枯死了,只要播下種子,長出一棵新樹就行了。)

  • If a Docker container goes down, .... You can simply use the oldcontainer's Dockerfile (think of it as a container seed) to sprout a newcontainer identical to the old one. Even better, Dockerfiles, like seeds, tendto be quite small , but they can grow into mighty oaks.(如果一個Docker集裝箱損毀了,你只要使用原來的dockerfile(就像種子)來重新長出一棵一樣的樹就行了。而且一個小小的dockerfile,就能長出一棵大樹。)

上述dockerfile是一種指令碼檔案,用來描述如何把二進位制(binary)檔案裝進一個Docker集裝箱映象(Dockerimage),並做好配置。當你使用docker build命令的時候,Docker會讀取這dockerfile檔案,執行其指令碼內容來構建立一個Docker映象。所以,DockerFile的用途就(像樹的種子)用來構建Docker映象。我想,從上所述,你應該可以領悟Docker集裝箱運輸的涵意了。

5、從LXC容器到Docker集裝箱

Docker集裝箱是基於LXC容器而發展出來的。其實,這裡的集裝箱和容器都是“Container”術語的的中文翻譯。那麼,為何我稱LXC容器,而稱Docker集裝箱呢? 其主要原因是:LXC容器是特定平臺的虛擬化,不能充分獨立於底層機器(平臺)的配置(configuration),例如networking, storage, logging, distro等等。所以,LXC本身無法充分跨(機器)平臺,導致App也無法跨平臺。也就說,LXC難以通過標準化的模板製作、重建、複製和移植,無法如船運集裝箱一般,可以跨越各地港口和碼頭。

後來,Docker弭補了這項缺點。Docker在LXC與平臺之間定義了標準介面,提供一種安全、可重複的執行環境,讓各集裝箱都運行於自己的網路空間、虛擬介面和IP地址;並能自動部署和更新軟體版本。這種跨平臺的新型LXC就成為Docker集裝箱。就像船運集裝箱與各港口的碼頭、各公司貨輪或拖車的型號、配置是無關的。

簡而言之,雖然LXC容器很成熟了,只是缺乏跨平臺性,不方便在多平臺(機器)之間移動;也不方便於建立管理,不易於重複操作和共享等。基於成熟的LXC容器功能,Docker集裝箱解決了上述問題,成為可移植、易於改版與整合的新一代虛擬化技術。“集裝箱”一詞強調了Docker 集裝箱的效益在於:讓所有云服務都有一致的部署、傳輸、改版等管理方式。眾多雲平臺就像眾多碼頭一樣,都使用一致的方式來操作集裝箱,例如卸貨器具、拖車等。

6、認識LXC容器

LXC仰賴namespace來實現隔離性。讓每個容器都有自己的名稱空間,確保不同容器之間不會相互影響,讓每個容器成為擁有自己程序和網路空間的虛擬環境,都成為一個獨立執行的單位。此外,LXC藉由核心的cgroup來對各個容器(的程序)使用的系統資源做嚴格的限制。

簡而言之,LXC基於namespace的隔離機制和cgroup的資源控制功能,來管理容器。例如可建立一個cgroup來限制某個(容器)程序對CPU的佔用率不能超過50%。而Docker則在LXC基礎上,加上Docker境像管理方式,就成為Docker集裝箱了。

Docker借鑑了虛擬機器(VM)的模式,讓使用者像管理VM一樣的管理他們的集裝箱映象。

6.1 隔離性

LXC運行於一個使用者空間程序裡,在既有的程序管理架構上,增添了資源管理和隔離機制。所以LXC是針對某一App提供資源隔離和控制的輕量型虛擬系統。LXC仰賴namespace來實現隔離性。讓每個容器都有自己的名稱空間,比如pid/net/ipc/mnt/uts等名稱空間,以及不同的 user id和group id。有了namespace從程序、網路、IPC、檔系統、UTS和使用者角度進行隔離,我們就能e確保在不同容器之間不會相互影響,每個容器都成為一個獨立執行的單位。從容器裡而觀之,它是一個完整的Linux的世界。在整個平臺而觀之,容器運行於一個普通的使用者空間程序,namespace創造了這種對映和隔離效果,雲平臺承載著一個個容器,就如同造物者創造了許多世外桃源一般。

6.2 資源控制

LXC仰賴cgroup來限制各個程序對系統資源的使用能力。通常會建立多個cgroup,形成一個樹狀結構(hierarchy)。然後subsystem會關聯連線到這個樹狀結構上。一個subsystem代表著一項資源,例如CPU、Memory或 I/O等。例如下圖:

圖-6、cgroup樹狀結構

這圖裡的cgroup組織形式是樹狀結構的,包含一個父cgroup和三個子cgroup,其關聯到兩個subsystem (即CPU和memory)。這subsystem是經由cgroup來與task(典型的就是程序)連結,以便實現對task的資源管理與控制。一個task可加入到樹狀結構上的一個cgroup,由此cgroup來限制該task的資源使用。其中,cgroup與task是多對多(N:N)的連結關係。亦即,一個cgroup可以連結到多個task。而一個task也可連結到多個cgroup,但是在一個樹狀結構裡只能加入一個cgroup。例如,針對一個(容器)程序,先建立名為cpuset的cgroup,然後將一個程序(/mytask)的PID寫入/sys/fs/cgroup/cpuset/ tasks 檔案裡,就把這個mytask加入到該cgroup了。如下圖:

圖-7、cgroup與task的N:N連結關係

這個mytask連結到兩個cgroup:即“cpuset”和“ioset”,各連結到一個subsystem(即CPU和I/O資源)。

7、認識Docker園丁(Runtime)

剛才說明了,我們在運輸(ship)或移植一個Docker集裝箱時,就像移植一棵樹一樣, 但是移植樹的種子(seed)到另一個花園(平臺)裡,重新打造出一樣的(identical)環境(花盆)並重新長出一樣的樹。例如,一個dockerfile就是種子,體積很小,運輸快速。如下圖:

圖-8、以樹來比喻Docker集裝箱的運輸

那麼,我們在電腦上,需要有位園丁來打造花盆、準備資源(如水、泥土)等工作。這位園丁就是:Docker Runtime。它是由三個模組所組成,包括:Docker Server、Docker Engine和Docker Daemon三部分。通常,人們是透過Docker Client來與Docker Server建立通訊(兩者是C/S架構)。例如,我們可以將docker build命令傳送給Docker Server來依據指定的dockerfile來建立一個Docker映象。

圖-9、Docker Runtime的結構

Docker Server接受DockerClient所傳送來的請求,然後轉給Docker Engine去轉換出一連串的工作(job)來管理集裝箱。例如,向Docker Registry獲取映象、通過GraphDriver執行集裝箱映象的建立、通過NetworkDriver執行容器網路環境的配置、通過ExecDriver執行集裝箱內部的軟體等。

8、認識Docker集裝箱集散地(Hub)

Docker公司不僅僅提供上述的Docker園丁來幫你搬運集裝箱,還提供DockerHub來做為集裝箱的共享平臺。Docker公司提供的開放平臺,主要包括:

Platform = Docker Engine + Docker Hub + APIs + Ecosystem

如下圖:

圖-10、<Docker Engine + Docker Hub>開放性平臺

我們在開發平臺上,使用Docker引擎來將App打包到集裝箱裡,然後透過DockerHub API來將集裝箱(的映象)放到DockerHub上。於是,Docker Hub成為一個集裝箱集散地,也就是一個共享的集裝箱平臺。需要時,可從這Hub尋找到集裝箱,並下載到雲服務平臺(如阿里雲或Google雲)上去執行。

圖-11、Docker Hub集裝箱共享平臺

所以,Docker Engine和Docker Hub兩者聯手,為開發者和系統管理員設計出一個易於釋出和執行分散式App的開放性平臺。

9、闡述<集裝箱>幕後的架構設計思維

9.1 序中有亂

前面,介紹過了臺灣長榮海運公司繁榮發達的歷史經驗,可讓你體會出集裝箱如何帶來巨大經濟價值。集裝箱的外表簡單有序、能疊得很高、而且井然有序;集裝箱的內部是空的,用來容納多樣化而繁雜的物品;這種情形稱為:序中有亂(變化)。序中有亂的巨大威力,改變了整個運輸產業,也改變了人們的生活。

俗語說:科學家從亂中找序,而設計師(藝術家)則規劃序中有亂。無論是亂中有序序中有亂,兩者都要呈現出序(order),幷包容亂(change),只是手段不同而已。兩種手段都能帶來巨大經濟價值,精通這兩種手藝,是當今需求碎片化時代哩,將雲平臺上的微服務(micro-service)迅速創新組合成為App的不二法門。序中有亂的<亂>是變化、成長與繁榮之意。

「亂中有序」與「序中有亂」兩者之間,只是人們抽象視角(viewpoint)的不同心智(mental)呈現而已,並外在世界的真實事物(和景像)。就像大家孰悉的「橫看成嶺側成峰,遠近高低各不同」詩句裡,因為視角不同而呈現於內心的不同景像。例如,臺北101大樓的鋼骨結構,可從「序中有亂」視角來看它;也可以從「亂中有序」來看它。再如,一盆看來很漂亮的楓葉,既可從「序中有亂」視角來看它;也可以從「亂中有序」來看它。

圖-12、「亂中有序」還是「序中有亂」呢?

其實,中文字的<易>,並不代表簡單(easy);而是代表變化(change)之意。當我們找到一種容器(container),來包裝變化,就得到簡單了。因此,「容易」兩個字組合在一起,才代表簡單(easy or simple)之意。於是,Docker集裝箱以容器來包裝複雜多變,任人們擁有<簡單而容易>的方式來實踐App的維運。它的幕後蘊藏了典型的「序中有亂」架構設計思維。

9.2 <>的設計法則

在我所寫的書籍:《思考軟體、創新設計:A段架構師的思考技術》(北京電子工業出版社)裡,我也詳細闡述了集裝箱的設計哲理,我書中寫道:

這來自於自然界的造物之道。自然界生物之設計,其主要限制是:資訊的有限性(Information Limitations)。由於這項限制,一個生物形體的造成,是出自一個概括性的計劃:<單純的造形>。隨著生物的成長、與環境的互動資訊越多,逐漸在細節上修修補補,就發展出<不同的內涵>。然後,基於單純的造形,不斷進行<重複的組合>。例如,漂亮的楓葉林,就是合乎“單純造形、不同內涵、重複組合”三項特性。許多造形相同(且不同細節)的楓葉,組合出一遍美麗的樹林。

圖-13、「序中有亂」帶來的美感

再如人們的手掌的造形也都極為相似,其細節紋路也各不相同,也滿足上述三項特性。關於<資訊的有限性>與自然造物法則,在生物學界的探討論文已經非常多了,在此就不多敘述了。在最具爆發力的工業設計品中,你常常可以發現其傑作具有其特色:簡單造形、內涵不同、無限重複。集裝箱就是典型的單純造形,它兼具了這三項特質。更重要的是,它帶來無比巨大的商業潛力和商機。舉凡能包容變化之體系,都有三項共同之特性:

  • 特性1:構造簡單—單一元素。

  • 特性2:容易組合—簡單的(如線性、樹狀或網狀)組合規律,呈現出美好的序。

  • 特性3:包容變化—集裝箱能裝無限形式之物。

因為單一元素,簡單組合,具有極大的包容力和彈性,發揮<序中有亂>的特質,帶來一樣的巨大潛能,蔚為風潮。

歡迎您有空時,可閱讀我所寫的這本書,並多多賜教。

在這本書裡,我詳細說明了,如何把變化封裝起來,凸顯簡單秩序,讓人們因為秩序簡單而令人著迷,因為變化無窮而令人驚歎它的無限潛能。這就是船運集裝箱、Docker軟體集裝箱等具有革命性威力的來源,就是:和諧而充滿能量。

9.3 世界首富:比爾.蓋茲(Bill Gates)也在思考集裝箱

鼎鼎大名的微軟創始人比爾.蓋茲,在2013年閱讀了上百本書籍,他閱讀之後也做了筆記。頗令人好奇的是,他第一份閱讀筆記,竟然是有關於<集裝箱運輸>。這本書名是:The BoxHow the Shipping Container Made the World Smaller and theWorld Economy Bigger.(By Marc Levinson)

圖-14、比爾.蓋茲也在思考集裝箱

如果您有興趣,也可以觀看我的線上視訊課程,其中有一個視訊課程(免費),名稱是:“新一代架構師:像Bill Gates一樣_思考集裝箱”。

在這視訊中,我詳細地闡述了集裝箱的架構設計思維。觀看網址:

http://www.cnblogs.com/smartADT。

10、Docker潮流下的贏家策略

10.1 從Operator視角看Docker集裝箱,掌握商機

  集裝箱帶來的商業利益,其直接受惠是運輸業者,並不是貨物製造者或應用者。所以集裝箱內部的包裝業,如紙盒製造業、打包工人等;拖車汽車廠、拖車行、拖車司機;還有造船廠、海運公司、碼頭工人等都會迅速蓬勃發展起來。

圖-15、從Operator視角看集裝箱

同樣地,Docker集裝箱帶來的商業利益,直接受惠是軟體管理者或稱維運者(operator),例如軟體測試工具業者、測試人員等。至於大多數的軟體開發者(developer),通常等到Docker集裝箱變得普遍流行起來了,大家才會大大感受到非用它不可了。因此,不論您是身為開發者,還是維運者,都應該站在維運者的視角和立場來感受Docker集裝箱潮流的力量,以便採取最佳策略,抓住這道力量帶來的巨大商機。否則您將成為潮流下的後知後覺者。

10.2 採取<組合創新>架構設計思維

自從1980年代,面向物件(object-oriented)軟體技術流行以來,架構設計有兩個基本技藝:分類(classification)與組合(composition)。逐漸地衍生了以下兩種不同的架構設計思維:

  • 古典抽象思維:偏於亂中有序,從複雜變化中分析出次序;其追求共通性。

  • 創新組合思維:偏於「序中有亂」,力求設計出次序來容納複雜變化;其追求獨特性。這種思維,最常見的比喻是“集裝箱”,因為從集裝箱的發展歷史,很容易讓我們體會出<序中有亂>如何帶來巨大經濟價值。

如今,在這需求碎片化時代裡,Docker集裝箱將成為打包微服務(micro-service)的最佳載體。於是,我們將需要有創造的架構來將雲端的微服務,組合形為具有獨特性的App了。於是,需要有<組合創新>的架構設計思維。就像飛機設計師一般,其把一群各自<不會飛>的模組(如輪胎、引擎、機翼、機尾、油箱等),以創新的模式將它們組合起來,竟然整體就<能飛>上天空了。

10.3掌握介面(interface),擁有話語權

集裝箱就是基於「序中有亂」思維,把複雜多變(的內容)包裝起來,呈現出簡單易用的序。這個序呈現出來,就是集裝箱的介面了。同樣地,Docker集裝箱也定義了一群標準的介面。

然而,軟體產業是一個強龍與地頭蛇混雜的叢林世界。大哥(強龍)訂定介面為標準,小弟(地頭蛇)遵循標準介面。唯有掌握介面制定權才能成為強龍,獲得話語權,成為最大獲利者。例如,Docker就是基於標準的LXC容器(也是集裝箱)而在制定自己的介面,成為產業新標準介面,而建立其強龍地位。

同樣地,在Docker集裝箱的潮流下,將湧現更多的小集裝箱和介面,也將湧現較大的集裝箱和介面。於是強龍處處有,獲利無窮時。如果您有興趣,也可以觀看我的線上視訊課程,其中有一個視訊課程(免費),名稱是:“新一代架構師:掌握介面,才有話語權”。