系列目录
目标读者:
想要构建高可用应用的应用所有者, 因此需要知道 pod 会发生哪些类型的中断
想要执行自动化 (比如升级和自动扩容) 的集群管理员.
自愿和非自愿的中断
pod 不会自动消息, 除非有人 (可能是一个人或者一个控制器) 把它销毁了, 或者出现无法避免的硬件或者系统软件错误.
我们把这些称作非自愿的不可避免的应用中断.
以下是示例:
用于支撑节点的机会出现硬件故障
集群管理员误操作把 VM(实例)删除了
虚拟机故障导致 VM 实例消失
kernel panic
由于网络分区导致集群节点消失
由于资源耗尽导致 pod 被驱离
除了资源耗尽外, 其它情况大部分读者应该都非常熟悉, 它们并不是 kubernetes 特有的.
我们称其它的情况为自愿中断. 这包括集群管理员或者应用拥有者采取的动作. 应用拥有者采取的典型动作有:
删除了管理 pod 的 deployment 或者其它控制器
更新了 deployment 的 pod 模板导致重启
直接删除 pod(比如误删除)
集群管理员的动作有如下:
排干 node 以便升级或修复
排干一个 node 以便对集群缩容
从节点中删除一个 pod 以便可以做其它的事情
这些动作可能由集群管理者直接触发, 或者自动触发, 或者有集群服务提供者触发
询问集群管理员或者云服务提供商或者查询文档来确定是否触发了自愿中止. 如果以上都没有发生, 你可以跳过创建 Pod Disruption Budgets
注意: 并非所有的自愿中断都被 Pod Disruption Budgets 约束, 比如删除 deployment 或者 pod 会绕过 Pod Disruption Budgets
处理中断
以下是一些可以减轻非自愿中断的办法
确保 pod 请求需要的资源
如果你想要高可用, 制作程序副本集
如果想要更高可用性, 使用跨区域集群部署应用
自愿中断的频率根据实际情况往往也是不同的. 在一个基础的集群上, 可能根本不会有自愿的中断. 但是集群管理员或者服务提供商可能会运行一些额外的服务导致自愿中断. 比如滚动更新可能会导致自愿中断. 一些自动集群扩容为了防止完整节点碎片化也会自愿中断. 集群管理员或者服务提供商应该用文档把可能导致的自愿中断写出来, 以便查询.
kubernetes 提供了这样一种特性, 当高频率自愿中断发生时仍然能够保证集群的高可用性, 我们称之为 Disruption Budgets
Disruption Budgets 有些资料上翻译为中断预算, 但是更多的是没有翻译, 大家只要知道它的大致意思就行了, 这里也不做翻译
Disruption Budgets 如何工作
应用所有者可以为每个应用创建一个 PodDisruptionBudget(PDB)对象. PDB 限制一个包含副本集的集群由于自愿中断而同时宕掉的 pod 的个数. 例如, 一个基于仲裁投票的应用想要保证运行的副本数永远不会低于某个数量以便仲裁. 一个 web 前端想要保证运行中的副本数不会低于某一比例.
集群管理员和服务提供商应当通过遵守 Pod Disruption Budgets 的 Eviction API 而不是直接删除 pod 或者 deployment. 例如可以使用 kubectl drain
当集群管理员想通过 kubectl drain 命令来排干一个节点. 命令会尝试排干节点机器上的所有 pod. 驱离请求可能会暂时被拒绝, 命令会周期性的重新发送失败请求直到所有 pod 都终止, 或者达到了设定的超时时间.
PDB 规定了副本集可以容忍的副本集的数量(实际上是能容忍的最小值), 这是相对于它期望的数量而言的. 比如一个有. spec.replicas: 5 的 deployment 希望在任何时候都有五个副本, 如果 PDB 允许有 4 个副本运行, 则 Eviction API 允许同一时刻有一个副本中断, 而不是 2 个.
期望的副本数量由 pod 控制器通过 pod 的. spec.replicas 计算得出, 控制器通过. metadata.ownerReferences 被 pod 发现
PDB 不能阻止非自愿的中断发生, 但是它们会被计入预算
由于被删除或者更新导到不可用的 pod 也会计入预算, 但是控制器 (比如 deployment,stateful-set) 滚动更新时不会被 PDB 限制, 滚动更新导致的失败会计入控制器的 spec 里
当一个 pod 通过 eviction API 被驱离, 它会优雅的中止(请看里的 terminationGracePeriodSeconds)
PDB 示例
比如集群有从 node-1 到 node-3 这样的 3 个节点. 集群中运行着一些应用, 其中一个有三个副本, 叫作 pod-a,pod-b 和 pod-c. 此外还有一个无关的, 包含 PDB 的 pod 称作 pod-x, 它们的初始分布情况如下:
node-1 | node-2 | node-3 |
---|---|---|
pod-a available | pod-b available | pod-c available |
pod-x available |
同一副本集的三个节点是一个 deployment 的一部分, 它们共享一个 PDB, 要求它们三个中至少有 2 个同时运行着.
假如集群管理员想要重启节点以便修复一个内核 bug, 集群管理员首先尝试通过 kubectl drain 命令来排干 node-1 节点. 命令会尝试把 pod-a 和 pod-x 驱离节点 node-1. 命令马上执行成功, 上面的 pod 同时进入 terminating 状态. 现在集群处于如下状态:
node-1 draining | node-2 | node-3 |
---|---|---|
pod-a terminating | pod-b available | pod-c available |
pod-x terminating |
deployment 发现其中一个节点终止了. 因此它创建了一个替代节点叫作 pod-d, 由于 node-1 被封锁, 因此它会落到其它节点. 其它的控制器也会创建一个 pod-y 来替代 pod-x
注意, 对一 StatefulSet,pod-a 可能叫作 pod-1, 需要在被替代之前完全终止, 它仍然叫作 pod-a, 但是 PID 可能不同了. 除此之外(pod 的名字的区别), 这个例子也适用于 StatefulSet.
现在集群处于如下状态:
node-1 draining | node-2 | node-3 |
---|---|---|
pod-a terminating | pod-b available | pod-c available |
pod-x terminating | pod-d starting | pod-y |
在某一个时间点, node-a 上的节点被终止, 现在集群的状态如下
node-1 drained | node-2 | node-3 |
---|---|---|
pod-b available | pod-c available | |
pod-d starting | pod-y |
此时, 如果一个没有耐心的集群管理员尝试排干 node-2 或者 node-3, 排干命令会被阻止, 因为只有两个可用的节点, 它的 PDB 要求至少运行 2 个, 过一段时间, pod-d 变得可用
node-1 drained | node-2 | node-3 |
---|---|---|
pod-b available | pod-c available | |
pod-d available | pod-y |
此时, 如果集群管理员尝试排干 node-2, 排干命令会以一定顺序驱离上面的两个 pod, 比如说先是 pod-b 然后是 pod-d, 它会成功驱离 pod-b. 但是当尝试驱离 pod-d 的时候会被拒绝, 因为这会导致 deployment 只有一个可用 pod
pod-b 被驱离后并不会马上在其它节点上落地开始工作, 也就是这个节点的替代节点并不能马上工作, 此时如果再驱离 pod-d 会导致只有 pod-c 是可用的, 因此会被拒绝.
deployment 创建了一个 pod-b 的替代叫作 pod-e, 由于集群没有足够资源来调度 pod-e 因此此时 drain 会再入陷入阻塞. 集群最终的状态如下:
node-1 drained | node-2 | node-3 | no node |
---|---|---|---|
pod-b available | pod-c available | pod-e pending | |
pod-d available | pod-y |
此时, 集群管理员需要添加一个节点来让升级继续.
你可以看到基于以下原因, kubernetes 怎样控制中断的速率:
集群需要多少个副本
优雅地中止一个实例需要多长时间
一个新的实例启动需要多长时间
控制器的类型
集群资源容量
分离集群拥有者和应用拥有者的角色
通常, 把集群管理者和应用拥有者看作是对对方知之甚少不同的角色是有用的. 这种职责分离在以下情形是有意义的:
多个开发团队使用同一个集群, 这时候有一个中立的专家角色
当一些第三方工具或者服务被用来做集群的自动化管理工作.
怎样在集群中执行有中断性的动作
如果你是集群管理员, 由于节点或者系统软件升级, 你可能需要对集群的所有节点执行可能产生中断的动作, 有以下选项:
升级过程中接受宕机时间
故障转移到一个完整的副本集群中. 这能够保证没有宕机时间, 但是可能需要花费高价钱来复制节点和花费人力来编排切换
使用能容忍中断的程序和使用 PDB
没有宕机时间
最小量资源复制
允许更多的集群自动化管理
编写能容忍中断的程序是很有技巧的, 但是容忍中断的工作很大部分是与支持自动扩容和容忍非自愿中断是重叠的
来源: https://www.cnblogs.com/tylerzhou/p/10982978.html