K8s 容器PodDisruptionBudget 主动驱逐保护

前言

在 Kubernetes 中,为了保证业务不中断或业务SLA不降级,需要将应用进行集群化部署。通过PodDisruptionBudget 控制器可以设置应用POD集群处于运行状态最低个数,也可以设置应用POD集群处于运行状态的最低百分比,这样可以保证在主动销毁应用POD的时候,不会一次性销毁太多的应用POD,从而保证业务不中断或业务SLA不降级。

PodDisruptionBudget 简介

Pod Disruption Budget (pod 中断 预算) 简称PDB,含义其实是终止pod前通过 labelSelector 机制获取正常运行的pod数目的限制,目的是对自愿中断的保护措施。

Kubernetes version >= 1.7 才支持 PodDisruptionBudget

PDB 应用场景

节点维护或升级时 ( kubectl drain )

注意:如果 Node 状态处于 not ready,PDB 是不会生效,因为 PDB 只能针对自愿中断生效,什么叫 自愿中断 下文介绍。

自愿中断和非自愿中断

非自愿中断

Pod 不会消失,直到有人(人类或控制器)将其销毁,或者当出现不可避免的硬件或系统软件错误。

我们把这些不可避免的情况称为应用的非自愿性中断,例如:

  • 后端节点物理机的硬件故障
  • 集群管理员错误地删除虚拟机(实例)
  • 云提供商或管理程序故障使虚拟机消失
  • 内核恐慌(kernel panic)
  • 节点由于集群网络分区而从集群中消失
  • 由于节点资源不足而将容器逐出

除资源不足的情况外,大多数用户应该都熟悉以下这些情况;它们不是特定于 Kubernetes 的。

自愿中断

包括由应用程序所有者发起的操作和由集群管理员发起的操作,我们称这些情况为自愿中断

典型的应用程序所有者操作包括

  • 删除管理该 pod 的 Deployment 或其他控制器
  • 更新了 Deployment 的 pod 模板导致 pod 重启
  • 直接删除 pod(意外删除)

集群管理员操作包括

  • 排空(drain)节点进行修复或升级。
  • 从集群中排空节点以缩小集群(了解集群自动调节)。
  • 从节点中移除一个 pod,以允许其他 pod 使用该节点。

这些操作可能由集群管理员直接执行,也可能由集群管理员或集群托管提供商自动执行。

PDB 关键参数与注意事项

spec.minAvailable:表示发生自愿中断的过程中,要保证至少可用的Pods数或者百分比
spec.maxUnavailable:表示发生自愿中断的过程中,要保证最大不可用的Pods数或者百分比

上面配置只能用来对应 Deployment,RS,RC,StatefulSet的Pods,推荐优先使用 .spec.maxUnavailable。

在极端的情况下,比如将maxUnavailable设置成0,或者设置成100%,那么就表示不能进行kubectl drain操作。同理将minAvailable设置成100%,或者设置成应用POD集群最大副本数,也表示不能进行kubectl drain操作。

注意:

  • 同一个 PDB Object 中不能同时定义 .spec.minAvailable 和 .spec.maxUnavailable。
  • 前面提到,应用滚动更新时Pod的delete和unavailable虽然也属于自愿中断,但是实际上滚动更新有自己的策略控制(marSurge 和 maxUnavailable),因此PDB不会干预这个过程。
  • PDB 只能保证自愿中断时的副本数,比如 evict pod过程中刚好满足 .spec.minAvailable 或 .spec.maxUnavailable,这时某个本来正常的Pod突然因为Node Down(非自愿中断)挂了,那么这个时候实际Pods数就比PDB中要求的少了,因此PDB不是万能的!

在使用上,如果设置 .spec.minAvailable 为 100% 或者 .spec.maxUnavailable 为 0%,意味着会完全阻止 evict pods 的过程( Deployment和StatefulSet的滚动更新除外 )。

PDB 例子

定义 minAvailable

1
2
3
4
5
6
7
8
9
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
minAvailable: 2 #定义存活的zookeeper的pod最少为2个
selector:
matchLabels:
app: zookeeper

定义 maxUnavailable

1
2
3
4
5
6
7
8
9
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
maxUnavailable: 1 #定义非存活的zookeeper的pod最多为1个
selector:
matchLabels:
app: zookeeper

创建资源清单

对于PodDisruptionBudget对象,无法直接进行更新操作,只能通过删除和重新创建来完成对PodDisruptionBudget对象的更新。

1
# kubectl apply -f zk-pdb.yaml

查看状态

对于PodDisruptionBudget对象,无法直接进行更新操作,只能通过删除和重新创建来完成对PodDisruptionBudget对象的更新。

1
2
3
# kubectl get pdb
NAME MIN-AVAILABLE ALLOWED-DISRUPTIONS AGE
zk-pdb 2 1 7s

查看详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# kubectl describe pdb pdb-demo
Name: zk-pdb
Namespace: default
Min available: 2
Selector: app=zookeeper
Status:
Allowed disruptions: 0
Current: 0
Desired: 2
Total: 0
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal NoPods 2m58s (x53 over 28m) controllermanager No matching pods found

通过下面命令查看PodDisruptionBudget对象的详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# kubectl get poddisruptionbudgets zk-pdb-o yaml

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
...
status:
currentHealthy: 3
desiredHealthy: 3
disruptedPods: null
disruptionsAllowed: 1
expectedPods: 3
observedGeneration: 1

官方参考文档https://kubernetes.io/docs/tasks/run-application/configure-pdb/

-------------本文结束感谢您的阅读-------------