塊存儲是將裸磁盤空間通過劃邏輯盤,做Raid,或者LVM(邏輯卷)等方式邏輯劃分出N個邏輯的硬盤,然后采用映射的方式將這些邏輯盤掛載到主機(jī)。主機(jī)的操作系統(tǒng)認(rèn)為這些磁盤均為物理硬盤,跟直接拿一塊物理硬盤掛載到操作系統(tǒng)沒有區(qū)別。
塊存儲的優(yōu)點(diǎn)不言而喻:
1. 使用了Raid與LVM等手段,可以多數(shù)據(jù)做冗余保護(hù);
2. 可以使用磁盤陣列,組成大容量的邏輯盤對外提供服務(wù),提高容量;
3. 對邏輯盤寫數(shù)據(jù)可轉(zhuǎn)化為對幾塊物理磁盤的并行寫入,提升了讀寫效率。
需求
在IaaS中,塊存儲被廣泛應(yīng)用于為虛擬機(jī)提供持久卷。虛擬機(jī)故障后依然能夠通過在其他虛擬機(jī)上掛載舊數(shù)據(jù)卷的方式來訪問磁盤數(shù)據(jù),因此被普遍認(rèn)可。受此影響,一些客戶在設(shè)計(jì)PaaS時(shí),自然而然的聯(lián)想到共享存儲的這一優(yōu)勢,提出在PaaS中為容器掛載塊存儲的需求。
但是,憑借在IaaS中的卓越表現(xiàn),塊存儲也能夠躋身PaaS業(yè)務(wù)中嗎?
分析
假設(shè)已有一套可提供RBD塊存儲的Ceph集群的前提下,我們先來分析幾個場景:
場景一
“我使用容器技術(shù),但還不是深度用戶,只使用docker run之類的命令來手工啟動單個容器,這些容器中運(yùn)行的服務(wù)都比較消耗磁盤空間。”
這類用戶局限于將容器作為一個臨時(shí)工具,并沒有將其與業(yè)務(wù)緊密結(jié)合。
1. 如果對磁盤沒有持久化的需求,那么在主機(jī)磁盤空間空余足夠的情況下可以考慮直接映射宿主機(jī)文件系統(tǒng)。
2. 若想讓磁盤獨(dú)占共享磁盤,或希望在不同宿主機(jī)上啟用容器時(shí),均能重復(fù)使用之前訪問過的數(shù)據(jù)卷;此時(shí)可以在啟動docker時(shí),指定volume-driver為ceph-rbd的方式來使用由Ceph集群提供的塊存儲。
塊存儲驅(qū)動框架圖如下所示:
場景二
“我使用容器編排工具來管理應(yīng)用,比如docker-compose、Rancher或Kubernetes.但我在每一個service下只需要啟用一個container,且對service沒有擴(kuò)容的需求;這些service都比較消耗磁盤,我希望在容器被重啟或重新調(diào)度后,仍可使用舊的數(shù)據(jù)盤。”
該場景比較特殊,每一個service只對應(yīng)一個container.因此,不會有多個container同時(shí)讀寫一塊數(shù)據(jù)盤的需求,只需保障container之前所掛載的存儲卷在container故障恢復(fù)或正常遷移后依然能夠被container訪問即可;即存儲卷對容器的自動跟隨。
遷移場景如下圖所示:
但是,值得注意的是:
1. 假設(shè)之前的container運(yùn)行在host-1上,對應(yīng)的,塊存儲就掛載在host-1上。
2. 當(dāng)原有container因故被調(diào)度到新的host-2上時(shí),編排框架檢測到該變化,將host-1上的原有塊設(shè)備卸載,然后掛載到host-2.
3. 按照該流程,塊存儲的每一次遷移都需要從一臺主機(jī)上卸載,再到另外一臺主機(jī)上掛載;新container的啟動依賴于volume,因此容器或者業(yè)務(wù)的恢復(fù)速度依賴于塊存儲的遷移速度。
4. 假設(shè)平臺未能及時(shí)檢測到host-1上的container故障、舊有的container卡死無法快速銷毀,或者h(yuǎn)ost-1突然斷電時(shí),Ceph Server必須等待超時(shí)后,才允許host-2重新掛載之前被使用的RBD塊。此時(shí),container啟動時(shí)間就會變得難以忍受,顯然這是與容器的秒起秒停的優(yōu)勢相互違背的。
場景三
我使用Rancher或者Kubernetes之類的容器編排軟件來管理應(yīng)用,每一個應(yīng)用有多個微服務(wù);每一個微服務(wù)又對應(yīng)多個容器來并行對外提供服務(wù)。
Rancher
在Rancher里面,應(yīng)用被稱之為Stack,每一個stack包含一到多個service; service即微服務(wù),微服務(wù)之間按照單一職責(zé)劃分,只做一件事情。service屬于邏輯的概念,真正做事的是各service對應(yīng)的containers.如果希望通過為service擴(kuò)容,就增加service對應(yīng)的container數(shù)量;這些container無狀態(tài),可被調(diào)度到多臺宿主機(jī)上,它們必須使用共享存儲來保障業(yè)務(wù)的持續(xù)性。
Kubernetes
在Kubernetes中,業(yè)務(wù)也是由一到多個service來共同完成的,這里的service與Rancher中service的概覽類似。Kubernetes的service是一個外部訪問點(diǎn)(endpoint),通過selector指定labels的方式可以選定一組pods,service為這組pods提供訪問代理和負(fù)載均衡。外部的客戶端只需知道service所暴露的端口和IP就能夠訪問到業(yè)務(wù)。由于pod是無狀態(tài)的,因此同Rancher一樣,也需要將業(yè)務(wù)數(shù)據(jù)存儲到共享存儲上,還必須保障同一個service對應(yīng)的多個pods均能共享該業(yè)務(wù)數(shù)據(jù)。
限于塊存儲只能同時(shí)被一個客戶端(主機(jī))所掛載,當(dāng)service的多個containers或pods調(diào)度到多臺主機(jī)上時(shí),塊存儲就難以應(yīng)付了。此時(shí),原始共享文件系統(tǒng)的方法又體現(xiàn)出了它的優(yōu)勢,NAS會是一個最好的選擇!