Karmada 1.3 新特性:基于污点的故障迁移

93 阅读6分钟

Karmada 在最近发布 v1.3.0 中更新了很多的新特性。其中对应用跨集群故障迁移功能进行了重新设计,实现了基于污点的故障驱逐机制,并提供平滑的故障迁移功能,可以有效保障服务迁移过程的连续性(不断服)。设计理念源于 K8s 的污点容忍机制,对于熟悉 K8s 的用户来说并没有过多的学习成本,很容易就能理解 Karmada 的 failover 的原理。Karmada 的控制器拥有众多的组件,每个组件各司其职。在 Karmada 原有的这套高度解耦的构架下很优雅地实现了 failover 的功能。

故障转移依赖 cluster-controller、cluster-stauts-controller、taint-manager、scheduler、graceful-eviction、webhook 等多个控制器协同完成故障迁移流程,其中 taint-manager 是全新的组件,它是其中的重要一环,它决定是否驱逐工作负载。我们可以把整个流程可以分为:“集群故障判定”,“负载预驱逐”,“重新调度”,“清理冗余负载”。

cluster-status 控制器来判断集群的健康状态,如果集群被判定为故障集群后,cluster 控制器会将集群标记 effect 为 “NoExecute” 的污点,随后 taint-manager 控制器根据容忍机制开始驱逐该该集群上的工作负载,最后调度器将重新调度被驱逐的工作负载到候选集群上。如果开启了优雅驱逐的特性,graceful-eviction 控制器会从队列中执行优雅驱逐的 task。

01

集群的 健康状态

在 Karmada 中,无论是 Push 还是 Pull 模式的 member 集群,都是由 cluster status 控制器持续间隔时间来探测 cluster 是否健康,并将状态信息在 cluster.status.condition 中进行更新。集群状态的 condition 为 Ready, 每次检测集群的隔间时间为 10 秒,可以通过 --cluster-status-update-frequency 的 flag 来设置。集群 Ready 的状态为 false 可以分为两种情况:

  • ClusterNotReachableReason: 集群在一个时间周期内请求没有响应。
  • ClusterNotReady:集群请求正常响应,在一个时间周期内健康检测的 endpoint 响应不正常。

相应的时间周期我们可以通过 --cluster-failure-threshold 的 flag 进行设置,默认为 30 秒。只有当以上两种请求都能正常响应,我们才认为集群是健康的状态。下面是一个不健康的集群的案例:

Status:
  Conditions:
    Last Transition Time:  2022-10-31T03:36:08Z
    Message:               cluster is not reachable
    Reason:                ClusterNotReachable
    Status:                False
    Type:                  Ready

02

集群 污点标记

目前 failover 的功能还处于 alpha 的阶段,想要使用该功能可以通过 --feature-gates=Failover=true flag 来开启。在 Karmada 中,集群的污点标记是自动的,cluster 的控制器会根据 cluster 的 condition 来为 cluster 标记污点。根据集群的状态可以分为下面几种类型的污点:

  • 当集群的 Ready 的 condition 的状态为 "False" 时:
key: cluster.karmada.io/not-ready
effect: NoSchedule
  • 当集群的 Ready 的 condition 的状态为 "Unknown" 时:
key: cluster.karmada.io/unreachable
effect: NoSchedule

以上的污点并不会被 taint-manager 处理,它只会处理带有 effectNotExecute污点的集群。为了增加集群容错的时间,集群在处于 NoSchedule 一定时间后,才会被设置为 NoExecute。可以通过 --failover-eviction-timeout 来设置时间间隔,默认时间为 5 分钟。

  • 当集群被移除的时候,也会被设置为以下的污点:
key: cluster.karmada.io/terminating
effect: NoSchedule

03

集群 污点容忍

taint-manager 是整个功能关键组件,当集群被标记 effectNoExecute 污点后,并不会立马驱逐该集群上的工作负载。它实现了污点容忍的机制,它会根据该集群的 RB/CRB 资源上设置的容忍参数进行判断,具体可以分为三种情况:

  • 需要立马驱逐:没有设置污点容忍或者没有容忍时间。
  • 永不驱逐:容忍了所有的污点。
  • 一定时间后进行驱逐:karmada-webhook 为每一个 PropagationPolicy/ClusterPropagationPolicy 自动设置默认的容忍时间,默认为 10 分钟。可以通过 --default-not-ready-toleration-seconds--default-unreachable-toleration-seconds flag 自定义容忍时间。
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: nginx-propagation
  namespace: default
spec:
  placement:
    clusterTolerations:
    - effect: NoExecute
      key: cluster.karmada.io/not-ready
      operator: Exists
      tolerationSeconds: 600
    - effect: NoExecute
      key: cluster.karmada.io/unreachable
      operator: Exists
      tolerationSeconds: 600
  resourceSelectors:
  - apiVersion: apps/v1
    kind: Deployment
    name: nginx
    namespace: default

04

重新调度

被驱逐的资源重新调度的流程,还是由 scheduler 来执行, taint-manager 在确定故障集群满足驱逐条件后,会在 RB/CRB 资源中把污点集群从可用集群列表中移除。Scheduler 控制器会重新触发调度流程。不过在 scheduler 中新增了 taint_toleration 插件,由这个插件来控制资源能否被污点集群所容忍。除此之外,还需要满足以下两点限制条件:

  • 重新调度的资源,还是需要满足传播策略的限制,例如:ClusterAffinity 或者 SpreadConstraints。
  • 在故障迁移整个过程中,之前已经被调度到 Ready 集群的资源会被保留。

05

优雅驱逐

在真实场景中,如果当集群为判断为故障集群,应用还没有被迁移到可用集群就被删除了,可能会造成服务不可用,这对用户的体验上是不友好的。为了避免这个问题,Karmada 设计了优雅驱逐功能,整个过程可以保障在驱逐过程中业务不中断,让用户无感知。目前这个功能还处于 alpha 的阶段,需要通过 -–GracefulEviction=true flag 开启。优雅驱逐由一个新的控制器 graceful-eviction 来完成的,它的执行过程可以分为:

  • taint-manager 通过污点容忍机制确定需要驱逐的应用,将创建一个 GracefulEviction 的 task,这个 task 将设置到 RB/CRB 的 spec.GracefulEvictionTasks 队列中。
  • scheduler 执行了重新调度的流程,在候选集群中选择集群去调度驱逐的工作负载。
  • graceful-eviction controller 确定了重新调度结果后,并检查资源的健康状态。在超过间隔时间后才将故障集群资源移除。这个间隔时间可以通过 --graceful-eviction-timeout 时间设置,默认 10 分钟。最后将这个 task 从队列移除。

06

对比 V1.3 之前的故障迁移

在 Karmada 1.3 版本之前的 failover 功能,只依赖了 cluster-status 和 scheduler 两个控制器就完成了整个流程。Schduler 监听到 cluster 状态为 NotReady 后,就启动了重调度的流程。启动的时机取决于 cluster-status 的状态判断,从这个过程中我们可以看出它并没有任何的集群容错能力,这对于真实的生产环境可能会造成频繁跨集群迁移带来的诸多风险。

Karmada 基于污点的优雅驱逐机制的设计得非常合理,也非常符合 Karmada 当前的架构。不过目前还处于一个 alpha 的阶段,还需要一段时间来检验功能可靠性。


本文作者

陈文

现任「DaoCloud 道客」 云原生开发工程师