3億Docker容器部署的挑戰(zhàn)及應(yīng)對方案
IronWorker 是一個(gè)面向開發(fā)者的任務(wù)隊(duì)列服務(wù),開發(fā)人員可以在不設(shè)置和管理任何基礎(chǔ)設(shè)施的基礎(chǔ)上,調(diào)度執(zhí)行大規(guī)模的任務(wù)。幾個(gè)月前,IronWorker 開始使用 Docker,如今其內(nèi)部已經(jīng)部署了3億多個(gè) Docker 容器,本文中分享了 IronWorker 在使用基于 Docker 的基礎(chǔ)架構(gòu)時(shí),遇到的挑戰(zhàn)、解決方法,以及其中的收獲。
以下為譯文:
IronWorker 是一個(gè)任務(wù)隊(duì)列服務(wù),他讓開發(fā)人員在不用設(shè)置和管理任何基礎(chǔ)設(shè)施的基礎(chǔ)上,調(diào)度執(zhí)行大規(guī)模的任務(wù)。我們3年多前推出這項(xiàng)服務(wù)時(shí),使用了包含所有的語言和代碼包的LXC容器運(yùn)行任務(wù)。Docker使我們能夠輕松地升級和管理一組容器,為客戶提供更多的語言環(huán)境和安裝包。
我們剛開始使用的是v0.7.4版本的 Dokcer ,使用過程中遇到一些困難(不能正常關(guān)閉曾是個(gè)大問題,不過后來被解決了)。我們不僅成功地克服了所有的困難,并且發(fā)現(xiàn) Docker 不僅滿足了我們的需求,更是超出了我們的預(yù)期。因此我們在我們的基礎(chǔ)架構(gòu)中推廣使用 Docker 。基于我們的經(jīng)驗(yàn)來看,這樣做是有意義的。
Docker的優(yōu)勢:
更新維護(hù)鏡像非常容易
Doker 使用類似 git 的非常強(qiáng)大的方法來管理 image ,使得它能很方便地管理大量的、不斷變化的環(huán)境,他的 image 分層系統(tǒng)不僅節(jié)省空間而且使我們擁有更細(xì)區(qū)分度的 images 。 現(xiàn)在,我們能夠跟上快速更新的語言的節(jié)奏,例如我們能夠提供一個(gè)新的專為媒體處理而設(shè)計(jì)的 ffmpeg stack 。我們現(xiàn)在有多達(dá)15個(gè)不同的堆棧并且正在迅速擴(kuò)大。
資源分配
基于 LXC 的容器是操作系統(tǒng)級別的虛擬化方法,所有的容器共享系統(tǒng)內(nèi)核,但是每個(gè)容器可以被約束使用指定的資源,比如 CPU 、內(nèi)存和 I/O 。 Docker 提供 REST API 、環(huán)境版本控制、獲取/提交鏡像、輕松獲取統(tǒng)計(jì)數(shù)據(jù)等功能。 Docker 支持使用 CoW 文件系統(tǒng)來更安全的隔離數(shù)據(jù)。這意味著,任務(wù)中對文件的所有改變都分開存儲,并可以用一個(gè)命令清除。 LXC 不能跟蹤這種變化。
Dockerfiles使得集成簡單
我們的團(tuán)隊(duì)遍布世界各地。只要發(fā)布一個(gè)簡單的 Dockerfile 就可以下班,當(dāng)你休息時(shí),可以保證其他工作的人能夠生成和你的一樣的鏡像。克服了不同地方的人有不同的作息時(shí)間的困難。干凈的鏡像使得它部署和測試更快。我們的迭代周期更快,團(tuán)隊(duì)里每個(gè)人更加開心。
不斷壯大的社區(qū)
Docker 現(xiàn)在更新得非常快,甚至比 chrome 還快。更重要的是,參與增加新功能和修復(fù) bug 的社區(qū)數(shù)量在大量增加。 無論是為為鏡像貢獻(xiàn)還是為 Docker 做貢獻(xiàn),甚至是為 Docker 的周邊工具做貢獻(xiàn),有一大批聰明的人正在為其努力,因此我們也不能置身事外。我們發(fā)現(xiàn) Docker 的社區(qū)非常活躍有意義,我們很高興能夠成為其中一員。
Docker + CoreOS
我們也處在探索階段,但我們發(fā)現(xiàn) Docker 和 CoreOS 的結(jié)合對于我們來說似乎是更好地選擇。Docker 提供了穩(wěn)定的鏡像管理和容器。CoreOS 提供了一個(gè)精簡的云操作系統(tǒng)、機(jī)器級別分布式編排和虛擬狀態(tài)管理。這個(gè)組合關(guān)注問題的不同方面,是一個(gè)更合理的基礎(chǔ)設(shè)施棧。
挑戰(zhàn)
每一個(gè)服務(wù)器端的技術(shù)需要微調(diào)和定制,尤其是大規(guī)模運(yùn)行時(shí),,Docker 也不例外。(例如:我們跑不到5000萬的任務(wù),一個(gè)月50萬小時(shí)計(jì)算,并且不斷更新我們的鏡像)。下面是我們使用大量 Docker 容器數(shù)時(shí)遇到的一些挑戰(zhàn):
向后兼容性不夠
該領(lǐng)域的快速創(chuàng)新雖然是一個(gè)優(yōu)勢,但是也存在缺點(diǎn)。其中之一是向后兼容性差。在多數(shù)情況下,我們遇到的問題主要是是命令行語法、 API 的改變,從產(chǎn)品角度來說這不是一個(gè)嚴(yán)重的問題。
但在某些情況下,它影響了操作性能。例如,在任何啟動容器后引發(fā)的 Docker 錯(cuò)誤,我們要解析 STDERR 并根據(jù)錯(cuò)誤類型進(jìn)行響應(yīng)(例如重試)。非常不幸的是,錯(cuò)誤的輸出格式隨著版本不同變化,不得不在不斷變化的結(jié)果中調(diào)試,使我們非常疲憊。
圖注:Docker的錯(cuò)誤率
這個(gè)問題相對來說還比較好解決,但是意味著每次的更新要經(jīng)過多次驗(yàn)證,并且你需要一直開發(fā)直到這個(gè)更新的版本被發(fā)布到了系統(tǒng)大部分環(huán)境中。我們幾個(gè)月前使用v0.7.4,現(xiàn)在我們的系統(tǒng)更新到v1.2.0.在這個(gè)領(lǐng)域我們已經(jīng)有了一個(gè)很大的進(jìn)步。
有限的工具和庫
雖然 Docker 有一個(gè)四個(gè)月前發(fā)布的穩(wěn)定版本,圍繞它的一些工具仍然不穩(wěn)定。采用 Docker 生態(tài)圈中的大部分工具意味著需要投入更多的精力。為了使用***的功能、修復(fù) bug ,你團(tuán)隊(duì)中需要有人熬夜加班對這些功能,頻繁的進(jìn)行一些修改.也就是說,我們很高興有一些 Docker 周邊的工具在開發(fā),而且很期待能夠有一個(gè)工具在其中脫穎而出。我們對 etcd 、 fleet 、 kubernetes 比較看好。
戰(zhàn)勝困難
接下來根據(jù)我們的經(jīng)驗(yàn),更深入的講我們講我們遇到的問題和我們的解決方法。問題列表主要來自我們 Ironworker 的***開發(fā)兼工程運(yùn)營總監(jiān) Roman Kononov 和一直在調(diào)試和規(guī)范化我們 Docker 操作的 Sam Ward 。
圖注:Debug時(shí)的一個(gè)異常
說明一下,當(dāng)我們遇到和 Docker 相關(guān)或者其它系統(tǒng)相關(guān)的問題,我們可以自動的重新執(zhí)行任務(wù),對用戶沒有任何影響(重試是平臺的內(nèi)置功能)。
刪除操作時(shí)間長
起初刪除容器時(shí)間長,需要太多的磁盤I/O操作。這導(dǎo)致我們的系統(tǒng)速度明顯變慢,形成了瓶頸。我們不得不增加可用的內(nèi)核數(shù)目,而這個(gè)數(shù)量遠(yuǎn)遠(yuǎn)超出我們所需的。
圖注:快速刪除Docker容器的解決方案
通過研究使用 devicemapper(一個(gè) Docker 的文件系統(tǒng)驅(qū)動),我們發(fā)現(xiàn)設(shè)置一個(gè)選項(xiàng)有作用--storage-opt dm.blkdiscard=false ,這個(gè)選項(xiàng)告訴 Docker 刪除容器時(shí)跳過花費(fèi)時(shí)間長的磁盤操作,大大加速了容器的關(guān)閉過程。當(dāng)修改好刪除腳本后,這個(gè)問題就沒了。
卷無法卸載
由于 Docker 沒有可靠地卸載卷,容器不能正確地停止。這導(dǎo)致容器永遠(yuǎn)在運(yùn)行,即使已經(jīng)完成了任務(wù)。解決辦法就是顯示地調(diào)用用戶自己寫得一些列腳本來卸載卷,刪除文件夾。幸運(yùn)的是,這個(gè)問題是之前我們使用 Docker v0.7.6 版本時(shí)遇到的,當(dāng) Docker 更新到 v0.9.0 解決了這個(gè)問題后我們就刪除了那些冗長的腳本。
內(nèi)存限制開關(guān)
Docker 其中的一個(gè)發(fā)布的版本中突然新增了內(nèi)存限制選項(xiàng),刪除了 LXC 中的選項(xiàng)。其結(jié)果是一些工作進(jìn)程到達(dá)內(nèi)存界限,然后了整體不響應(yīng)。這弄得我們措手不及,因?yàn)榧词故褂昧怂恢С值脑O(shè)置, Docker 也沒有出錯(cuò)。解決方法很簡單,即在 Docker 內(nèi)部設(shè)置內(nèi)存限制。
未來計(jì)劃
正如你所看到的,我們對 Docker 投入非常多,我們在接下得每天會繼續(xù)投入。除了用它來隔離用戶在 IronWorker 中運(yùn)行的代碼,我們也準(zhǔn)備在其他的一些領(lǐng)域使用它。這些領(lǐng)域包括:
IronWorker 后臺
除了使用 Docker 作為任務(wù)的容器,我們也在使用它來管理每個(gè)服務(wù)器上運(yùn)行的用來管理和啟動任務(wù)的進(jìn)稱。每一進(jìn)程著的主要任務(wù)是從隊(duì)列中拿一個(gè)任務(wù),把它放到合適的 Docker 容器中,運(yùn)行,監(jiān)測,運(yùn)行完后刪除環(huán)境。有趣的是同一臺機(jī)器上我們有容器化的代碼來管理其它容器。把我們所有的基礎(chǔ)設(shè)施環(huán)境放到 Docker 的容器中讓我們在 CoreOS 上的運(yùn)行相當(dāng)容易。
IronWorker, IronMQ,以及 IronCache APIs
和其他的運(yùn)維團(tuán)隊(duì)一樣,我們也不喜歡部署。能夠把我們的所有的服務(wù)打包 Docker 容器中,然后簡單、確定地部署,我們非常地激動。不用再配置服務(wù)器,我們需要的就只是能夠運(yùn)行 Dokcer 容器的服務(wù)器。我們正在替換我們的服務(wù)器搭建,使用 Docker 容器在服務(wù)器上為我們發(fā)布的產(chǎn)品搭建環(huán)境。變得的靈活、簡單,有更可靠的協(xié)議棧。
生成和加載程序
我們也在用 Docker 容器在 IronWorker 中生成和加載程序。一個(gè)顯著的進(jìn)步是為用戶改進(jìn)了,大規(guī)模、特定任務(wù)負(fù)載和工作流的創(chuàng)建、上傳、運(yùn)行任務(wù)的過程。還有一個(gè)好處是用戶可以在本地測試程序,而測試環(huán)境和我們的生產(chǎn)服務(wù)一致。
企業(yè)內(nèi)部部署版
使用 Docker 作為主要分發(fā)方法, IronMQ 企業(yè)內(nèi)部部署版簡化了我們的分發(fā)工作,并且提供了一個(gè)簡單通用的在幾乎任何云環(huán)境中都能部署的方法。就像我們在共有云上運(yùn)行的服務(wù),客戶需要的就是可以運(yùn)行 Docker 容器的服務(wù)器,同時(shí)他們可以相對容易的獲得在測試或生產(chǎn)環(huán)境中運(yùn)行的多臺服務(wù)器的云服務(wù)。
原文出自:https://docker.cn/p/docker-in-production-what-weve-learned