自定义Kubernetes调度程序来编排高可用性应用程序

只要愿意遵守规则,在Kubernetes上进行部署和乘飞机旅行就可以很愉快。通常,事情会“正常工作”。但是,如果有兴趣与必须生存的鳄鱼一起旅行,或对必须保持可用状态的数据库进行扩展,则情况可能会变得更加复杂。为此,甚至可能更容易构建自己的飞机或数据库。除了爬行动物之外,扩展高可用性的有状态系统也不是一件容易的事。

扩展任何系统都有两个主要组成部分:

  1. 添加或删除系统将在其上运行的基础结构,以及
  2. 确保系统知道如何处理自己添加和删除的其它实例。

大多数无状态系统(例如Web服务器),在创建时不需要知道对等对象的。有状态的系统(包括CockroachDB之类的数据库)必须与对等实例进行协调,并在数据周围进行重新整理。幸运的是,CockroachDB能处理数据的重新分发和复制。棘手的部分是通过确保数据和实例分布在许多故障域(可用性区域)中,能够容忍这些操作中的故障。

Kubernetes的职责之一是将“资源”(例如磁盘或容器)放入群集中,并满足所要求的约束。例如:“必须在可用区域A”,或“不能将我与另一个Pod放置在同一节点上”。

除了这些约束之外,Kubernetes还提供Statefulsets(状态集),该状态集为Pod提供身份,以及“跟随”这些已标识Pod的持久性存储。StatefulSet中的身份由Pod名称末尾的递增整数处理。该整数必须始终是连续的:在StatefulSet中,如果容器1和3存在,则容器2也必须存在。

CockroachCloud将CockroachDB的每个区域作为StatefulSet,部署在其Kubernetes集群中。在本文中,将研究一个单独的区域,一个StatefulSet和一个Kubernetes集群,该集群分布在至少三个可用性区域中。

一个三节点的CockroachCloud集群如下所示:

向集群添加资源时,将它们分布在区域之间。为了获得最快的用户体验,同时添加了所有Kubernetes节点,然后扩展了StatefulSet。

无论Pod分配给Kubernetes节点的顺序如何,都满足反亲和性anti-affinity。此示例中,分别将Pod 0、1和2分配给区域A,B和C,分别以不同的顺序将Pod 3和4分配给区域B和A。由于吊舱仍放置在不同的区域中,因此仍然可以满足抗亲和力anti-affinity要求。

从集群中删除资源,逆序执行这些操作。

首先缩小StatefulSet,然后从群集中删除缺少CockroachDB pod的所有节点。

小为n的StatefulSet中的pod的id必须在range内[0,n)。将StatefulSet按m缩小,Kubernetes会从最高序数开始,向最低序数移动m吊舱,倒序添加。考虑下面的群集拓扑:

当从该群集中删除序号5到3时,状态集statefulset将在所有3个可用性区域中继续存在。

Kubernetes的调度程序并不能像最初预期的那样,保证上面的位置。

以下方面的综合了解,导致这种错误的原因。

考虑以下拓扑:

这些窗格是按顺序创建的,分布在集群中的所有可用性区域中。当序数5到3终止时,此群集将失去在C区的存在!

自动化将删除节点A-2,B-2和C-2。使CRDB-1处于非计划状态,持久卷积仅在最初创建区域中可用。

为了更正后一个问题,现在采用“狩猎和啄食hunt and peck”的方法从群集中删除计算机。不会从群集中盲目删除Kubernetes节点,而只会删除没有CockroachDB pod的节点。更艰巨的任务是纠缠Kubernetes调度程序。

头脑风暴会议为我们提供了3个选择:

1.升级到kubernetes 1.18并利用Pod拓扑扩展约束

虽然这似乎是一个完美的解决方案,公共云中的两个最常见的托管Kubernetes服务(EKS和GKE)尚无法使用Kubernetes 1.18。此外,pod拓扑扩展约束仍然是1.18中beta功能,这意味着即使v1.18可用,也不能保证在托管群集中也可以使用它。整个过程让人想起了Internet Explorer 8仍然存在时检查caniuse.com的过程

2.为每个区域部署一个有状态集。

与其在所有可用区域上分布一个StatefulSet,不如在每个区域具有节点亲和力的单个StatefulSet,将允许对区域拓扑进行手动控制。一直认为这是一种选择,这使其特别具有吸引力。最终,决定放弃此选项,因为这将需要对代码库进行大修,在现有客户集群上执行迁移,将是一项同样艰巨的任务。

3.编写一个自定义的Kubernetes调度程序。

编写自己的自定义Kubernetes调度程序。部署并运行了概念验证后, Kubernetes的调度程序,负责将持久卷映射到其调度的Pod。输出kubectl get events,还有另一个系统在起作用。在寻找负责存储声明映射的组件的过程中,发现了kube-scheduler插件系统。下一个POC是一个Filter插件,按Pod顺序确定合适的可用性区域,并且可以完美地工作!

自定义调度程序插件是开源的,可在所有CockroachCloud集群中运行。控制StatefulSet Pod的调度方式,充满信心地进行扩展。一旦GKE和EKS中提供了Pod拓扑扩展约束,可能会考虑淘汰插件,但是维护开销却出乎意料的低。更妙的是:该插件的实现与业务逻辑正交。部署或撤消它,就像更改schedulerName的StatefulSet定义中的字段一样简单。

自定义Kubernetes调度程序来编排高可用性应用程序的更多相关文章

  1. [转帖]Kubernetes及容器编排的总体介绍【译】

    Kubernetes及容器编排的总体介绍[译] 翻译自The New Stack<Kubernetes 生态环境>作者:JANAKIRAM MSV和 KRISHNAN SUBRAMANIA ...

  2. 三小时学会Kubernetes:容器编排详细指南

    三小时学会Kubernetes:容器编排详细指南 如果谁都可以在三个小时内学会Kubernetes,银行为何要为这么简单的东西付一大笔钱? 如果你心存疑虑,我建议你不妨跟着我试一试!在完成本文的学习后 ...

  3. OpenStack宣布用Kubernetes重写底层编排引擎

    Mirantis是OpenStack的主要贡献者,今天他宣布将使用Kubernetes作为底层编排引擎重写其私有云平台.我们认为这是推进OpenStack和Kubernetes 社区伟大的一步. Op ...

  4. 用集装箱装ASP。带有Docker和Azure Kubernetes服务的NET Core应用程序

    介绍 曾经有一个单一软件应用程序的时代,整个应用程序被打包并部署在作为单个进程运行的单个服务器上.我们都知道,在这个模型中,单点故障可能会导致整个应用程序崩溃. 微服务体系结构的发展是为了解决单片应用 ...

  5. asp.net项目发布网上-当前自定义错误设置禁止远程查看应用程序

    早上服务器的系统突然出错了,悲剧~ ==============异常信息:============================== 服务器上出现应用程序错误.此应用程序的当前自定义错误设置禁止远程 ...

  6. 通过用 .NET 生成自定义窗体设计器来定制应用程序

    通过用 .NET 生成自定义窗体设计器来定制应用程序 https://www.microsoft.com/china/MSDN/library/netFramework/netframework/Cu ...

  7. kustomize 模版自由的配置&&自定义kubernetes工具

    kustomize 是一个可以方便我们基于模版配置,自定义kubernetes 的工具,类似kompose,但是个人觉得kompose 更灵活点,而且使用上更方便 安装 mac brew instal ...

  8. kubernetes(k8s)容器编排工具基础概念

    Kubernetes (K8s): 中文社区:https://www.kubernetes.org.cn/replication-controller-kubernetes 官网:https://ku ...

  9. uniapp自定义顶部搜索框兼容微信小程序

    zhuanzai:  uniapp自定义顶部搜索框兼容微信小程序 自定义组件 navbarvue (胶囊底部高度 - 状态栏的高度) + (胶囊顶部高度 - 状态栏内的高度) = 导航栏的高度 < ...

随机推荐

  1. 限制pyqt5应用程序 只允许打开一次

    起因 pyqt5程序创建桌面快捷方式后,多次单击图标 会打开多个UI界面,这种情况肯定是不允许的! 解决 if __name__ == '__main__': try: app = QtWidgets ...

  2. 关于Spring Data JPA 多表查询 返回自定义Vo的问题记录

    这两天开了一个新项目,使用SpringBoot+SpringData,  刚做了一个小功能,都是一张表的操作没什么问题,今天设计到了两张表联查,两张表各取了几个字段,组合成了一个vo, 当我用原生sq ...

  3. pwn 好的联系网站

    https://pwnable.kr/ https://w3challs.com/challenges/wargame http://overthewire.org/wargames/ http:// ...

  4. hdu4287 水题

    题意:          水题,就是给你一些单词,和一些按键记录,问打出下面的那些单词,每一个按键记录一共按了多少次. 思路:       直接把每个单词的每一位转换成数字,然后再把每个单词转换的数字 ...

  5. 死磕到底RecyclerView | RecyclerView 的滚动是怎么实现的?

    RecyclerView 是一个展示列表的控件,其中的子控件可以被滚动.这是怎么实现的?以走查源码的方式一探究竟. 切入点:滚动事件 阅读源码时,如何在浩瀚的源码中选择合适的切入点很重要,选好了能少走 ...

  6. 6 JDBC

    JDBC 理解图 需要mysql包 下载官网:https://downloads.mysql.com/archives/c-j/ 第一个JDBC项目 创建一个java项目,一路next 导入jar包 ...

  7. CDN 加速配置

    1 https://cloud.tencent.com/document/product/228/3149 2 https://cloud.tencent.com/document/product/4 ...

  8. python函数默认值只初始化一次

    当在函数中定义默认值时,值初始化只会进行一次,就是执行到def methodname时执行.看下面代码: from datetime import datetime def test(t=dateti ...

  9. 使用基于centos7 dbus问题总结

    Authorization not available. Check if polkit Authorization not available. Check if polkit service is ...

  10. 使用 parted 命令可以查看系统采用什么类型的分区表 gpt/mbr/msdos/ext/ext/ext2/ext3/ext4

      Linux磁盘表示方式 Linux以字母标识磁盘的个数 a:第一块 b:第二块 Linux用数字标识分区:1-4标识主分区或扩展分区 逻辑分区从5开始 例如:sda.sda1.sda2 低级格式化 ...