容器化 RDS:你須要瞭解資料是怎樣被寫"壞"的
Volume 使用流程大致例如以下:
生成 Volume
mount 到資料庫例項所在節點,資料庫啟動
從儲存池中獲取 Volume,掛載到指定 Node 上,並在該 Node 上啟動持久化應用 MySQL
MySQL具備重建/故障切換/又一次排程的能力
生成 Volume
mount 到資料庫例項所在節點,資料庫啟動
資料庫例項由於recreate/failover/rescheduling,被排程新節點
Volume 從原節點 unmount
mount 到新節點,資料庫啟動
相比上個場景。添加了3個環節。
複雜一點
Volume 在 mount 之前,須要“通知” Cloud Provider
Volume 在 unmount 之後,須要“通知” Cloud Provider
這兩個步驟被稱為 attach/detach。
Volume 使用流程也會更復雜一些:
生成 Volume
attach 到資料庫例項所在節點
mount 到資料庫例項所在節點,資料庫啟動
資料庫例項由於recreate/failover/rescheduling,被排程其它節點
Volume 從原節點 unmount
Volume 從原節點 detach
attach 到新節點
mount 到新節點。資料庫啟動
再複雜一點
Kubernetes 1.3 之前,以上全部的工作由 Kubelet 完畢。由Volume Plugin 適配第三方 Cloud Provider 的邏輯。
但 Kubelet 是執行在 Node 端的 Agent。
一旦 Node 重新啟動 / Crash / 網路故障,都會導致無法“通知”Cloud Provider,即便該 Volume 已經沒有應用訪問。Cloud Provider 都不會讓不論什麼節點使用它。
當然。還會有其它問題,譬如多個 Kubelet 帶來的“race condition”。
解耦 Attach-Mount-Unmount-Detach
該 Controller 被叫做 AttachDetach Controller。它執行在已有的 Controller Plane 上。
通過“volumes.kubernetes.io/controller-managed-attach-detach”啟動該特性(預設使用該特性)。
問題還沒有解決
Volume 在 mount 之前,Kubelet 會先確認是否已經 attach
Volume 在 detach 之前,AttachDetach Controller 會確認是否已經 unmount
又回到之前的問題。
Kubelet 是執行在 Node 端的 Agent,一旦 Node 重新啟動 / Crash / 網路故障,都會導致無法完畢 unmount 操作。
AttachDetach Controller 不可能無限制的等待前置動作 unmount,所以通過引數 maxWaitForUnmountDuration(預設6分鐘)解決該問題。
這破壞了 attach-mount-umount-detach 流程的序列有序,一個 RW Volume 在多個節點上掛載的可能性出現了。
資料可能被寫“壞"
“心跳”丟失的可能性非常多,譬如:
Node 重新啟動 / Crash。
Node 跟 API Server 網路故障;
Node 在高負載下,Kubelet無法獲得 CPU 時間分片;
等等
這時執行在 Controller Plane 之上的 NodeLifecycle Controller 會把該節點標記為“ConditionUnknown”。
一旦超過閾值podEvictionTimeout,NodeLifecycle Controller會對該節點上執行的 MySQL 進行驅趕,Scheduler會將 MySQL排程到其它“available”節點。
配合上 force detaching 導致的“多點掛載”,多個例項對同一個 Volume 的“Write”導致“Data Corruption”。
作者介紹:熊中哲,沃趣科技產品&研發負責人。
曾就職於阿里巴巴和百度。超過10年關係型資料庫工作經驗,眼下致力於將雲原生技術引入到關係型資料庫服務中。
原文連結:https://docs.google.com/document/d/1Q0xYOGpHvZ0LFXpzG98f6tZeWguBjgvBaGrSDiTkMXM/edit
Kubernetes零基礎進階培訓
4月20日正式上課,點選閱讀原文連結就可以報名。