Skip to main content

OpenKruise 0.10.0:新增应用弹性拓扑管理、应用防护等能力

· 阅读需要 1 分钟
Siyu Wang

本文将带你一览 v0.10.0 的新变化,其中新增的 WorkloadSpread、PodUnavailableBudget 等大颗粒特性后续还将有专文详细介绍其设计实现原理。

WorkloadSpread:旁路的应用弹性拓扑管理能力

在应用部署运维的场景下,有着多种多样的拓扑打散以及弹性的诉求。其中最常见、最基本的,就是按某种或几种拓扑水平打散,比如:

  • 应用部署需要按 node 维度打散,避免堆叠(提高容灾能力)
  • 应用部署需要按 AZ(available zone)维度打散(提高容灾能力)

这些基本的诉求,通过 Kubernetes 原生提供的 pod affinity、topology spread constraints 等能力目前都能够满足了。但在实际的生产场景下,还有着太多更加复杂的分区与弹性需求,以下举一些实际的例子:

  • 按 zone 打散时,需要指定在不同 zone 中部署的比例数,比如某个应用在 zone a、b、c 中部署的 Pod 数量比例为 1 : 1 : 2 等(由于一些现实的原因比如该应用在多个 zone 中的流量不均衡等)
  • 存在多个 zone 或不同机型的拓扑,应用扩容时,优先部署到某个 zone 或机型上,当资源不足时再部署到另一个 zone 或机型上(往后以此类推);应用缩容时,要按反向顺序,优先缩容后面 zone 或机型上的 Pod(往前以此类推)
  • 存在多个基础的节点池和弹性的节点池,应用部署时需要固定数量或比例的 Pod 部署在基础节点池,其余的都扩到弹性节点池

对于这些例子,过去一般只能将一个应用拆分为多个 Workload(比如 Deployment)来部署,才能解决应用在不同拓扑下采用不同比例数量、扩缩容优先级、资源感知、弹性选择等场景的基本问题,但还是需要 PaaS 层深度定制化,来支持对一个应用多个 Workload 的精细化管理。

针对这些问题,在 Kruise v0.10.0 版本中新增了 WorkloadSpread 资源,目前它支持配合 Deployment、ReplicaSet、CloneSet 这些 Workload 类型,来管理它们下属 Pod 的分区与弹性拓扑。 以下是一个简化的例子:

apiVersion: apps.kruise.io/v1alpha1
kind: WorkloadSpread
metadata:
name: workloadspread-demo
spec:
targetRef:
apiVersion: apps/v1 | apps.kruise.io/v1alpha1
kind: Deployment | CloneSet
name: workload-xxx
subsets:
- name: subset-a
requiredNodeSelectorTerm:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- zone-a
maxReplicas: 10 | 30%
- name: subset-b
requiredNodeSelectorTerm:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- zone-b

创建这个 WorkloadSpread 可以通过 targetRef 关联到一个 Workload 对象上,然后这个 Workload 在扩容 pod 的过程中,Pod 会被 Kruise 按上述策略注入对应的拓扑规则。这是一种旁路的注入和管理方式,本身不会干涉 Workload 对 Pod 的扩缩容、发布管理。

注意:WorkloadSpread 对 Pod 的缩容的优先级控制是通过 Pod Deletion Cost 来实现的:

  • 如果 Workload 类型是 CloneSet,则已经支持了这个 feature,可以实现缩容优先级
  • 如果 Workload 类型是 Deployment/ReplicaSet,则要求 Kubernetes version >= 1.21,且在 1.21 中要在 kube-controller-manager 上开启 PodDeletionCost 这个 feature-gate

使用 WorkloadSpread 功能,需要在 安装/升级 Kruise v0.10.0 的时候打开 WorkloadSpread 这个 feature-gate。

PodUnavailableBudget:应用可用性防护

在诸多 Voluntary Disruption 场景中 Kubernetes 原生提供的 Pod Disruption Budget(PDB) 通过限制同时中断的 Pod 数量,来保证应用的高可用性。

但还有很多场景中,即便有 PDB 防护依然将会导致业务中断、服务降级,比如:

  • 应用 owner 通过 Deployment 正在进行版本升级,与此同时集群管理员由于机器资源利用率过低正在进行 node 缩容
  • 中间件团队利用 SidecarSet 正在原地升级集群中的sidecar版本(例如:ServiceMesh envoy),同时HPA正在对同一批应用进行缩容
  • 应用 owner 和中间件团队利用 CloneSet、SidecarSet 原地升级的能力,正在对同一批 Pod 进行升级

这其实很好理解 -- PDB 只能防控通过 Eviction API 来触发的 Pod 驱逐(例如 kubectl drain驱逐node上面的所有Pod),但是对于 Pod 删除、原地升级 等很多操作是无法防护的。

在 Kruise v0.10.0 版本中新增的 PodUnavailableBudget(PUB)功能,则是对原生 PDB 的强化扩展。它包含了 PDB 自身的能力,并在此基础上增加了对更多 Voluntary Disruption 操作的防护,包括但不限于 Pod 删除、原地升级 等。

apiVersion: apps.kruise.io/v1alpha1
kind: PodUnavailableBudget
metadata:
name: web-server-pub
namespace: web
spec:
targetRef:
apiVersion: apps/v1 | apps.kruise.io/v1alpha1
kind: Deployment | CloneSet | StatefulSet | ...
name: web-server
# selector 与 targetRef 二选一配置
# selector:
# matchLabels:
# app: web-server
# 保证的最大不可用数量
maxUnavailable: 60%
# 保证的最小可用数量
# minAvailable: 40%

使用 PodUnavailableBudget 功能,需要在 安装/升级 Kruise v0.10.0 的时候打开feature-gate(两个可以选择打开一个,也可以都打开):

  • PodUnavailableBudgetDeleteGate:拦截防护 Pod 删除、驱逐 等操作
  • PodUnavailableBudgetUpdateGate:拦截防护 Pod 原地升级 等更新操作

CloneSet 支持按拓扑规则缩容

在 CloneSet 缩容(调小 replicas 数量)的时候,选择哪些 Pod 删除是有一套固定算法排序的:

  1. 未调度 < 已调度
  2. PodPending < PodUnknown < PodRunning
  3. Not ready < ready
  4. 较小 pod-deletion cost < 较大 pod-deletion cost
  5. 较大打散权重 < 较小
  6. 处于 Ready 时间较短 < 较长
  7. 容器重启次数较多 < 较少
  8. 创建时间较短 < 较长

其中,“4” 是在 Kruise v0.9.0 中开始提供的特性,用于支持用户指定删除顺序(WorkloadSpread 就是利用这个功能实现缩容优先级);而 “5” 则是当前 v0.10.0 提供的特性,即在缩容的时候会参考应用的拓扑打散来排序

  • 如果应用配置了 topology spread constraints,则 CloneSet 缩容时会按照其中的 topology 维度打散来选择 Pod 删除(比如尽量打平多个 zone 上部署 Pod 的数量)
  • 如果应用没有配置 topology spread constraints,则默认情况下 CloneSet 缩容时会按照 node 节点维度打散来选择 Pod 删除(尽量减少同 node 上的堆叠数量)

Advanced StatefulSet 支持流式扩容

为了避免在一个新 Advanced StatefulSet 创建后有大量失败的 pod 被创建出来,从 Kruise v0.10.0 版本开始引入了在 scale strategy 中的 maxUnavailable 策略:

apiVersion: apps.kruise.io/v1beta1
kind: StatefulSet
spec:
# ...
replicas: 100
scaleStrategy:
maxUnavailable: 10% # percentage or absolute number

当这个字段被设置之后,Advanced StatefulSet 会保证创建 pod 之后不可用 pod 数量不超过这个限制值。 比如说,上面这个 StatefulSet 一开始只会一次性创建 10 个 pod。在此之后,每当一个 pod 变为 running、ready 状态后,才会再创建一个新 pod 出来。

注意:这个功能只允许在 podManagementPolicy 是 Parallel 的 StatefulSet 中使用。

More

更多版本变化,请参考 release pageChangeLog