Pod Disruption Budgets(PDB)
的笔记PDB
,什么是 PDB
?PDB
可以做什么?配置创建 PDB
DemoPDB
原理简单说明不念过去,不畏将来,不负余生
对于对高可用
要求很高的一些容器化应用,例如一些有状态
的工作负载,比如数据库,分布式协调服务等, K8s 集群中 Pod 频繁的调度是不能容忍的一件事。尤其涉及到应用集群数据同步,共识,心跳
等诸多因素. 容易造成可用性降低,数据延迟甚至潜在的数据丢失。
集群中的 Pod 正常情况下不会频繁的调度,即使存在大量的超售超用,也可以通过 Qos 等手段在准入的时候控制。当然,除非有人操作,或者节点故障等一些因素的干扰。
在 k8s 中,我们把这些干扰分为两类,自愿干扰和非自愿干扰
:
非自愿干扰(Involuntary Disruptions)
的情况常见下面一些场景:
自愿干扰(Voluntary Disruptions)
的情况常见下面一些场景:
对于非自愿干扰
,常常是不可避免的,能做的只能是减轻, k8s 官方提供的一些非自愿干扰的方法:
跨机架
(使用 反亲和性) 或跨区域
(如果使用多区域集群)扩展应用,考虑拓扑分布。对于 自愿干扰
来讲,可能由集群管理员直接执行,也可能由集群管理员所使用的自动化工具执行,或者由集群托管云厂商 自动执行。k8s 提供了Pod干扰预算(PDB)
来 解决这些问题,支持运行高度可用的应用。
用最简单的话描述,Pod Disruption Budgets(PDB)
是 K8s 中的一项功能,可以确保在进行维护、升级或扩展集群
等自愿操作时,不会影响应用程序的稳定性
,从而提高可用性。
PDB 是确保 K8s 环境中高可用性的强大功能,强烈建议在生产环境中使用。
简单介绍一下 PDB
的发展历程
v1.4
版本中,开始作为Alpha
版本提供v1.6
版本中被标记为Beta
版本,使其更易于使用v1.8
,PDB 增加了更多的功能,包括针对故障域的限制和管理多个 Pod 组合的能力。v1.14
中,引入了 TopologySpreadConstraints API(拓扑分布约束),以更精确地控制 Pod 的分布,并进一步完善了 PDB 的功能。v1.21
版本中,PDB 被标记为stable
版本。这意味着其 API 已经稳定,并且与未来版本兼容可以为每个工作负载(deployment或者statefulSet)
创建一个 PodDisruptionBudget(PDB)
。
PDB 将限制在同一时间因自愿干扰导致的多副本应用中发生宕机的 Pod 数量
。
例如:
选举投票机制
的应用集群希望确保运行中的副本数永远不会低于票选所需的数量。Web 前端
可能希望确保提供负载的副本数量
永远不会低于总数的某个百分比。PDB 可以指定工作负载可以容忍的副本数量
(相当于应该有多少副本)。
例如,具有 .spec.replicas: 5
的 Deployment 在任何时间都应该有 5 个 Pod。如果 PDB
允许其在某一时刻有 4 个副本,那么驱逐 API 将允许同一时刻仅有一个(而不是两个)Pod 自愿干扰
。这里和 滚动升级机制
的优先级需要考虑一下。
由于应用的滚动升级而被删除或不可用的 Pod 确实会计入干扰预算
, 但是工作负载资源
(如 Deployment 和 StatefulSet) 在进行滚动升级时不受 PDB 的限制
。应用更新期间的故障处理方式是在对应的工作负载资源的 spec
中配置的。
确定在自发干扰时,多少实例可以在短时间内同时关闭。其中 minAvailable
表示最小活跃 pod。maxUnavailable
表示最大不活跃 Pod ,可以表示为整数或百分比
无状态的前端
:
minAvailable
值为 90%。单实例有状态应用
:
maxUnavailable=0
的 PDB。意为(Kubernetes 范畴之外的)集群操作人员需要在终止应用前与用户协商, 协商后准备停机,然后删除 PDB 表示准备接受干扰,后续再重新创建。多实例有状态应用
,如 Consul、ZooKeeper 或 etcd:
仲裁规模
,否则将出现写入失败。解决方案maxUnavailable
值为 1 (适用于不同规模的应用)。minAvailable
值为仲裁规模(例如规模为 5 时设置为 3)。(允许同时出现更多的干扰)。可重新启动的批处理任务:
用 PodDisruptionBudget 来保护应用的一般步骤:
想要保护通过内置的 Kubernetes 控制器指定的应用,这是最常见的使用场景,支持下面一些控制器
minAvailable
或 maxUnavailable
的值可以表示为整数或百分比。需要考虑指定百分比时的舍入逻辑:
如果将值指定为百分比,则可能无法映射到确切数量的 Pod。Kubernetes 采用向上取整
到最接近的整数的办法。
一个 PodDisruptionBudget 有 3 个字段:
.spec.selector
用于指定其所作用的 Pod 集合,该字段为必需字段。.spec.minAvailable
表示驱逐后仍须保证可用的 Pod 数量。即使因此影响到 Pod 驱逐 (即该条件在和 Pod 驱逐发生冲突时优先保证)。.spec.maxUnavailable
(Kubernetes 1.7 及更高的版本中可用)表示驱逐后允许不可用的 Pod 的最大数量。其值可以是绝对值或是百分比。注意事项:
PodDisruptionBudget
中只能够指定 maxUnavailable
和 minAvailable
中的一个。maxUnavailable
只能够用于控制存在相应控制器
的 Pod 的驱逐(即不受控制器控制的 Pod 不在 maxUnavailable
控制范围内)。maxUnavailable
的值设置为 0%(或 0)或设置 minAvailable 值为 100%(或等于副本数) 则会阻止所有的自愿驱逐。将无法成功地腾空(drain )运行其中一个 Pod 的节点.在下面的示例中, “所需副本” 指的是相应控制器的 scale
,控制器对 PodDisruptionBudget 所选择的 Pod 进行管理。
示例 1:设置 minAvailable 值为 5 的情况下,驱逐时需保证 PodDisruptionBudget 的 selector 选中的 Pod 中 5 个或 5 个以上处于健康状态。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
minAvailable: 5
selector:
matchLabels:
app: zookeeper
示例 2:设置 maxUnavailable 值为 30% 的情况下,只要不健康的副本数量不超过所需副本总数的 30% (取整到最接近的整数),就允许驱逐。如果所需副本的总数仅为一个
,则仍允许该单个副本中断, 从而导致不可用性实际达到 100%。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
maxUnavailable: 30%
selector:
matchLabels:
app: zookeeper
┌──[root@vms100.liruilongs.github.io]-[~]
└─$cat reviews-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: reviews-pdb
spec:
maxUnavailable: 1
selector:
matchLabels:
app: reviews
┌──[root@vms100.liruilongs.github.io]-[~]
└─$kubectl apply -f reviews-pdb.yaml
poddisruptionbudget.policy/reviews-pdb created
┌──[root@vms100.liruilongs.github.io]-[~]
└─$kubectl get poddisruptionbudgets.policy
NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
reviews-pdb N/A 1 1 9s
zk-pdb N/A 1 0 5m37s
┌──[root@vms100.liruilongs.github.io]-[~]
└─$kubectl describe poddisruptionbudgets.policy reviews-pdb
Name: reviews-pdb
Namespace: default
Max unavailable: 1
Selector: app=reviews
Status:
Allowed disruptions: 1
Current: 3
Desired: 2
Total: 3
Events: <none>
┌──[root@vms100.liruilongs.github.io]-[~]
└─$kubectl get poddisruptionbudgets.policy reviews-pdb -o yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"policy/v1","kind":"PodDisruptionBudget","metadata":{"annotations":{},"name":"reviews-pdb","namespace":"default"},"spec":{"maxUnavailable":1,"selector":{"matchLabels":{"app":"reviews"}}}}
creationTimestamp: "2023-05-06T17:29:29Z"
generation: 1
name: reviews-pdb
namespace: default
resourceVersion: "12068742"
uid: 7d0d15b4-0884-433f-af6b-44cbe9036ede
spec:
maxUnavailable: 1
selector:
matchLabels:
app: reviews
status:
conditions:
- lastTransitionTime: "2023-05-06T17:29:29Z"
message: ""
observedGeneration: 1
reason: SufficientPods
status: "True"
type: DisruptionAllowed
currentHealthy: 3
desiredHealthy: 2
disruptionsAllowed: 1
expectedPods: 3
observedGeneration: 1
部分字段解释:
关于 Pod 干扰预算(PDB) 和小伙伴们分享到这里,这里只是简单介绍了 PDB,对于原理没有太多介绍。
k8s 官网有一个有趣的例子,篇幅问题没有整理,感兴趣可以去看看,大概意思说, 通过 PDB 限制,k8s 可能会在某些时间进入阻塞状态,延迟对一些 API 调用(命令)的响应,等到符合 PDB 限制,在做成响应,优雅的处理自愿干扰对 Pod 副本的影响,重而改变干扰发生的速率,Pod 调度的影响。
关于 K8s 如何改变干扰发生的速率,除了 PDB ,还要考虑下面一些因素:
值得一说的是 ,干扰预算并不能真正保证指定数量/百分比的 Pod 一直处于运行状态,
预算只能够针对自发的驱逐提供保护
,而不能针对所有 Pod不可用的诱因
。
例如:当 Pod 集合的规模处于预算指定的最小值时,承载集合中某个 Pod 的节点发生了故障,这样就导致集合中可用 Pod 的数量低于预算指定值。
生活加油哈 ^_^
网易云看到一句话,蛮喜欢... 我曾以为总有一天,我能够改变一些什么,可当我看见她渐渐淹没在人海的时候,我才明白,我这一生除了相遇大概注定一事无成了。
© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知,这是一个开源项目,如果你认可它,不要吝啬星星哦 :)
https://kubernetes.io/zh-cn/docs/tasks/run-application/configure-pdb/
https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/disruptions/
https://medium.com/geekculture/kubernetes-pod-disruption-budgets-pdb-b74f3dade6c1