戳藍字「CSDN雲計算」關注我們哦!
技術頭條:乾貨、簡潔、多維全面。更多雲計算精華知識盡在眼前,get要點、solve難題,統統不在話下!
Docker 在企業環境的應用端具有很大的潛力,在這一點上我想大家是有目共睹的,無狀態的服務採用容器化已經是一種大趨勢,那麼問題來了,作為系統核心的資料庫是否需要容器化?
針對資料庫是否適合容器化這個問題,不同的人可能會給出不同的答案,在回答此問題之前我們先看下容器化部署資料庫和常規資料庫部署上的一些比較。
容器化VS非容器化
資料庫不適合容器化,筆者相信持這種觀點的技術人員不在少數,為此筆者專門梳理了此種觀點常見的一些依據,我們一起看一下:
1. 數據安全性
數據安全這個話題較大,可以細分很多的小方向,在此我們只從數據丟失這個角度分下資料庫容器化後引入的問題。
和資料庫打過交道的同學應該都知道,公司線上的資料庫一般都需要進行定期的數據備份,區別的話無非就是根據業務的輕重緩急設置不同的數據備份方式、備份頻率和備份數量。常見的資料庫的數據備份方式有全量備份和增量備份。
顧名思義,全量備份即每次都進行一次完整的數據備份,即便是相較前一次的全量備份數據沒有絲毫的增加也要再進行一次完整的數據備份,此種方式的特點是可靠性較好,每一個數據備份都是備份所在時間點的完整數據,當然此種方式的缺點也是顯而易見的,即備份周期較長(相比增量備份的數據量大),且備份數據占用的磁碟存儲也較大;增量備份即在第一次備份時進行一次全量的備份,後續在進行備份時只備份相較前一次備份時變化的數據,增量備份的優點是備份周期短,且備份數據占用的磁碟空間較少。
備份周期並非越小越好,需要結合業務的屬性進行選擇,如公司OA系統使用的資料庫可以一周備份一次,畢竟OA 這種系統並會經常進行大量數據的寫入。再一種情況,比如公司的重要的線上業務一般需要較高的備份頻率,一般以天或者小時作為備份周期的時間單位,比如一天備份一次、或者1小時備份一次。有些更重要的業務系統,出現數據丟失時會帶來比較大的損失,此種情況一般會採用更高的數據備份頻率,比如銀行的資料庫備份多以分鐘或者秒作為資料庫的備份周期單位。
和備份周期的設置類似,備份數據保留的數量也並非越多越好,也需要根據具體的業務場景來設置備份數據的保留數量。比如一般的線上業務可以每天備份一次,最多保留7份備份數據。
以上我們說的是我們在將資料庫容器化之前為防止資料庫數據丟失通常進行的配置,從現實角度來看即使我們設置了上面提到的各種配置也仍然不能保證不丟失數據。
從上面的經驗來看,容器化後即使我們通過容器的volume 將數據存儲在容器所在宿主機上也不能保證數據不丟失。況且Docker 的volume 是圍繞聯合文件系統的鏡像層來進行的持久化存儲設計,這種設計目前在資料庫存儲方面仍缺乏保證。
除了上面的問題,還有一種情況也會為資料庫的數據安全性帶來問題,眾所周知在容器的世界裡某個容器的崩潰、重建是常態,這種情況對於業務實例來說也許不會有多大的影響,但同樣的場景換為資料庫可能會出現問題,比如運行著資料庫的容器崩潰可能會導致容器內的資料庫不能正確關閉,從而可能造成數據的損壞。
2. 環境需求
在非容器化的場景中,為了避免避免和其他組件的資源競爭,資料庫這種核心組件我們一般都是單獨部署的,要麼單獨部署到一台或者幾台的虛擬機上,要麼單獨部署到一台或者幾台的物理機上,一般需要和其它的線上組件分開部署,比如後端的一些業務實例等,防止其它異常組件拖垮資料庫,畢竟資料庫掛了線上業務一般也就歇菜了,這種情況下企業一般也是寧願多花點錢來保證線上業務的正常運行。
資料庫的單獨部署只是第一步,實際環境中一般還需要給資料庫組件配置好一些的硬體資源,具體需要在哪些方面進行升配也需要結合具體額業務場景和資料庫的類型來看。比如關係型資料庫,一般對I/O要求較高,這個時候一般需要為資料庫配置較好的存儲設備,比如磁碟選用優質的全固態盤。在一種比如緩存資料庫,為提高查詢效率緩存資料庫一般會將數據存儲在內存中,如果存在較多的高頻訪問數據,此時一般需要為資料庫配置較高的內存。
考慮到上面的兩種情況,我們在進行資料庫的容器化過程中為了避免資料庫實例和其他的業務實例產生資源競爭,我們需要為資料庫容器配置大量額外的資源,一般可能需要設置超過實際用量一倍的資源,比如我們實際需要8GB內存,可能需要為實例分配16GB內存,多出的這8GB的內存資源一般並不會被完全使用。
3. 網絡需求
Docker 的引入一定程度上增加了網絡的複雜性,想要理解Docker 的網絡需要對網絡虛擬化有比較深入的了解。另外,雖然Docker 的使用已經逐步落地,但Docker 本身的技術仍在發展之中,Docker 本身還存在或多或少的bug,這些bug可能會為我們帶來一些意外的情況。為應對這些意外,我們可能需要花費較多的時間排查和修復Docker 的bug,從筆者實際體驗來看這種情況一般會花費企業較多的人力。
上文中我們提到資料庫一般會有較高的吞吐量,因此通常情況下我們需要為資料庫配置較好的配置,以此來應對更高的負載。除了磁碟、內存、CPU會較大的影響資料庫的性能之外,網絡對資料庫的性能也是非常只要的一環,尤其是在涉及到數據複製的場景,網絡性能差的情況下可能會影響到資料庫的數據複製效率,在異步複製的場景下網絡性能差可能會導致業務實例讀不到最新的數據。我們知道容器是虛擬機管理程序和主機虛擬機背後的一個隔離層,Docker 容器引入的額外的網絡邏輯一定程度上會降低網絡的傳輸效率,進而可能會影響到資料庫容器之間的數據複製,進而導致業務實例從資料庫讀取到錯誤的數據。
資料庫本身就是一個比較複雜的系統,資料庫的容器化會導致資料庫更加難以管理,相比引入Docker複雜的網絡環境,將資料庫實例放在專用的環境中,節省下時間專注於業務的改進對項目、對企業來說可能會是更好的選擇。
4. 狀態抉擇
Docker 容器出現之初主要是用來運行無狀態的應用實例,對於資料庫這種情況並未專門的支持。資料庫的特性決定了它是有狀態的,和無狀態的應用實例混布在一起,會加大系統的故障範圍,業務系統中的應用程式實例異常可能會直接影響到運行在有狀態容器中的資料庫實例。
5. Docker的支持
簡單說來就是Docker並未對容器中運行資料庫這種場景做專門的優化。我們先看下Docker 官方對Docker的定義:
Docker Containerization Unlocks the Potential for Dev and Ops,Freedom of choice, agile operations and integrated container security for legacy and cloud-native applications。
具體說來就是:
(1) Docker 是為程序開發者和系統運維人員提供的一個開放平台,這個平台提供了包含應用構建、應用分發和運行分布式應用在內的一些功能。
(2) Docker 為程序開發者和系統管理人員提供了Docker 引擎和眾多的配套組件,如Docker Hub,Docker 引擎是一個C/S架構的應用程式,開發者可以藉助Docker 引擎對Docker 對象進行管理,常見的Docker 對象包括:Dcoker鏡像、Docker容器、Docker網絡、Docker 資料庫卷等。Docker Hub 為開發者提供鏡像的託管服務。開發者藉助Docker 可以將應用程式以組件的形式進行快速的部署,同時藉助Docker 可以消除各種環境的差異性,比如開發環境、測試環境、生產環境。因此藉助Docker 開發者可以更快的對應用進行分發,可以實現一份應用在個人電腦、數據中心的虛擬機和任何雲上運行上快速運行。
從上面的介紹我們可以明顯的看出Docker的一些特性,比如易於構建新環境、適合持續集成、靈活的水平伸縮和不同環境的易維護性等。那麼問題來了,這些特性會為資料庫帶來什麼?
為了回答這個問題我們先看下資料庫的容器化和本地化運行資料庫,二者是否有較大的差異,我們以mongodb資料庫為例來具體看下:
本地化的批量部署軟體大家一般都會藉助一些現成的批量部署工具,比如我們最常使用的Ansible,藉助Ansible 我們可以很輕鬆的部署並設置幾十個mongodb實例,比對下容器化部署幾十個mongodb實例,可能容器化的方式並未為我們節省多少時間。
有些同學可能會問如果批量重新部署多個mongodb實例的話容器化的部署方案應該會更加高效一些,但問題來了,實際工作中資料庫實例需要批量升級的頻率有多高,這種情況可能大部分人在自己目前的職業生涯中都還沒有遇到過一次。且資料庫實例的升級一般不是可用性問題,而是一個比較系統的工程問題,需要考慮到資料庫實例在升級後在整個系統中的可用性。比如更新資料庫的版本之後已有的應用中的邏輯可以無縫的對接嗎,這個可能不見得,從實際情況來看,資料庫實例更換了引擎版本之後可能會引入很多的新特性,這些特性中一般也會有一些不兼容的情況,為解決更新資料庫版本帶來的不兼容的問題,我們需要花費很多額外的人力來對應用進行對應的版本升級,整個過程耗時、耗力,因此實際生產環境中一般不會對資料庫實例進行頻繁的升級,所以在此點上資料庫的容器化並不能帶來明顯的效率提升。
再一個方面,比如動態伸縮。容器化的實例在動態伸縮方面確實存在優勢,尤其是一般的後端應用上,但放在資料庫的容器化實例上卻不能這麼樂觀。比如我們在容器雲中運行了一個db server的多個實例,那麼我們需要考慮下多個實例之間的數據一致性問題,如何解決這個數據一致性?有些同學可能會說多個容器實例共享數據目錄或者加入複製的從節點不就可以解決嗎,這些方式當然是合適的,但是都會引入額外的問題,比如數據並發問題和可能出現的數據損壞問題改如何應對,這些都是問題。反觀非容器化部署資料庫實例,將多個資料庫實例部署到專用的環境中相對來說更簡單,更容易維護,數據更安全,且不會引入額外的問題,另外對於技術人員來說學習成本也相對較低。
通過上面幾個特性的對比,相比專用環境部署資料庫資料庫的容器化似乎並未為我們帶來明顯的改進。
6. 隔離問題
了解Docker 的同學應該都知道,Docker 通過namespace(命名空間)對各種資源進行了隔離,這些隔離包括:主機和域名隔離、進程編號隔離、用戶和用戶組隔離、文件系統隔離、網絡設備隔離、網絡棧隔離、埠號隔離、信號量消息隊列和共享內存的隔離等。
默認情況下只有同一個namespace下的進程之間是可以相互聯繫的,無法感受到外部進程的存在,Docker通過這種方式營造出一種獨立的系統環境,從而實現隔離。
這種隔離性雖然保證了不同容器中進程的衝突等問題,但是這些額外引入的隔離級別也會增加資源的開銷。並且這種隔離性只是為業務的應用量身打造的,並未專門針對資料庫做做額外的優化。
7. 雲平台問題
當前環境下藉助雲平台已經成為常態,我們知道雲計算簡化了虛擬機管理、替換上的複雜性,因此在需要添加新的虛擬機計算節點時直接登錄上雲平台,控制台介面上滑鼠操作幾個步驟即可準備完畢幾台新的計算節點,為我們節省了很多的購買已經設備和測試硬體設備的時間和精力,可謂方便至極。當然這個也是我們需要向雲廠商付費的原因之一。
我們再說回容器雲,用過雲廠商容器雲產品的同學應該會知道,雲廠商提供的容器產品相比原生的容器往往會有一些限制,這個時候如果我們不想直接使用雲廠商提供的容器雲產品,轉而使用雲廠商提供的其他的計算產品自己部署容器環境,比如使用虛擬機或者使用物理機,這種情況下上文中我們講到的雲廠商為我們提供的便利性就不存在了,當然我們可以在容器所在宿主上對資料庫容器實例的資源使用進行限制,這種方式的確可以,但相比直接使用虛擬機或者物理機部署資料庫實例這種容器化部署的方式更加複雜。
以上我們在7個方面列舉了下資料庫不適合進行容器化的原因,很多方面僅僅只是進行了粗略的描述,尤其是在關鍵的有狀態部署和無狀態部署方面,由於此部分涉及對比的方面較多,在此下面我們專門單獨拿出來看下。
有狀態 VS 無狀態
Docker 及其編排技術的興起和逐步成熟讓大家由最初的要不要上容器轉為什麼不用容器,但在業務容器化的過程中大家一般都會遇到這樣一個問題:我們應該將自己的資料庫實例跑在容器中嗎?
要想回答這個問題,我們不妨先回顧下容器技術出現的背景,即這門技術的出現是為了解決什麼問題。接觸容器比較早的話大家應該記得容器技術主要是用在有臨時數據的無狀態服務上,也就是說可以隨時起、隨時用、隨時銷毀(銷毀的組件包括容器中的緩存和數據),容器基本就是用來處理請求,可能還會保存一部分的臨時數據,且這部分數據是允許丟失的。由於這種特性的存在,用戶不能將不允許丟失的數據存放在容器中,這類數據比如用戶上傳的文件、應用的關鍵日誌信息等,也是由於此特性的存在為資料庫的容器化帶來了障礙。
有些同學可能會問,通過給容器掛載volume不能解決嗎? 的確,容器是有掛載volume的機制,volume 可將docker 容器所在的宿主機上的某個路徑掛載到容器中,這樣容器中的應用可以將需要持久化的數據寫入到volume掛載的路徑中,寫入到volume 掛載路徑的數據實際會被寫入到Docker 容器所在的宿主機上,這樣docker 容器銷毀之後我們需要的數據仍然存於容器所在的宿主機之上,不會丟失。這種方案看似比較合理,但是也存在一個很大的漏洞。使用容器的時我們一般通過保存鏡像的方式將容器中新增的數據保存到鏡像中,但是docker 容器的鏡像保存機制不能將容器中掛載的volume里的數據保存到鏡像中,如果容器中運行的為我們的資料庫,資料庫的data路徑為docker容器的volume掛載路徑,當我們保存容器鏡像時,由於剛剛講到的docker的特性,容器運行後資料庫中新增的數據並不能被保存到鏡像中,不是很方便。由於資料庫有狀態特性的存在一定程度上限制了我們對資料庫實例的容器化。
上面我們談到的volume 可以解決資料庫實例資料庫持久化的問題只是在為引入容器編排的情況下的情況。實際使用中項目在使用容器部署應用時一般都會引入容器的編排功能,最常見的容器編排工具,比如kubernetes。加入容器編排之後,假設我們將資料庫容器實例以有狀態服務的方式進行運行,那麼問題來了,如果資料庫容器實例漂移到了另一台的宿主機上怎麼辦,畢竟資料庫的數據還在漂移前的宿主機上。這個時候我們可能就需要將計算和存儲進行分離,最常見的比如加入分布式存儲來解決這個問題,如Ceph分布式存儲,這種方式的確是可以的,很多實用容器雲的企業也是這樣操作的,但是引入Ceph會引入很多的複雜性,且企業內的運維人員不一定對Ceph存儲了如指掌,這種情況下我們為了實現資料庫容器化而額外引入的問題可能比資料庫容器化帶來的便利性還要多。
總結
上文中關於資料庫是否適合容器化的描述中我們更多的對比的是數據需要持久化的資料庫,以及需要特殊硬體環境才能運行的資料庫。但大家都知道資料庫中眾多,並不是每一種都需要進行數據的持久化,比如當做緩存使用的資料庫,拿redis來說,如果我們使用redis作為緩存或者用來存儲用戶會話這一類的數據,這種場景下資料庫的容器化不會涉及前文中提到的7個方面的限制,因此資料庫實例作為緩存這種場景時,資料庫實例的容器化也是合適的。
從實際的使用來看,資料庫要不要容器化這個問題並不是絕對的,需要結合具體的業務場景才能得出結論。比如,微服務的場景,如果我們的系統已經實現了微服務化,資料庫實例的規模可以根據業務負載的實際情況進行動態的調整,這種場景下資料庫實例的微服務化是比較有意義的,一般也是比較推薦的,且很多業務做了微服務化改造的企業確實也是這樣做的。當然微服務化的過程中資料庫的容器化也不是絕對的,筆者自己接觸的一些業務已經微服務化落地的企業中就存在一些未對資料庫做微服務化改造的情況。
筆者個人認為資料庫的容器化像一般應用的容器化那樣普及只是時間問題,隨著Docker 及其周邊的配套技術的逐步成熟,相信在不久的將來大家會像使用Docker 容器部署應用一樣來部署自己的各種資料庫實例,會像使用kubernetes 編排應用的實例一樣來自由的編排自己的資料庫實例。
福利
掃描添加小編微信,備註「姓名+公司職位」,加入【雲計算學習交流群】,和志同道合的朋友們共同打卡學習!
推薦閱讀:
太形象了!什麼是邊緣計算?最有趣的解釋沒有之一!
網際網路出海十年
華為員工年薪 200 萬!真相讓人心酸!
天才程式設計師:25 歲進貝爾實驗室,32 歲創建資訊理論 琥珀 極客寶寶 5天前
安全顧問反水成黑客, 靠瞎猜盜得5000萬美元的以太幣, 一個區塊鏈大盜的另類傳奇
人造器官新突破!美國科學家3D列印出會「呼吸」的肺 | Science
真香,朕在看了!