zoukankan      html  css  js  c++  java
  • 容器化 RDS:你须要了解数据是怎样被写"坏"的

    版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/79877076

    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

  • 相关阅读:
    flume杀掉重启
    Tomcat访问日志浅析 (转)
    httpclient Accept-Encoding 乱码
    解决Maven报Plugin execution not covered by lifecycle configuration
    mahout基于Hadoop的CF代码分析(转)
    hadoop Mahout中相似度计算方法介绍(转)
    nginx配置文件结构,语法,配置命令解释
    nginx 中文和英文资料
    使用异步 I/O 大大提高应用程序的性能
    nginx AIO机制与sendfile机制
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/9907359.html
Copyright © 2011-2022 走看看