openkruise cloneset里提供了两种Lifecycle hookpreDelete
和inPlaceUpdate
其中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例子来实现这个过程