一個偉大的問題誕生在 mechanical-sympathy Google郵件列表,或許已經有許多其他的偉大的問題誕生在此了。問題如下:
我不斷地聽說Docker,就好像他是切片面包以來最偉大的發明一樣,但是我還聽說低延遲應用在使用它的時候遭受打擊。
沒有誰比Azul Systems的技術副總裁、首席技術官和聯合創始人Gil Tene更適合回答這個問題了。就像我們相信喬丹的三步上欄一樣,我們總能依靠Gil的洞察力,參見下面的文章:
系統地去除Linux操作系統抖動的黑魔法
你的載荷生成器可能騙了你——吃下紅藥丸然后找出原因
下面是Gil的答案:
拋開問題的品味和風格不說,單說延遲效果(原始的問題),從機制角度來分析,答案很簡單:Docker使用Linux容器作為執行方式沒有對CPU和內存的操作系統虛擬層,有可選的(即使缺省是打開的)對I/O的虛擬層。
CPU和內存
從延遲的角度來說,Docker(和其他Linux容器)的CPU和內存延遲特性不能夠和Linux自身區分出來,但是對Linux有效的控制遲延行為對Docker也有效。
如果你想要清楚和一致的低延遲,你必須做不用Docker和不用容器時相同的工作來獲得相同級別的一致性。例如,如果你想讓整個系統盡在掌握(沒有饑餓的鄰居),你也不得不在主機這個層次為Docker做工作。
如果你需要分隔套接字或者內核和選擇哪些進程在哪里,對Docker容器或者其中的線程,你也要做相同的事。
如果你使用非統一內存存取(NUMA, Non-Uniform Memory Access),或者使用任何類型的直接的NUMA驅動的內存分配,你也要做相同的事。
并且,你需要做的一些事情可能看起來違反一些人想要的部署Docker的模式。但是,如果你真正對一致性的低延遲感興趣,你或許需要擺脫現有工具集,使用不同的控制組(cgroups)、任務設置(tasksets)和其他酷的工具來確保事情的安排。然而,即使你做了這些事情,你也不能夠區分容器內外的進程的CPU和內存的延遲。
I/O
磁盤I/O
在不同配置下的I/O行為是許多延遲問題產生和解答的原因。對于磁盤I/O行為和選項我也所知甚少,不能談論太多。但我確定解決任何存儲吞吐量和延遲敏感問題的答案是“越過虛擬層和邏輯分區,直接訪問磁盤和掛接點”。
網絡
網絡的情形相當清楚:如果你想要網絡地理位置無關、網絡地址翻譯(NAT, Network Address Translation)或橋接、自動生成的網絡等功能,你或許會為網絡延遲或吞吐量(相比Linux上直接真實物理網卡)付出代價。然而,也有為Docker配置低成本或基本上零延遲成本的網絡鏈路的選項(再一次,可能與一些人想要的部署方式不同)。使用宿主機的網絡或者專用IP地址和網卡,你將獲得比缺省的橋接網絡更好的性能。但你將會遇到配置Solarflare的網卡(在裸金屬低延遲環境中很普遍)、繞過內核、專用自旋核心網絡協議棧等相關的事宜。這些延遲相關的行為與是在宿主機上還是用Docker沒有分別。
Docker(作為一個整體屬于用戶空間)不是把大雜燴裝進一個盒子,客機(guest OS)作為一個整體的虛擬化方案也不是。確實,他們都能夠這樣用(經常是這樣),但是使用他們的最大益處是發布一致的精心選擇的配置,還有開發、測試和部署都使用相同配置的能力。后者可以容易地管理發布和版本(包括回滾),還有實現如“彈性大小”這樣的酷的事情。其他配置工具(puppet或者shef等)當然也能得到相同的結果(假定他們控制你的鏡像中的一切),但是把可以工作的東西打包在一起開箱即用確實是很誘人的事。
我知道有使用一個宿主機上只有一個客機這樣虛擬化方案的人們(例如,AWS r3.8加大實例類型目前大概就是這樣的)。也知道有采用相同方式使用Docker的人們(一個宿主機一個容器)。這兩種用例是為了配置控制和部署,不是為了節約成本而把東西打包。
低延遲這件事現在變成了“它更糟嗎?”這個問題。相比較基于宿主機和客機或KVM的虛擬化方案,在低延遲這個問題上,只要做正確的選擇(專用網卡、內核和設備),Docker帶來的損害更少,真正的不可察覺。