openkruise 生命周期钩子之inPlaceUpdate Hook(一)

550 阅读2分钟

openkruise cloneset里提供了两种Lifecycle hookpreDeleteinPlaceUpdate

其中preDelete比较好理解,而inPlaceUpdate比较绕。

官方文档是这么说的:

每个 CloneSet 管理的 Pod 会有明确所处的状态,在 Pod label 中的 lifecycle.apps.kruise.io/state 标记:

  • Normal:正常状态
  • PreparingUpdate:准备原地升级
  • Updating:原地升级中
  • Updated:原地升级完成
  • PreparingDelete:准备删除

如果设置 inPlaceUpdate.markPodNotReady=true

  • Kruise 将会在 Pod 进入 PreparingUpdate 状态时,将 KruisePodReady 这个 Pod Condition 设置为 False, Pod 将变为 NotReady
  • Kruise 将会尝试将 KruisePodReady 这个 Pod Condition 设置回 True

当 CloneSet 原地升级一个 Pod 时:

  • 升级之前,如果定义了 lifecycle hook 且 Pod 符合 inPlaceUpdate 条件,则将 Pod 状态改为 PreparingUpdate
  • 等用户 controller 完成任务去掉 label/finalizer、Pod 不符合 inPlaceUpdate 条件后,kruise 将 Pod 状态改为 Updating 并开始升级
  • 升级完成后,如果定义了 lifecycle hook 且 Pod 不符合 inPlaceUpdate 条件,将 Pod 状态改为 Updated
  • 等用户 controller 完成任务加上 label/finalizer、Pod 符合 inPlaceUpdate 条件后,kruise 将 Pod 状态改为 Normal 并判断为升级成功

实际测试了一下用我自己的话再说一遍:

没有hook的情况,只有这两个状态,

要么你看到正好在升级中

  • Updating:原地升级中

要么你看到时已经升级完了

  • Normal:正常状态

我们加上inPlaceUpdate hook,其中一个方法是在template里打上labels

  # 或者也可以通过 label 定义
  template:
    metadata:
      labels:
        app: guestbook
        hook.example.kruise.io/unready-blocker: "true"
    spec:

光打上label并没有什么卵用,需要通过通过lifecycle语法开启hook功能,

注意两边label内容要一样才会生效。

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
spec:
  # 或者也可以通过 label 定义
  lifecycle:
    inPlaceUpdate:
      labelsHandler:
        hook.example.kruise.io/unready-blocker: "true"

现在开始原地升级,比如改一个镜像版本

这时状态会卡在 hook第一个状态:

  • PreparingUpdate:准备原地升级,

这时我们需要继续往下走,可以将template里的labels

设为hook.example.kruise.io/unready-blocker: "false",或者直接删掉这个labels,反正就跟下面lifecycle设的不一样就可以了。

这时继续运行:

  • Updating:原地升级中
  • Updated:原地升级完成

又停住了,此时状态是Updated

这时候我们要继续往下走,可以将template里的labels

设为hook.example.kruise.io/unready-blocker: "true",就是跟下面lifecycle设的一样就可以了

再继续运行,状态转变成:

  • Normal:正常状态

最终完成了整个lifecycle过程

小结

第一部分,很啰嗦地口述了整个过程

接下来第二部分将会直接了当的用一个controller例子来实现这个过程