大數(shù)據(jù)平臺(tái)Docker應(yīng)用之路
隨著大數(shù)據(jù)平臺(tái)型產(chǎn)品方向的深入應(yīng)用實(shí)踐和Docker開(kāi)源社區(qū)的逐漸成熟,業(yè)界有不少的大數(shù)據(jù)研發(fā)團(tuán)隊(duì)開(kāi)始擁抱Docker。簡(jiǎn)單來(lái)說(shuō),Docker會(huì)讓Hadoop平臺(tái)部署更加簡(jiǎn)單快捷、讓研發(fā)和測(cè)試團(tuán)隊(duì)集成交付更加敏捷高效、讓產(chǎn)線(xiàn)環(huán)境的運(yùn)維更加有質(zhì)量保障,而這背后的業(yè)務(wù)場(chǎng)景和具體的實(shí)踐方法有哪些?在Docker容器服務(wù)逐步走向完善的過(guò)程中,大數(shù)據(jù)平臺(tái)產(chǎn)品Docker模式的應(yīng)用又是如何解決的?正是本文所著重闡述的。
實(shí)踐中發(fā)現(xiàn)問(wèn)題
場(chǎng)景一
在大數(shù)據(jù)平臺(tái)型產(chǎn)品的開(kāi)發(fā)過(guò)程中,經(jīng)常要跟許多模塊打交道,包括Hadoop、HBase、Hive、Spark、Sqoop、Solr、Zookeeper……等多達(dá)幾十個(gè)開(kāi)源組件,為了不影響團(tuán)隊(duì)成員間的工作任務(wù)協(xié)同,開(kāi)發(fā)人員其實(shí)非常需要自己有一套獨(dú)立的集群環(huán)境,以便反復(fù)測(cè)試自己負(fù)責(zé)的模塊,可真實(shí)的企業(yè)開(kāi)發(fā)環(huán)境往往只有一兩個(gè)大的虛擬集群,這可怎么辦?難道要給每個(gè)開(kāi)發(fā)人員都配幾臺(tái)獨(dú)立的物理機(jī)器?
場(chǎng)景二
針對(duì)每一次新版本的發(fā)布,產(chǎn)品測(cè)試組都需要反復(fù)的重裝整個(gè)平臺(tái)以便發(fā)現(xiàn)問(wèn)題,而正如本文前面所闡述的那樣,大數(shù)據(jù)平臺(tái)所依賴(lài)的組件繁多,不同組件模塊依賴(lài)的底層庫(kù)也不盡相同,經(jīng)常會(huì)出現(xiàn)各種依賴(lài)沖突問(wèn)題,而一旦安裝完成,就很難再讓Linux系統(tǒng)恢復(fù)到一個(gè)非常干凈的狀態(tài),通過(guò)Remove、UnInstall、rpm -e等手動(dòng)方式卸載,往往需要花費(fèi)很長(zhǎng)的時(shí)間,那如何才能快速地恢復(fù)大數(shù)據(jù)平臺(tái)集群的系統(tǒng)環(huán)境?
場(chǎng)景三
當(dāng)測(cè)試人員在測(cè)試大數(shù)據(jù)平臺(tái)過(guò)程中發(fā)現(xiàn)了一個(gè)Bug,需要保存現(xiàn)場(chǎng),這里面包括相關(guān)的大數(shù)據(jù)組件配置、進(jìn)程狀態(tài)、運(yùn)行日志、還有一些中間數(shù)據(jù),可是,平臺(tái)集群服務(wù)器節(jié)點(diǎn)數(shù)量很多,針對(duì)每個(gè)進(jìn)程的配置目錄和日志文件,都相對(duì)較獨(dú)立,一般都需要專(zhuān)業(yè)的開(kāi)發(fā)工程師或者運(yùn)維工程師進(jìn)入相關(guān)服務(wù)器節(jié)點(diǎn),按照不同組件的個(gè)性化配置信息,手工方式收集所需的各個(gè)條目信息,然后打包匯集到日志中心服務(wù)器進(jìn)行統(tǒng)一分析,而目前業(yè)界并沒(méi)有一款能夠自動(dòng)分布式收集故障相關(guān)的日志系統(tǒng),但測(cè)試工作還要繼續(xù),怎么辦?
場(chǎng)景四
如何把一個(gè)部署好的大數(shù)據(jù)平臺(tái)快速地遷移到其它地方?
你得注意以下幾點(diǎn):
- 如果是關(guān)鍵業(yè)務(wù)系統(tǒng),數(shù)據(jù)不能丟;
- 如果是遷移物理機(jī),機(jī)器可能會(huì)壞;
- 如果是不間斷實(shí)時(shí)在線(xiàn)業(yè)務(wù),要保證快速平穩(wěn)切換。
傳統(tǒng)解決方案的缺陷
想要解決這些問(wèn)題,第一個(gè)想到的方案當(dāng)然是用虛擬機(jī),而筆者經(jīng)歷的團(tuán)隊(duì),之前也確實(shí)用的就是虛擬機(jī),但這種方式并不能完美的解決以上問(wèn)題,比如:
- 雖然虛擬機(jī)也可以完成系統(tǒng)環(huán)境的遷移,但這并不是它所擅長(zhǎng)的,不夠靈活,很笨重。
- 虛擬機(jī)的快照可以保存當(dāng)前的狀態(tài),但要恢復(fù)回去,就得把當(dāng)前正在運(yùn)行的虛擬機(jī)關(guān)閉,所以并不適合頻繁保存當(dāng)前狀態(tài)的業(yè)務(wù)場(chǎng)景。
- 雖然可以給每個(gè)人都分配幾個(gè)虛擬機(jī)用,但它是一個(gè)完整的系統(tǒng),本身需要較多的資源,底層物理機(jī)的資源很快就被用完了,所以我們需要尋找其它方式來(lái)彌補(bǔ)這些不足。
Docker技術(shù)的引入
Docker 項(xiàng)目的目標(biāo)是實(shí)現(xiàn)輕量級(jí)的操作系統(tǒng)虛擬化解決方案,換句話(huà)說(shuō),它可以讓我們把一臺(tái)物理機(jī)虛擬成多臺(tái)來(lái)使用,而且它還可以保存修改、完整遷移到其它地方、性能損耗小等等好處,能夠很好解決我們之前遇到的問(wèn)題。
那為什么不用虛擬機(jī)方案?
簡(jiǎn)單來(lái)說(shuō),因?yàn)樗忍摂M機(jī)更輕便,啟動(dòng)一個(gè)Docker容器只要幾秒種的時(shí)間,在一臺(tái)物理機(jī)上可以創(chuàng)建幾百上千個(gè)容器,而虛擬機(jī)做不到。
下面是虛擬機(jī)與Docker兩種方案的實(shí)現(xiàn)原理:
虛擬機(jī)實(shí)現(xiàn)資源隔離的方法是利用獨(dú)立的OS,并利用Hypervisor虛擬化CPU、內(nèi)存、IO設(shè)備等實(shí)現(xiàn)的。例如,為了虛擬CPU,Hypervisor會(huì)為每個(gè)虛擬的CPU創(chuàng)建一個(gè)數(shù)據(jù)結(jié)構(gòu),模擬CPU的全部寄存器的值,在適當(dāng)?shù)臅r(shí)候跟蹤并修改這些值。需要指出的是在大多數(shù)情況下,虛擬機(jī)軟件代碼是直接跑在硬件上的,而不需要Hypervisor介入。只有在一些權(quán)限高的請(qǐng)求下,Guest OS需要運(yùn)行內(nèi)核態(tài)修改CPU的寄存器數(shù)據(jù),Hypervisor會(huì)介入,修改并維護(hù)虛擬的CPU狀態(tài)。
Hypervisor虛擬化內(nèi)存的方法是創(chuàng)建一個(gè)shadow page table。正常的情況下,一個(gè)page table可以用來(lái)實(shí)現(xiàn)從虛擬內(nèi)存到物理內(nèi)存的翻譯。在虛擬化的情況下,由于所謂的物理內(nèi)存仍然是虛擬的,因此shadow page table就要做到:虛擬內(nèi)存->虛擬的物理內(nèi)存->真正的物理內(nèi)存。
對(duì)比虛擬機(jī)實(shí)現(xiàn)資源和環(huán)境隔離的方案,docker就顯得簡(jiǎn)練很多。docker Engine可以簡(jiǎn)單看成對(duì)Linux的NameSpace、Cgroup、鏡像管理文件系統(tǒng)操作的封裝。docker并沒(méi)有和虛擬機(jī)一樣利用一個(gè)完全獨(dú)立的Guest OS實(shí)現(xiàn)環(huán)境隔離,它利用的是目前Linux內(nèi)核本身支持的容器方式實(shí)現(xiàn)資源和環(huán)境隔離。簡(jiǎn)單的說(shuō),docker利用namespace實(shí)現(xiàn)系統(tǒng)環(huán)境的隔離;利用Cgroup實(shí)現(xiàn)資源限制;利用鏡像實(shí)現(xiàn)根目錄環(huán)境的隔離。
當(dāng)新建一個(gè)容器時(shí),docker不需要和虛擬機(jī)一樣重新加載操作系統(tǒng)內(nèi)核。我們知道,引導(dǎo)、加載操作系統(tǒng)內(nèi)核是一個(gè)比較費(fèi)時(shí)費(fèi)資源的過(guò)程,當(dāng)新建一個(gè)虛擬機(jī)時(shí),虛擬機(jī)軟件需要加載Guest OS,這個(gè)新建過(guò)程是分鐘級(jí)別的。而docker由于直接利用宿主機(jī)的操作系統(tǒng),則省略了這個(gè)過(guò)程,因此新建一個(gè)docker容器只需要幾秒鐘。另外,現(xiàn)代操作系統(tǒng)是復(fù)雜的系統(tǒng),在一臺(tái)物理機(jī)上新增加一個(gè)操作系統(tǒng)的資源開(kāi)銷(xiāo)是比較大的,因此,docker對(duì)比虛擬機(jī)在資源消耗上也占有比較大的優(yōu)勢(shì)。事實(shí)上,在一臺(tái)物理機(jī)上我們可以很容易建立成百上千的容器,而只能建立幾個(gè)虛擬機(jī)。
可見(jiàn)容器是在操作系統(tǒng)層面上實(shí)現(xiàn)虛擬化,直接復(fù)用本地主機(jī)的操作系統(tǒng),而傳統(tǒng)方式則是在硬件層面實(shí)現(xiàn)。當(dāng)然,一些容器核心模塊依賴(lài)于高版本內(nèi)核,存在部分版本兼容問(wèn)題。
如何基于Docker實(shí)現(xiàn)大數(shù)據(jù)平臺(tái)的敏捷部署與運(yùn)維?
第一步:搭建基礎(chǔ)的Docker環(huán)境
在實(shí)踐過(guò)程中,部署一套可用的大數(shù)據(jù)平臺(tái)Docker環(huán)境,必需做好以下前提工作:
- 搭建私有鏡像倉(cāng)庫(kù),用來(lái)統(tǒng)一存放構(gòu)建好的鏡像文件
- 搭建一個(gè)安裝包倉(cāng)庫(kù),用來(lái)存放我們發(fā)布的各種版本的大數(shù)據(jù)組件安裝包
- 配置多個(gè)物理機(jī)上的Dcoker容器可以相互通信,可參考官方給出的方案
第二步:為大數(shù)據(jù)平臺(tái)定制基礎(chǔ)鏡像
1.既然要在Docker容器內(nèi)安裝我們的大數(shù)據(jù)平臺(tái),那就需要一個(gè)統(tǒng)一的Linux系統(tǒng)做為我們的Dcoker容器,像Ubuntu、CentOS等發(fā)行商都會(huì)發(fā)布自己的Docker基礎(chǔ)鏡像到Docker Hub上,如果Docker Hub上恰好沒(méi)有你需要的鏡像,也可以自己制作。
2.比如用CentOS6.8做為我們的基礎(chǔ)鏡像,那么請(qǐng)先把它pull下來(lái)
3.然后我們用這個(gè)鏡像創(chuàng)建一個(gè)容器,并在里面配置一些我們大數(shù)據(jù)平臺(tái)依賴(lài)的參數(shù),比如ntpd、httpd服務(wù)等等,最終生成我們平臺(tái)專(zhuān)屬的基礎(chǔ)鏡像。
4.這是很關(guān)鍵的一步,有了它以后,所有人員可以隨時(shí)創(chuàng)建一個(gè)自己需要的Linux環(huán)境出來(lái),以便在其內(nèi)進(jìn)行產(chǎn)品的研究和實(shí)驗(yàn),且每個(gè)人的環(huán)境互不相干,當(dāng)容器內(nèi)的環(huán)境被破壞后,可以刪掉再創(chuàng)建,這樣一來(lái),場(chǎng)景一和場(chǎng)景二所遇到的問(wèn)題也就迎刃而解。
第三步:將已經(jīng)部署好的集群做成鏡像
我們可以把已經(jīng)部署了集群的容器保存成多種鏡像,如:只包含了Hadoop的集群、同時(shí)包含Hadoop、Zookeeper、Hbase的集群,或安裝了所有組件的集群等等,然后上傳到私有倉(cāng)庫(kù),其它人需要的時(shí)候,直接啟動(dòng)自已需要的集群就可以了,因?yàn)槊馊チ瞬渴钆c配置等步驟,因而大幅度提高了工作效率,也提高了產(chǎn)品迭代速度。
上圖是已經(jīng)做好的鏡像,圖中共三種類(lèi)型的鏡像:
- 第一個(gè)箭頭指基礎(chǔ)鏡像
- 第二個(gè)箭頭指的是已經(jīng)安裝了大數(shù)據(jù)平臺(tái)的鏡像,因?yàn)槭欠植际?,所以有五個(gè)
- 第三個(gè)是單節(jié)點(diǎn)版的大數(shù)據(jù)集群,所以只有一個(gè)鏡像
第四步:鏡像的修改與保存
Docker提供了commit功能可以將一個(gè)正在運(yùn)行的容器保存起來(lái),假如在測(cè)試過(guò)程中遇到一個(gè)Bug并且需要先保存下來(lái),執(zhí)行一條簡(jiǎn)單的命令即可,如:
- # docker commit container_name image:v2
在以后需要復(fù)現(xiàn)的時(shí)候用這個(gè)鏡像創(chuàng)建容器即可,像下面這樣
- # docker run -tid –name c1 image:v2 bash
但注意,并不是所有狀態(tài)都能被保存下來(lái),它只保存文件層面的狀態(tài),不能保存內(nèi)存中的狀態(tài),所以再次啟動(dòng)容器的時(shí)候,容器內(nèi)的所有服務(wù)都已經(jīng)變成了停止?fàn)顟B(tài),需要再手動(dòng)啟動(dòng)一次,這樣就導(dǎo)致有些類(lèi)型的Bug不能復(fù)現(xiàn)。
不過(guò)欣慰的是,Docker官方打算在后面的版本中加入checkpiont功能,它可以保存容器中的所有狀態(tài),這樣就可以完整地復(fù)現(xiàn)Bug,這個(gè)新功能的用法就像下面這樣:
這個(gè)功能對(duì)很多人來(lái)說(shuō),絕對(duì)是個(gè)好消息!
第五步:腳本化部署、監(jiān)視、刪除
當(dāng)然了,每個(gè)人都不應(yīng)該把過(guò)多的精力放在怎么使用Docker的問(wèn)題上,這樣會(huì)為團(tuán)隊(duì)帶來(lái)額外的工作量,最簡(jiǎn)單的辦法當(dāng)然是把所有重復(fù)性的工作腳本化,向每個(gè)人提供最簡(jiǎn)便的使用接口,只需要一條簡(jiǎn)單的命令就可以創(chuàng)建自己想要的集群環(huán)境,當(dāng)不需要的時(shí)候一條命令即可刪除,這樣即降低了學(xué)習(xí)成本又解決了容器管理問(wèn)題。
根據(jù)筆者的實(shí)踐經(jīng)驗(yàn),腳本化的實(shí)現(xiàn)應(yīng)該著重考慮幾個(gè)方面:
- 多種類(lèi)型集群的創(chuàng)建
- 記錄每個(gè)集群的所屬者,容器所屬的物理機(jī),創(chuàng)建時(shí)間等等
- 可實(shí)時(shí)查看所有容器的運(yùn)行狀態(tài),物理機(jī)資源使用情況
- 刪除指定的集群
結(jié)語(yǔ)
現(xiàn)在已經(jīng)有很多開(kāi)源的Docker容器管理框架,但需求總是復(fù)雜多變的,并不能適用所有的場(chǎng)景。比如筆者所負(fù)責(zé)的大數(shù)據(jù)平臺(tái)就需要為每個(gè)容器做端口映射、內(nèi)含大數(shù)據(jù)組件的鏡像在啟動(dòng)后還需做Hostname與IP映射等,總之,目前開(kāi)源容器框架的易用性還有很大的改進(jìn)空間,都存在一些手動(dòng)配置的工作。
關(guān)于容器服務(wù),在具體的實(shí)踐過(guò)程中,一定還會(huì)遇到很多問(wèn)題,比如服務(wù)發(fā)現(xiàn)和編排。當(dāng)下在應(yīng)用層面雖還算不上特別的成熟,但已經(jīng)使原本部署與配置很復(fù)雜的大數(shù)據(jù)平臺(tái)變得簡(jiǎn)單快速,讓一部分研發(fā)團(tuán)隊(duì)的產(chǎn)品迭代得到加速。當(dāng)然,不管是大數(shù)據(jù)平臺(tái)產(chǎn)品,還是Docker開(kāi)源社區(qū)本身,都還在不斷的完善中。
本文由 聯(lián)想大數(shù)據(jù)團(tuán)隊(duì) 投稿至36大數(shù)據(jù),并經(jīng)由36大數(shù)據(jù)編輯發(fā)布,轉(zhuǎn)載必須獲得原作者和36大數(shù)據(jù)許可,并標(biāo)注來(lái)源36大數(shù)據(jù)http://www.36dsj.com/archives/75999,任何不經(jīng)同意的轉(zhuǎn)載均為侵權(quán)。