1. 程式人生 > >容器化 RDS:你須要瞭解資料是怎樣被寫"壞"的

容器化 RDS:你須要瞭解資料是怎樣被寫"壞"的

640?wxfrom=5&wx_lazy=1


容器化 RDS 系列文章:


即使不使用 Kubernetes,在編排持久化 workload 時,你都須要瞭解編排框架和 Cloud Provider 是怎樣互動的。資料又是怎樣被寫"壞"的。下面描寫敘述的場景具有普遍意義,也是必須要回答的問題。

640?wxfrom=5&wx_lazy=1


簡單場景

640


從儲存池中獲取 RW Volume,掛載到指定 Node 上,並在該 Node 上啟動持久化應用 MySQL。

640


Volume 使用流程大致例如以下:

640


  • 生成 Volume

  • mount 到資料庫例項所在節點,資料庫啟動


略微複雜一點

640


  • 從儲存池中獲取 Volume,掛載到指定 Node 上,並在該 Node 上啟動持久化應用 MySQL

  • MySQL具備重建/故障切換/又一次排程的能力


640


Volume 使用流程也會更復雜一些:

640


  • 生成 Volume

  • mount 到資料庫例項所在節點,資料庫啟動

  • 資料庫例項由於recreate/failover/rescheduling,被排程新節點

  • Volume 從原節點 unmount

  • mount 到新節點,資料庫啟動


相比上個場景。添加了3個環節。
複雜一點

640


大多數情況下 Kubernetes 不會直接管理 bare-metal。而是執行在第三方 Cloud Provider 上(GCE/Azure/AWS/OpenStack),Kubernetes 會作為 Volume 的使用者,由 Cloud Provider 負責 Volume 的生命週期,所以之前的 mount/unmount 會有所變化:
  • Volume 在 mount 之前,須要“通知” Cloud Provider

  • Volume 在 unmount 之後,須要“通知” Cloud Provider


假設Volume 在 unmount 之後,沒有“通知” Cloud Provider,Cloud Provider 會保證該 Volume 不會被掛載到其它 Node 上,“多點掛載”在大多數場景下會導致“Data Corruption”。所以加入這兩個步驟是有必要的,Cloud Provider 須要感知 Volume 的“使用場景”(譬如在 GCE 環境,是不同意RW Volume 同一時候掛載到多個節點)。

這兩個步驟被稱為 attach/detach。


640


Volume 使用流程也會更復雜一些:

640


  • 生成 Volume

  • attach 到資料庫例項所在節點

  • mount 到資料庫例項所在節點,資料庫啟動

  • 資料庫例項由於recreate/failover/rescheduling,被排程其它節點

  • Volume 從原節點 unmount

  • Volume 從原節點 detach

  • attach 到新節點

  • mount 到新節點。資料庫啟動


再複雜一點

640


須要繼續思考一個問題:誰來“通知”Cloud Provider?
Kubernetes 1.3 之前,以上全部的工作由 Kubelet 完畢。由Volume Plugin 適配第三方 Cloud Provider 的邏輯。

640


但 Kubelet 是執行在 Node 端的 Agent。
一旦 Node 重新啟動 / Crash / 網路故障,都會導致無法“通知”Cloud Provider,即便該 Volume 已經沒有應用訪問。Cloud Provider 都不會讓不論什麼節點使用它。
當然。還會有其它問題,譬如多個 Kubelet 帶來的“race condition”。


解耦 Attach-Mount-Unmount-Detach

640


流程不變,Kubernetes 1.3 之後。嘗試使用專門的 Controller 管理 Attach 和 Detach 操作。


640


該 Controller 被叫做 AttachDetach Controller。它執行在已有的 Controller Plane 上。

640


通過“volumes.kubernetes.io/controller-managed-attach-detach”啟動該特性(預設使用該特性)。
問題還沒有解決

640


attach-mount-umount-detach流程的序列有序是保障資料不被寫“壞”的基礎。
  • Volume 在 mount 之前,Kubelet 會先確認是否已經 attach

  • Volume 在 detach 之前,AttachDetach Controller 會確認是否已經 unmount


所以。假設 Volume 不能被 Kubelet 成功地 unmount,AttachDetach Controller 不能進行 detach 操作。
又回到之前的問題。
Kubelet 是執行在 Node 端的 Agent,一旦 Node 重新啟動 / Crash / 網路故障,都會導致無法完畢 unmount 操作。 
AttachDetach Controller 不可能無限制的等待前置動作 unmount,所以通過引數 maxWaitForUnmountDuration(預設6分鐘)解決該問題。


640


超過 maxWaitForUnmountDuration。AttachDetach Controller 會啟動 force detaching。


這破壞了 attach-mount-umount-detach 流程的序列有序,一個 RW Volume 在多個節點上掛載的可能性出現了。


資料可能被寫“壞"

640


Kuberetes 叢集的正常執行,依賴 API Server 跟 Kubelet 的正常互動,能夠理解為”心跳”。


640


“心跳”丟失的可能性非常多,譬如:
  1. Node 重新啟動 / Crash。

  2. Node 跟 API Server 網路故障;

  3. Node 在高負載下,Kubelet無法獲得 CPU 時間分片;

  4. 等等


換句話說,一旦“心跳”丟失,叢集無法推斷 Node 的真實狀態。

這時執行在 Controller Plane 之上的 NodeLifecycle Controller 會把該節點標記為“ConditionUnknown”。
一旦超過閾值podEvictionTimeout,NodeLifecycle Controller會對該節點上執行的 MySQL 進行驅趕,Scheduler會將 MySQL排程到其它“available”節點。
配合上 force detaching 導致的“多點掛載”,多個例項對同一個 Volume 的“Write”導致“Data Corruption”。


640

總結

640


Kubernetes 是極好的編排平臺。前提是我們須要深入的瞭解它。
作者介紹:熊中哲,沃趣科技產品&研發負責人。

曾就職於阿里巴巴和百度。超過10年關係型資料庫工作經驗,眼下致力於將雲原生技術引入到關係型資料庫服務中。
原文連結:https://docs.google.com/document/d/1Q0xYOGpHvZ0LFXpzG98f6tZeWguBjgvBaGrSDiTkMXM/edit

Kubernetes零基礎進階培訓

640


本次培訓內容包含:容器原理、Docker架構及工作原理、Docker網路與儲存方案、Harbor、Kubernetes架構、元件、核心機制、外掛、核心模組、Kubernetes網路與儲存、監控、日誌、二次開發以及實踐經驗等。 點選瞭解詳細培訓內容


640?


4月20日正式上課,點選閱讀原文連結就可以報名。