田 源,李 樊,汪曉臣,趙偉慧,黃志威
(1. 中國鐵道科學(xué)研究院集團有限公司 電子計算技術(shù)研究所, 北京 100081;2. 軌道交通系統(tǒng)測試國家工程實驗室, 北京 100081)
乘客信息系統(tǒng)(PIS)采用中心-車站-車載的多層級架構(gòu),由控制中心統(tǒng)一管理各級設(shè)備[1]。目前的軟件部署采用單機拷貝安裝方式,面對數(shù)量龐大的設(shè)備集群,需要逐個設(shè)備安裝調(diào)試。部署過程中容易暴露出諸多弊端,如軟件運行環(huán)境配置導(dǎo)致的未知錯誤;單機拷貝和配置的安裝方式耗費人力;軟件版本升級或同步容易出錯;應(yīng)用與數(shù)據(jù)的耦合性較緊;硬件設(shè)備更換后,軟件需重新部署等。
目前,Docker技術(shù)在越來越多的場景中得到了應(yīng)用。張兆晨等人[2]設(shè)計了一種持續(xù)集成系統(tǒng),利用Docker的鏡像封裝和輕量級特性,取代了傳統(tǒng)持續(xù)集成系統(tǒng)的虛擬機架構(gòu),提升了開發(fā)效率,降低了系統(tǒng)占用資源;鄒保平等人[3]通過與傳統(tǒng)虛擬機比較的方式,驗證了Docker容器化部署應(yīng)用的敏捷性;姚煒等人[4]在傳統(tǒng)開發(fā)平臺中引入Docker技術(shù),簡化了從開發(fā)到部署的繁雜配置,有效提升了項目的發(fā)布速度。綜上所述,基于Docker的容器化部署方案適用于開發(fā)與發(fā)布緊密結(jié)合、安裝配置繁雜的軟件部署場景。Docker技術(shù)的引入,將有效解決當(dāng)下乘客信息系統(tǒng)中軟件部署的諸多難點。
在乘客信息系統(tǒng)中,傳統(tǒng)的應(yīng)用軟件部署方式是通過存儲介質(zhì)或網(wǎng)絡(luò)傳輸?shù)姆绞?,拷貝軟件安裝包至目標(biāo)機。然后在操作系統(tǒng)中配置軟件運行所需的依賴環(huán)境,安裝軟件并進(jìn)行配置,執(zhí)行二進(jìn)制文件或腳本來運行程序,提供軟件服務(wù)。乘客信息系統(tǒng)中,車站設(shè)備數(shù)量多達(dá)上百臺,分布距離較遠(yuǎn),逐個設(shè)備部署、安裝、調(diào)試的工作量非常巨大,后期對于軟件的部署架構(gòu)調(diào)整和版本維護都不友好。
容器是輕量級的操作系統(tǒng)級虛擬化。它可以實現(xiàn)在一個資源隔離的進(jìn)程中運行應(yīng)用及其依賴項[5]。應(yīng)用程序與其所依賴的環(huán)境,可以被封裝成鏡像,并可以復(fù)用。應(yīng)用需要被部署到目標(biāo)機時,僅需在目標(biāo)機上獲取鏡像,將其實例化為容器進(jìn)程,運行即可。當(dāng)軟件或依賴環(huán)境產(chǎn)生變化,只需更新鏡像即可。如此,將操作系統(tǒng)與應(yīng)用程序相關(guān)的環(huán)境獨立開,可降低部署難度,提升軟件的可維護性,保證線路軟件部署質(zhì)量的統(tǒng)一性。容器技術(shù)具有以下優(yōu)勢:
(1)敏捷環(huán)境:容器的啟動速度快,更新便捷。
(2)高效生產(chǎn):開發(fā)人員不用擔(dān)心生產(chǎn)環(huán)境下特殊的運行環(huán)境,實現(xiàn)一處調(diào)試,處處運行的高質(zhì)量軟件發(fā)布效果。
(3)版本控制:容器必須由鏡像生成,鏡像的版本唯一決定了運行容器的一致性。
(4)輕便:鏡像文件占用空間小,且僅包含應(yīng)用程序和關(guān)鍵依賴,方便軟件歸檔和版本分發(fā)。
Linux 容器( LXC,Linux Container)是一個在單一 Linux 主機上提供多個隔離的Linux 環(huán)境的操作系統(tǒng)級虛擬技術(shù)[6]。Docker是一個基于LXC 的高級容器引擎[7]。Docker的沙箱機制有效的隔離各個用戶實例,多容器共享系統(tǒng)內(nèi)核的特性使得Docker實例輕量化,便于部署[8]。
Docker服務(wù)部署在宿主機操作系統(tǒng)之上。如圖1所示,Docker將應(yīng)用及其依賴環(huán)境封裝在容器中運行。容器是操作系統(tǒng)為不同的用戶或進(jìn)程分配的具有一定相互獨立空間(包括內(nèi)存分頁空間、CPU時鐘分配、硬盤空間、進(jìn)程空間、運行庫等、IP地址)。
本文在傳統(tǒng)乘客信息系統(tǒng)的架構(gòu)之上,引入Docker虛擬化技術(shù)。軟件供應(yīng)商將既有應(yīng)用軟件進(jìn)行鏡像封裝,依據(jù)Docker私有倉庫(Registry)規(guī)范,搭建一套應(yīng)用軟件管理系統(tǒng)。
圖 1 Docker技術(shù)架構(gòu)
該系統(tǒng)接入中心機房的核心交換機,負(fù)責(zé)管理乘客信息系統(tǒng)全部的應(yīng)用鏡像,并向各層級設(shè)備群提供鏡像下載服務(wù),如圖2所示。
圖 2 基于Docker的乘客信息系統(tǒng)部署架構(gòu)
應(yīng)用軟件管理系統(tǒng)由軟件倉庫管理工作站和軟件倉庫服務(wù)器組成。軟件供應(yīng)商提供初始的Docker鏡像。鏡像文件經(jīng)管理工作站,推送至軟件倉庫服務(wù)器。軟件倉庫服務(wù)器宜采用主備集群策略,保證倉庫鏡像存儲的高可靠性。結(jié)合Docker輕量、敏捷的技術(shù)特性,設(shè)備可在較短時間內(nèi)完成部署任務(wù),或從故障狀態(tài)中快速的恢復(fù)。同時,該架構(gòu)提供了云端應(yīng)用級的容災(zāi)方案。
控制中心服務(wù)器集群、車站子系統(tǒng)設(shè)備群和車載子系統(tǒng)設(shè)備群的各設(shè)備需預(yù)置Docker環(huán)境,通過pull或run方式下載或更新軟件鏡像,如圖3所示。
圖 3 軟件鏡像部署與運行流程
虛線(1)所示是pull指令的數(shù)據(jù)傳遞流程。部署人員在操作系統(tǒng)中使用CLI指令向Docker守護進(jìn)程發(fā)送拉取鏡像A的指令,守護進(jìn)程從軟件倉庫服務(wù)器獲取對應(yīng)的鏡像A。
實線(2)所示是鏡像的實例化過程。運行指令傳遞給Docker守護進(jìn)程后,守護進(jìn)程會將鏡像A在本地實例化為容器A-1,并返回一個用于訪問容器的虛擬會話。容器A-1在宿主機后臺運行,通過端口映射向外部提供應(yīng)用服務(wù)。
通過上述流程,基于Docker的私有倉庫和應(yīng)用容器化技術(shù),系統(tǒng)實現(xiàn)了應(yīng)用軟件從云端備份到本地運行的無縫結(jié)合。
鏡像是一個用于創(chuàng)建Docker容器的只讀模板。鏡像的制作方式有2種。
(1)容器提交(docker commit)
選擇合適的基礎(chǔ)鏡像,啟動一個可交換的容器。進(jìn)入其中,安裝需要的依賴環(huán)境和軟件包。然后,退出容器。使用docker commit指令,將容器中的全部修改提交,形成一份新的鏡像。
(2)鏡像構(gòu)建(docker build)
建立鏡像首先需要創(chuàng)建一個Dockerfile文件。根據(jù)語法,在Dockerfile文件中定義了創(chuàng)建和運行鏡像的必要指令。Dockerfile中的每一條指令都會在鏡像中創(chuàng)建一個獨立層,當(dāng)Dockerfile內(nèi)容發(fā)生變更需要重新構(gòu)建時,只有變更的地方會被重建,因此,與其他虛擬化技術(shù)相比,Docker鏡像顯得更加輕量、小巧和快速。
上述兩種鏡像的生成方式優(yōu)缺點對比如表1所示。乘客信息系統(tǒng)的應(yīng)用軟件多為定制化較強的專用軟件,軟件依賴環(huán)境特殊,版本控制嚴(yán)格。在應(yīng)用軟件的鏡像制作中,針對不同軟件類型,應(yīng)制作不同的鏡像。
考慮到應(yīng)用軟件依賴環(huán)境的多元化,對于依賴環(huán)境定制程度不高的應(yīng)用軟件類型,可以通過Dockerfile構(gòu)建鏡像。Dockerfile模板可擴展后服務(wù)于多個鏡像構(gòu)建,易于版本迭代和鏡像維護。
表 1 兩種Docker鏡像制作方式比較
對于依賴環(huán)境定制程度高的應(yīng)用軟件類型,宜在既有容器逐步調(diào)試依賴環(huán)境,生成穩(wěn)定可用的鏡像。當(dāng)軟件版本或依賴環(huán)境需要變更時,在前一鏡像版本的基礎(chǔ)上,進(jìn)入容器修改,通過鏡像迭代完成版本升級和軟件維護。
容器是鏡像的實例。通過Docker API或CLI(Command Line Interface),可以創(chuàng)建、啟動、停止、移動或刪除一個容器。默認(rèn)情況下,一個容器與其他容器、宿主機之間是相互隔離的。由于Docker引對卷掛載和端口映射的良好支持,容器可以通過外部存儲的掛載(-v參數(shù)),或映射網(wǎng)絡(luò)端口(-p參數(shù)),與宿主機或外部設(shè)備進(jìn)行通信。
3.2.1 端口映射
在乘客信息系統(tǒng)中,應(yīng)用軟件的實現(xiàn)都建立在網(wǎng)絡(luò)通信技術(shù)的基礎(chǔ)上。應(yīng)用軟件容器化后,如何將容器內(nèi)端口映射至宿主機是首要任務(wù)。
Docker容器運行時,通過-p參數(shù),可以將容器內(nèi)的網(wǎng)絡(luò)端口映射至宿主機端口,實現(xiàn)網(wǎng)絡(luò)通信的功能。對于多網(wǎng)卡宿主機,可以通過指定宿主機IP的方式,將容器內(nèi)端口映射至指定網(wǎng)卡的端口。下述指令實現(xiàn)了將nginx容器的80端口映射至宿主機配置IP為192.168.1.10網(wǎng)卡的8090端口。
docker run -p 192.168.1.10:8090:80 -d nginx:latest
3.2.2 數(shù)據(jù)持久化
Dokcer鏡像是一堆只讀層的集合。容器實例化過程,是在只讀鏡像層基礎(chǔ)上,建立一層可讀寫的容器層。以鏡像為模板,創(chuàng)建的容器層可以通過提交指令轉(zhuǎn)換為只讀層,形成新的鏡像。若不提交,在容器退出后,docker服務(wù)進(jìn)程會將容器層移除。
綜上所述,由鏡像創(chuàng)建出的容器,其運行過程中的狀態(tài)不會持久保存。所以,在實現(xiàn)例如數(shù)據(jù)庫等應(yīng)用的容器化時,除了端口映射,還需要保證數(shù)據(jù)的持久化。通過-v參數(shù),將容器中的/var/lib/mysql文件夾映射至宿主機本地文件夾。
docker run -d -p 3306:3306 -v /usr/local/mysql/data:/var/lib/mysql mysql:latest
3.2.3 圖像傳輸
乘客信息系統(tǒng)的終端設(shè)備需要提供媒體和信息服務(wù),媒體播放應(yīng)用程序需要圖形化界面顯示圖形和文字信息。Docker容器中應(yīng)用的圖形化顯示,可以利用X11服務(wù)實現(xiàn)。容器運行命令中使用-v參數(shù),可以掛載容器的X11的unix套接字到宿主機,同時通過-e參數(shù),更改宿主機的DISPLAY環(huán)境變量,控制圖形輸出至宿主機。
docker run -e DISPLAY=unix$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix myGuiApp
在Docker容器與宿主機間,X11通信數(shù)據(jù)流如圖4所示。
圖 4 容器應(yīng)用圖像傳輸流程示意圖
應(yīng)用軟件管理系統(tǒng)由軟件倉庫服務(wù)器和軟件倉庫管理工作站組成。軟件倉庫是應(yīng)用軟件的Docker鏡像的集合,位于控制中心,向中心服務(wù)器、車站服務(wù)器和車站播控提供鏡像下載服務(wù)。為了實現(xiàn)倉庫存儲鏡像數(shù)據(jù)的持久化,需要將倉庫存儲掛載至宿主機,即軟件倉庫服務(wù)器的本地目錄。
軟件倉庫的界面化管理平臺基于開源軟件實現(xiàn),平臺采用B/S架構(gòu)。運維人員通過軟件倉庫管理工作站,可以實現(xiàn)鏡像上傳、鏡像更新、鏡像標(biāo)簽編輯,鏡像移除、鏡像備份等操作,避免了在工作站環(huán)境下安裝Docker環(huán)境和CLI訪問倉庫的繁雜步驟。
本文提出了一種基于容器技術(shù)的軟件部署方案。通過容器化設(shè)計降低了應(yīng)用程序與運行環(huán)境的耦合性,簡化了系統(tǒng)安裝與部署流程,保證了軟件運行的可靠性,有助于降低人力成本和維護難度。但是本文提出的軟件容器化部署方案,僅從操作系統(tǒng)層面實現(xiàn)了資源節(jié)約,未來可進(jìn)一步研究基于硬件資源平臺的虛擬化方案,對系統(tǒng)級的云平臺構(gòu)建提出設(shè)計方案。