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日正式上课,点击阅读原文链接就可以报名。