將Docker作為應用程序容器管理系統已經在最近兩年當中成為眾多開發人員及系統工程師們的標準實踐方式。有一部分朋友甚至表示,容器方案是自OpenSSH之后最為可觀且值得肯定的技術飛躍。Docker目前已經成為技術領域當之無愧的新生力量,且被廣泛應用于各類云系統架構當中。然而除此之外,Docker還需要了解如何贏得開發人員們的芳心。
下面我們將一起了解Docker的發展歷程,未來將要面對的競爭形勢以及對發展前景的預估。
那么,Docker到底是什么?
Docker是一款使用libcontainer的微容器管理工具。作為Solomon Hykes利用Go語言開發而成的項目,Docker于2013年轉入開源并被快速應用在諸多領域當中。這款工具的出色靈活性甚至使其成為游戲規則的改變者。
在Docker出現之前,創建一套應用程序容器需要掌握多種相對比較先進的概念。LXC已經在這一領域占據了相當可觀的市場份額,其賣點在于提供“純虛擬化”解決方案并借此賺取利潤。OpenVZ與Xen也在市場上擁有一定地位。不過這些系統在設計方面仍然很大程度上面向服務器解決方案,而且需要配合相當程度的配置工作。
這里我們要澄清一點:Docker的作用并不是取代LXC、OpenVZ或者Xen。它也并不是一套像KVM、VirtualBox以及VMware那樣的虛擬化解決方案。Docker擁有屬于自己的定位視角、獨特的運作方式而且具備完全不同的功能出發點。
與OpenVZ、Xen以及LXC一樣,Docker也采用rootfs原則——這實際上就是一套root文件系統。它采用樹狀結構作為遠程系統的root(類似于chroot的作用),同時提供網絡層與設置系統。但它同時也有著自己的一些獨特設計。
首先,它的鏡像與容器通過union mount文件系統(例如aufs以及devicemapper等)進行分層。這一方面節約了磁盤存儲空間,另一方面也能夠幫助我們在無需復制整套root的前提下快速構建容器環境。
另一大差異在于,Docker回避了訪客系統當中的初始化步驟。換句話來說,容器的root只會被用作指定應用程序的運行環境。
最后,Docker擁有對鏡像版本的注冊與控制能力,這也正是其步入標準化的重要標志。在默認情況下,Docker會使用公共注冊表。該注冊表提供多套現成可用的鏡像(既包括官方給出的正式鏡像,亦擁有由社區用戶提交的鏡像),同時也為后續付費提供了實現空間。從理論層面講,Docker在很大程度上與Git類似,而其Hub則類似于GitHub這樣的服務方案。Docker同時采用多種常見概念,例如提交、標簽以及遠程注冊服務器等等。
圍繞Docker項目建立起的技術社區非常活躍,其中提供大量用于自動啟動(fig,也就是現在的Docker Compose)、簡化云集成及管理流程(CoreOS)以及實現監控任務(cAdvisor)的工具,而且這份工具清單還在不斷拓展。
時至今日,Docker已經席卷了整個IT領域。OpenStack、Amazon、谷歌、CoreOS等等都在高度關注這項技術成果,甚至已經將其整合到了自己的基礎設施當中。
不過激烈的市場競爭也即將到來!
提高系統便捷度
Docker的主要訴求無疑在于簡化容器創建流程,從而更為便捷地實現微服務架構管理。首先需要強調的是,容器本身其實是一種對應用程序進行完全隔離的手段。歸功于其libcontainer庫,Docker能夠在整個cgroup管理流程當中始終實現內存與線程的徹底隔離。
除非使用者進行特殊指定,否則Docker不會開啟主機設備上的任何一個端口。如果兩套容器系統需要通過IP層進行通信,它們可以彼此連通,從而直接利用容器名稱而非IP地址實現信息交互(因為IP地址可能隨著容器重啟而發生變化)。
云規模伸縮
Docker已經在云環境下獲得極高人氣,這主要是由于其極低的運行資源需求、出色的分卷管理以及能夠顯著降低磁盤存儲空間需求的union mount文件系統。在研究Docker運作機制的過程當中,大家會發現我們能夠非常輕松地利用它創建出一套具備可擴展性且/或高可用性的系統方案。
“docker”命令實際上是一種簡單的REST客戶端,旨在同daemon進行通信。在默認情況下,該服務(daemon)會創建一個unix socket(位置為/var/run/docker.sock)來提供該API。而“docker”命令將僅僅使用該API。
該API可以被用于監聽各類事件,包括容器何時創建、啟用或者停止。利用該API所提供的信息,大家能夠輕松掌握哪套容器系統目前正在運行哪種服務并使用哪個端口等等。
如果大家不打算或者沒有能力使用CoreOS、OpenStack等所要求的架構,那么也完全可以創建自己的架構及工具——而且整個過程并不困難。該API相當易于訪問且效率極高。
下面請大家一起來看我們當前項目中的一個架構示例:
我們采取以下規劃方式:
每臺物理從服務器都配備有一項發現服務,用于監聽該Dockers socket。
當某套容器系統啟用或者停止時,該服務會將信息發送至主服務器。
該主服務器隨后能夠采納適當的措施,例如修改nginx服務器配置或者刪除/移除一臺上流服務器等。
另一種選項則是對Docker的配置進行修改,從而保證該API能夠在TCP模式下接受訪問(即使其擁有網絡可訪問能力)。在這種特定情況下,小型客戶端能夠與所有從服務器相對接,并監聽其中發生的全部事件。不過這種方式的基本原則仍然相同:每個事件都將允許管理員在nginx當中(假設使用nginx)對一臺上游服務器進行添加或者刪除。
二者的差別在于,這里主服務器必須處理全部指向所有從服務器的連接。而前一種方式的運行成本更低,因為所有從服務器都接入到主服務器中。
在這兩類情況下,主服務器能夠在每一套容器系統啟用或者停止時得到通知,并可以修改主nginx服務器、重啟容器或者規避事故發生。
當然,我們也可以同時設置兩臺主服務器來實現故障轉移管理。這種解決方案完全可行而且易于維護。
為開發人員行方便
毫無疑問,Docker非常適合系統管理員使用。但除此之外,它也能夠在生產流程當中扮演重要角色,也就是面向開發人員。我們曾經為客戶提供的一套解決方案就將Dockerfile與docker-compose文件結合在了一起(由Docker進行fig項目的檢索)。
這一思路是首先定義開發人員的工作站在運行項目時需要哪些必備要素,而后創建Dockerfile(如果需要)以建立有針對性的鏡像方案,同時將一個docker-compose.yml文件與這些容器相對接。
在此之后,當使用版本控制服務器(例如Git、Mercurial以及SVN等等)時,大家可以輕松設置該項目目錄,從而將這些文件以及項目源代碼添加到其中,并為容器指定所要使用的存儲分卷。接下來,技術團隊可以檢索該項目,而且只需要使用“docker-compose up”這一條命令即可啟用該服務。
讓我們以一個Drupal項目為例,在這里我們要使用兩套容器系統:
一套MySQL容器
一套包含有Apache加PHP模塊的容器
Drupal的源代碼被旋轉在“/src”之下,并會被發送至Apache容器當中。而這也正是分卷的基本原則:主機上的一個本地目錄或者文件可以被連接到特定目錄下的一套或者多套容器處。在此之后,大家可以利用同樣的方法處理MySQL存儲目錄,從而避免被保存在數據庫內的記錄發生丟失。
下面是Dockerfile內容示例:
FROM debian:7
MAINTAINER [email protected]
# Install software
RUN apt-get update && apt-get install apache2 php5 php5-mysql libapache2-mod-php5
# Start Apache
CMD /usr/sbin/apache2ctl -D FOREGROUND
接下來是docker-compose.yml文件內容示例:
web:
dockerfile: .
volumes:
- "./src:/var/www/drupal
ports:
- "8080:80"
links:
- "db"
db:
image: mysql
volumes:
- "./data:/var/lib/mysql"
其中“web”服務被鏈接至“db”中(參閱以上示例中的‘links’命令),因此它能夠讀取用于提供MySQL地址及端口(由Dockerfile負責提供)的各環境變量。
[page]舉例來說,以下變量皆可在“web”容器當中接受訪問:
DB_PORT_3306_TCP_ADDR=172.17.1.24
DB_PORT_3306_TCP_PORT=3306
其它種種
大家當然也可以使用其它容器稱,示例當中的“web”與“db”代表的是兩套容器當中的設備名稱。
換句話來說,“mysql://db”這一地址也可以變更。接下來,大家需要修改Drupal配置文件來訪問該數據庫,完成后工作到此結束。該項目將具備以下結構:
”data/”用于存儲MySQL數據
”src/”用于容納Drupal源代碼
”Dockerfile”用于創建Apache/PHP鏡像
”docker-compose.yml”用于描述容器的啟動方式
為了保證示例的簡單性,我們并沒有提到Apache配置文件以及各容器如何共享各個分卷。總結來講,就是這套Web服務器的配置可以隨意進行修改。
大家可能還注意到,綁定的端口也已經得到處理。由于開發人員用不著獲得使用端口80的權限,因此我們利用本地端口8080來映射Apache容器的端口80。開發人員只需要訪問127.0.0.1:8080即可查看當前處于運作狀態的Drupal實例。
為了理解這套對接體系,請大家參閱以下圖表。
競爭關系
就目前的形勢看,Docker似乎成了世界上惟一一項沐浴在贊美當中的容器技術成果。然而請記住,Docker使用libcontainer與cgroups,這意味著為了能夠使用這些內核的功能,該服務必須以root方式運行。而這很可能招致安全問題。
這實際正是CoreOS以及其它同類方案批評Docker的主要著眼點——但值得一提的是,這項技術確實極具吸引力,也支撐著CoreOS創建出了當下最具知名度的云系統方案之一。Docker需要root權限來接入cgroups,但以root角色運行的服務確實很可能給系統造成安全漏洞。
Docker的開發團隊就此給出過禮貌的回應。很明顯,他們將在未來的版本升級當中考慮這一問題,而且歡迎大家提出任何能夠解決這些缺陷的建議(不過迄今為止,Docker還沒真正惹出過任何麻煩)。不過各位讀者朋友別慌:這項漏洞被真正利用的可能性非常之低。截至目前,惟一一次安全問題出現在2014年的1.0版本當中,而且現在問題已經得到解決。
總而言之,CoreOS決定創建自己的一套容器系統(能夠使用Docker鏡像),名為Rkt(發音同火箭,即‘rocket’)。但就目前的情況看,大多數用戶將繼續在CoreOS解決方案的基礎之上使用Docker。就在Rkt剛剛發布之時,LinuxContainers(LXC背后的大型項目)亦宣稱計劃與Cannonical公司合作開發LXD。
如大家所見,容器管理領域的一舉一動都在盡可能向內核靠攏,而由此帶來的結果就是其性能水平將不斷提升。
時間逐漸推移,容器的必要性也變得愈發凸顯。
但Windows與OS X又會如何?對于OS X來說,目前還沒有相關聲明出爐,更不存在任何產品可供選擇。因此,使用boot2docker(一套專門用于運行Docker的虛擬機)也就成了惟一的出路。Windows目前同樣需要依賴于boot2docker,不過微軟公司最近在聲明中指出,未來的微軟操作系統將直接納入容器機制。具體如何,我們將拭目以待……
總結陳詞
很明顯,Docker是一項適用于開發及系統管理工作的技術成果。它能夠不斷提供精簡效果并改善性能水平,同時具備良好的可行性,這一切使得用戶能夠以前所未有的方式輕松建立服務。無論您的基礎設施到底處于何種規模,相信Docker都能助大家一臂之力。
除此之外,它的亮點也完全能夠體現在生產流程當中。如今開發工作正變得日趨標準化,而開發人員與系統之間的界線也變得越來越精細。我們期待著Docker下個版本的正式降臨,希望到時候它能夠提供更具吸引力的競爭優勢。
就目前來看,Docker仍然是容器領域的惟一王者。
原文標題:How to get systems administrators and developers to agree with Docker