docker 使用

Docker:利用Linux容器實現可移植的應用部署

Docker是一種在Linux容器裏運行應用的開源工具,一種輕量級的虛擬機。除了運行應用,Docker還提供了一些工具,藉助Docker Index或自己託管的Docker註冊表對進行了集裝箱化處理的應用進行分發,從而簡化複雜應用的部署過程。

我將在本文介紹如今在部署複雜系統時公司所面臨的挑戰,Docker怎樣有效地解決這個問題,以及Docker的其他用例。

部署的挑戰

服務器應用的部署已經越來越複雜了。把幾個Perl腳本拷貝到正確目錄就完成服務器應用的安裝,這種時代已經一去不復返了。如今的軟件有很多類型的需求:

  • 對已安裝軟件和庫的依賴(“Python版本高於2.6.3,使用Django 1.2”)

  • 依賴於正在運行的服務(“需要一個MySQL 5.5數據庫和一個RabbitMQ隊列”)

  • 依賴於特定的操作系統(“在64位的Ubuntu Linux 12.04上構建、測試”)

  • 資源需求:

    • 最小的可用內存(“需要1GB的可用內存”)

    • 能綁定特定的端口(“綁定80和443端口”)

我們來看一個相對簡單的應用的部署:WordPress。Wordpress的安裝通常要求:

  • Apache 2

  • PHP 5

  • MySQL

  • WordPress源碼

  • 一個Wordpress MySQL數據庫,配置Wordpress使用該數據庫

  • Apache的配置:

    • 加載PHP模塊

    • 支持URL重寫和.htaccess文件

    • 指向WordPress源碼的DocumentRoot

 
在服務器上部署、運行這樣一個系統,我們可能會遇到下面的問題和挑戰:

  1. 隔離性:如果我們已經在這個服務器上部署了不同的網站,已有的網站只能在nginx上運行,而Wordpress依賴於Apache,這時我們就會有麻煩:它們都監聽80端口。同時運行兩個網站是可以的,但需要調整配置(修改監聽端口),設置反向代理等。庫級別也會出現類似的衝突,如果還要運行一個仍然依賴PHP4的老應用就會出問題,因爲Wordpress不再支持PHP4,同時運行PHP4和PHP5則非常困難。運行在同一個服務器上的應用沒有互相隔離(在文件系統級別和網絡級別),所以它們可能會互相沖突。

  2. 安全性:WordPress的安全記錄並不是非常好。所以還是給它創建個沙箱,至少******時不會影響其他運行的應用。

  3. 升級、降級:升級應用一般會覆蓋現有文件。升級過程中會發生什麼?系統要關閉麼?如果升級失敗,或者不對該怎麼辦?我們怎樣快速回退到先前的版本?

  4. 快照、備份:一旦所有的內容都設置好,就給系統創建一個“快照”,以便能備份快照,甚至能移到另一個服務器上再次啓動,或者拷貝到多個服務器上以備不時之需。

  5. 重複性:系統出新版本之後,比較好的做法是先在測試基礎設施上自動部署並測試,然後再發布到生產系統。通常會利用諸如ChefPuppet等工具在服務器上自動安裝一堆包,等一切內容都就緒後,再在生產系統上運行相同的部署腳本。這在百分之九十九的情況下都沒有問題。但有百分之一的例外,在部署到測試環境和生產環境之間的時間跨度裏,你依賴的包在包倉庫裏有了更新,而新版本並不兼容。結果生產環境的設置和測試環境不同,還有可能破壞生產系統。假如沒有控制部署的每一個方面(例如託管自己的APT或YUM倉庫),持續在多個階段(比如測試、預演、生產環境)重複搭建出完全相同的系統就很困難。

  6. 資源限制:如果我們的Wordpress耗費CPU資源,並佔用了所有的CPU週期,導致其他應用無法做任何事情怎麼辦?如果它用盡了全部可用的內存呢?或者瘋狂寫日誌阻塞磁盤呢?要是能限制應用的可用資源,比如CPU、內存和磁盤空間,就會非常方便。

  7. 易於安裝:也許有Debian或CentOS包,抑或是能自動執行所有複雜步驟並安裝Wordpress的Chef菜譜。但這些菜譜很難穩定下來,因爲它們需要考慮目標系統上可能的系統配置。很多情況下,這些菜譜只能在乾淨的系統上運行。因此,你不太可能更換成自己的包或Chef菜譜。這樣的話,安裝就是個複雜的系統工程,而不是午休期間就能搞定的事情。

  8. 易於移除:軟件應該能輕鬆、乾淨地移除,不留痕跡。但部署應用通常要調整已有的配置文件、設置狀態(MySQL數據庫的數據,日誌),完全移除應用也變得不那麼容易。

那我們應該如何解決這些問題呢?

虛擬機!

我們決定在單獨的虛擬機上運行獨立的應用,例如Amazon的EC2,大部分問題這時會迎刃而解:

  1. 隔離性:在一個VM上安裝一個應用,應用是完全獨立的,除非它們攻入了對方的防火牆。

  2. 重複性:用你喜歡的方式準備系統,然後創建一個AMI。你可以隨意實例化多個AMI實例。完全是可重現的。

  3. 安全性:由於我們完全隔離,如果Wordpress遭到***,其餘的基礎設施並不會受到影響——除非你沒有保管好SSH密鑰或者在哪裏都使用同一個密碼,但你應該不會這麼做吧?

  4. 資源限制:VM會分配特定的CPU週期、可用內存和磁盤空間,沒有加價的話就不能超額。

  5. 易於安裝:越來越多的應用能夠在EC2上運行,只要在AWS marketplace上點擊一個按鈕就能實例化應用。啓動只需要幾分鐘,就是這樣。

  6. 易於移除:不需要某個應用了?銷燬VM。乾淨又方便。

  7. 升級、降級:Netflix如何部署代碼裏提到,只需要在新VM上部署新版本,然後讓負載均衡器指向部署了新版本的VM。不過應用如果需要在本地保存狀態,這種方法就不是很好用了。

  8. 快照、備份:點擊一個按鈕(或者調用一下API)就能獲得EBS磁盤的快照,快照會備份到S3中。

完美!

不過……我們有個新問題:虛擬機在兩個方面比較昂貴

  • 金錢:你真的有那麼多錢爲每個應用啓動一個EC2實例?另外你能預測到需要多少個實例麼?如果你以後需要更多的資源,你需要停止VM進行升級——否則就要爲閒置資源白白付錢,直到真正用起來(除非你用能動態調整大小的Solaris Zones,比如Joyent上的)。

  • 時間:虛擬機相關的操作大多都很慢:啓動要幾分鐘,捕捉快照要幾分鐘,創建鏡像也需要幾分鐘。世界不停轉動,我們可沒有這種時間!

我們能做得更好嗎?

進入Docker的世界吧。

Docker是由公共PaaS提供商dotCloud的人發起的開源項目,於去年初發起。從技術角度來說,Docker(主要用Go語言編寫)試圖簡化兩種已有技術的使用:

  • LXC:Linux容器,允許獨立進程在比普通Unix進程更高的隔離級別上運行。使用的技術術語是集裝箱化:一個容器裏運行一個進程。容器支持的隔離級別有:

    • 文件系統:容器只能訪問自己的沙箱文件系統(類似於chroot),否則要專門掛載到容器的文件系統中才能訪問。

    • 用戶名字空間:容器有自己的用戶數據庫(也就是容器的root不等於主機的root賬戶)。

    • 進程名字空間:只有容器裏的進程纔是可見的(ps aux的輸出會非常簡潔)。

    • 網絡名字空間:每個容器都有自己的虛擬網絡設備和虛擬IP(因此它可以綁定任意端口,不用佔用主機端口)。

  • AUFS:高級多層的統一文件系統,可用來創建聯合、寫時拷貝的文件系統。

Docker可以安裝在任何支持AUFS和內核版本大於等於3.8的Linux系統上。但從概念上來說它並不依賴於這些技術,以後也可以和類似的技術一起運行,例如Solaris的ZonesBSD jails,並將ZFS作爲文件系統。不過目前只能選擇Linux 3.8+和AUFS。

那Docker爲什麼有意思呢?

  • Docker非常輕量。啓動VM是個大動作,需要佔用大量內存;而啓動Docker容器只耗費很少的CPU和內存,並且非常快。幾乎和啓動一個常規進程沒什麼區別。不僅運行容器快,構建鏡像、捕獲文件系統的快照也很快。

  • 它運行在已經虛擬化過的環境中。也就是說,你可以在EC2實例、Rackspace VM或VirtualBox裏運行Docker。事實上,在Mac和Windows上使用Docker的首選方式是使用Vagrant

  • Docker容器能移植到任何運行Docker的操作系統上。無論是Ubuntu還是CentOS,只要Docker運行着,你的容器就能運行。

讓我們回到前面的部署、操作問題列表,看看Docker是怎麼解決的:

    1. 隔離性:Docker在文件系統和網絡級別隔離了應用。從這個意義上來講很像在運行”真正的“虛擬機。

    2. 重複性:用你喜歡的方式準備系統(登錄並在所有軟件裏執行apt-get命令,或者使用Dockerfile),然後把修改提交到鏡像中。你可以隨意實例化若干個實例,或者把鏡像傳輸到另一臺機器,完全重現同樣的設置。

  • 安全性:Docker容器比普通的進程隔離更爲安全。Docker團隊已經確定了一些安全問題,正在着手解決。

  • 資源約束:Docker現在能限制CPU的使用率和內存用量。目前還不能直接限制磁盤的使用情況。

  • 易於安裝:Docker有一個Docker Index,這個倉庫存儲了現成的Docker鏡像,你用一條命令就可以完成實例化。比如說,要使用Clojure REPL鏡像,只要運行docker run -t -i zefhemel/clojure-repl命令就能自動獲取並運行該鏡像。

  • 易於移除:不需要應用了?銷燬容器就行。

  • 升級、降級:和EC2 VM一樣:先啓動應用的新版本,然後把負載均衡器切換到新的端口。

  • 快照、備份:Docker能提交鏡像並給鏡像打標籤,和EC2上的快照不同,Docker是立即處理的


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